]> Zhao Yanbai Git Server - minix.git/commitdiff
Termcap update, replacing elvis by nvi. 41/241/1
authorLionel Sambuc <lionel@minix3.org>
Tue, 22 Jan 2013 11:03:53 +0000 (12:03 +0100)
committerLionel Sambuc <lionel.sambuc@gmail.com>
Thu, 24 Jan 2013 06:44:38 +0000 (07:44 +0100)
Removing elvis, importing nvi, ctags, updating libedit.

Change-Id: I881eb04d2dc64cf112facd992de1114e1a59107f

491 files changed:
commands/Makefile
commands/elvis/.descr [deleted file]
commands/elvis/Doc.sh [deleted file]
commands/elvis/Knownbug.txt [deleted file]
commands/elvis/Makedoc [deleted file]
commands/elvis/Makefile [deleted file]
commands/elvis/Man.sh [deleted file]
commands/elvis/Readme.txt [deleted file]
commands/elvis/blk.c [deleted file]
commands/elvis/cmd1.c [deleted file]
commands/elvis/cmd2.c [deleted file]
commands/elvis/config.h [deleted file]
commands/elvis/ctags.c [deleted file]
commands/elvis/ctype.c [deleted file]
commands/elvis/ctype.h [deleted file]
commands/elvis/curses.c [deleted file]
commands/elvis/curses.h [deleted file]
commands/elvis/cut.c [deleted file]
commands/elvis/elvprsv.c [deleted file]
commands/elvis/elvrec.c [deleted file]
commands/elvis/ex.c [deleted file]
commands/elvis/fmt.c [deleted file]
commands/elvis/input.c [deleted file]
commands/elvis/main.c [deleted file]
commands/elvis/misc.c [deleted file]
commands/elvis/modify.c [deleted file]
commands/elvis/move1.c [deleted file]
commands/elvis/move2.c [deleted file]
commands/elvis/move3.c [deleted file]
commands/elvis/move4.c [deleted file]
commands/elvis/move5.c [deleted file]
commands/elvis/opts.c [deleted file]
commands/elvis/prsvunix.c [deleted file]
commands/elvis/recycle.c [deleted file]
commands/elvis/redraw.c [deleted file]
commands/elvis/ref.c [deleted file]
commands/elvis/regexp.c [deleted file]
commands/elvis/regexp.h [deleted file]
commands/elvis/regsub.c [deleted file]
commands/elvis/system.c [deleted file]
commands/elvis/tinyprnt.c [deleted file]
commands/elvis/tinytcap.c [deleted file]
commands/elvis/tio.c [deleted file]
commands/elvis/tmp.c [deleted file]
commands/elvis/unix.c [deleted file]
commands/elvis/vars.c [deleted file]
commands/elvis/vcmd.c [deleted file]
commands/elvis/vi.c [deleted file]
commands/elvis/vi.h [deleted file]
dist/nvi/Changes [new file with mode: 0644]
dist/nvi/LICENSE [new file with mode: 0644]
dist/nvi/README [new file with mode: 0644]
dist/nvi/README.1st [new file with mode: 0644]
dist/nvi/README.DB3 [new file with mode: 0644]
dist/nvi/TODO [new file with mode: 0644]
dist/nvi/build.unix/README [new file with mode: 0644]
dist/nvi/build.unix/README.LynxOS [new file with mode: 0644]
dist/nvi/build.unix/README.Solaris [new file with mode: 0644]
dist/nvi/catalog/Makefile [new file with mode: 0644]
dist/nvi/catalog/README [new file with mode: 0644]
dist/nvi/catalog/dump.c [new file with mode: 0644]
dist/nvi/catalog/dutch.base [new file with mode: 0644]
dist/nvi/catalog/dutch.owner [new file with mode: 0644]
dist/nvi/catalog/english.owner [new file with mode: 0644]
dist/nvi/catalog/french.base [new file with mode: 0644]
dist/nvi/catalog/german.base [new file with mode: 0644]
dist/nvi/catalog/german.owner [new file with mode: 0644]
dist/nvi/catalog/ru_RU.KOI8-R.base [new file with mode: 0644]
dist/nvi/catalog/ru_RU.KOI8-R.owner [new file with mode: 0644]
dist/nvi/catalog/spanish.base [new file with mode: 0644]
dist/nvi/catalog/spell.ok [new file with mode: 0644]
dist/nvi/catalog/swedish.base [new file with mode: 0644]
dist/nvi/catalog/swedish.owner [new file with mode: 0644]
dist/nvi/cl/README.signal [new file with mode: 0644]
dist/nvi/cl/cl.h [new file with mode: 0644]
dist/nvi/cl/cl_bsd.c [new file with mode: 0644]
dist/nvi/cl/cl_funcs.c [new file with mode: 0644]
dist/nvi/cl/cl_main.c [new file with mode: 0644]
dist/nvi/cl/cl_read.c [new file with mode: 0644]
dist/nvi/cl/cl_screen.c [new file with mode: 0644]
dist/nvi/cl/cl_term.c [new file with mode: 0644]
dist/nvi/cl/extern.h [new file with mode: 0644]
dist/nvi/clib/bsearch.c [new file with mode: 0644]
dist/nvi/clib/env.c [new file with mode: 0644]
dist/nvi/clib/gethostname.c [new file with mode: 0644]
dist/nvi/clib/iswblank.c [new file with mode: 0644]
dist/nvi/clib/memchr.c [new file with mode: 0644]
dist/nvi/clib/memset.c [new file with mode: 0644]
dist/nvi/clib/mkstemp.c [new file with mode: 0644]
dist/nvi/clib/mmap.c [new file with mode: 0644]
dist/nvi/clib/snprintf.c [new file with mode: 0644]
dist/nvi/clib/strdup.c [new file with mode: 0644]
dist/nvi/clib/strpbrk.c [new file with mode: 0644]
dist/nvi/clib/strsep.c [new file with mode: 0644]
dist/nvi/clib/strtol.c [new file with mode: 0644]
dist/nvi/clib/strtoul.c [new file with mode: 0644]
dist/nvi/clib/vsnprintf.c [new file with mode: 0644]
dist/nvi/common/api.c [new file with mode: 0644]
dist/nvi/common/args.h [new file with mode: 0644]
dist/nvi/common/common.h [new file with mode: 0644]
dist/nvi/common/conv.c [new file with mode: 0644]
dist/nvi/common/conv.h [new file with mode: 0644]
dist/nvi/common/cut.c [new file with mode: 0644]
dist/nvi/common/cut.h [new file with mode: 0644]
dist/nvi/common/db.c [new file with mode: 0644]
dist/nvi/common/db.h [new file with mode: 0644]
dist/nvi/common/db1.c [new file with mode: 0644]
dist/nvi/common/dbinternal.h [new file with mode: 0644]
dist/nvi/common/delete.c [new file with mode: 0644]
dist/nvi/common/dldb.c [new file with mode: 0644]
dist/nvi/common/exf.c [new file with mode: 0644]
dist/nvi/common/exf.h [new file with mode: 0644]
dist/nvi/common/extern.h [new file with mode: 0644]
dist/nvi/common/gs.c [new file with mode: 0644]
dist/nvi/common/gs.h [new file with mode: 0644]
dist/nvi/common/key.c [new file with mode: 0644]
dist/nvi/common/key.h [new file with mode: 0644]
dist/nvi/common/log.c [new file with mode: 0644]
dist/nvi/common/log.h [new file with mode: 0644]
dist/nvi/common/log4.c [new file with mode: 0644]
dist/nvi/common/main.c [new file with mode: 0644]
dist/nvi/common/mark.c [new file with mode: 0644]
dist/nvi/common/mark.h [new file with mode: 0644]
dist/nvi/common/mem.h [new file with mode: 0644]
dist/nvi/common/msg.c [new file with mode: 0644]
dist/nvi/common/msg.h [new file with mode: 0644]
dist/nvi/common/multibyte.h [new file with mode: 0644]
dist/nvi/common/nothread.c [new file with mode: 0644]
dist/nvi/common/options.awk [new file with mode: 0644]
dist/nvi/common/options.c [new file with mode: 0644]
dist/nvi/common/options.h [new file with mode: 0644]
dist/nvi/common/options_f.c [new file with mode: 0644]
dist/nvi/common/pthread.c [new file with mode: 0644]
dist/nvi/common/put.c [new file with mode: 0644]
dist/nvi/common/recover.c [new file with mode: 0644]
dist/nvi/common/screen.c [new file with mode: 0644]
dist/nvi/common/screen.h [new file with mode: 0644]
dist/nvi/common/search.c [new file with mode: 0644]
dist/nvi/common/seq.c [new file with mode: 0644]
dist/nvi/common/seq.h [new file with mode: 0644]
dist/nvi/common/trace.c [new file with mode: 0644]
dist/nvi/common/util.c [new file with mode: 0644]
dist/nvi/common/util.h [new file with mode: 0644]
dist/nvi/common/util2.c [new file with mode: 0644]
dist/nvi/common/vi.src [new file with mode: 0644]
dist/nvi/common/vi_auto.c [new file with mode: 0644]
dist/nvi/common/vi_auto.h [new file with mode: 0644]
dist/nvi/common/vi_rec.c [new file with mode: 0644]
dist/nvi/dist/ExtUtils/Embed.pm [new file with mode: 0644]
dist/nvi/dist/INSTALL [new file with mode: 0644]
dist/nvi/dist/Makefile.am [new file with mode: 0644]
dist/nvi/dist/Makefile.in [new file with mode: 0644]
dist/nvi/dist/acconfig.h [new file with mode: 0644]
dist/nvi/dist/aclocal.m4 [new file with mode: 0644]
dist/nvi/dist/compile [new file with mode: 0644]
dist/nvi/dist/config.guess [new file with mode: 0644]
dist/nvi/dist/config.h.in [new file with mode: 0644]
dist/nvi/dist/config.sub [new file with mode: 0644]
dist/nvi/dist/configure [new file with mode: 0644]
dist/nvi/dist/configure.in [new file with mode: 0644]
dist/nvi/dist/depcomp [new file with mode: 0644]
dist/nvi/dist/distrib [new file with mode: 0644]
dist/nvi/dist/export [new file with mode: 0644]
dist/nvi/dist/findconfig [new file with mode: 0644]
dist/nvi/dist/install-sh [new file with mode: 0644]
dist/nvi/dist/ltconfig [new file with mode: 0644]
dist/nvi/dist/ltmain.sh [new file with mode: 0644]
dist/nvi/dist/m4/gtk.m4 [new file with mode: 0644]
dist/nvi/dist/missing [new file with mode: 0644]
dist/nvi/dist/mkinstalldirs [new file with mode: 0644]
dist/nvi/dist/pathnames.h.in [new file with mode: 0644]
dist/nvi/dist/port.h.in [new file with mode: 0644]
dist/nvi/dist/recover.in [new file with mode: 0644]
dist/nvi/dist/script [new file with mode: 0644]
dist/nvi/dist/spell.ok [new file with mode: 0644]
dist/nvi/dist/stamp-h.in [new file with mode: 0644]
dist/nvi/docs/README [new file with mode: 0644]
dist/nvi/docs/edit/Makefile [new file with mode: 0644]
dist/nvi/docs/edit/edittut.ms [new file with mode: 0644]
dist/nvi/docs/exref/Makefile [new file with mode: 0644]
dist/nvi/docs/exref/ex.rm [new file with mode: 0644]
dist/nvi/docs/exref/ex.summary [new file with mode: 0644]
dist/nvi/docs/vi.man/Makefile [new file with mode: 0644]
dist/nvi/docs/vi.man/spell.ok [new file with mode: 0644]
dist/nvi/docs/vi.man/vi.1 [new file with mode: 0644]
dist/nvi/docs/vi.ref/Makefile [new file with mode: 0644]
dist/nvi/docs/vi.ref/ex.cmd.texi [new file with mode: 0644]
dist/nvi/docs/vi.ref/ref.texi [new file with mode: 0644]
dist/nvi/docs/vi.ref/set.opt.texi [new file with mode: 0644]
dist/nvi/docs/vi.ref/spell.ok [new file with mode: 0644]
dist/nvi/docs/vi.ref/vi.cmd.texi [new file with mode: 0644]
dist/nvi/docs/vi.ref/vi.texi [new file with mode: 0644]
dist/nvi/docs/vitut/Makefile [new file with mode: 0644]
dist/nvi/docs/vitut/vi.apwh.ms [new file with mode: 0644]
dist/nvi/docs/vitut/vi.chars [new file with mode: 0644]
dist/nvi/docs/vitut/vi.in [new file with mode: 0644]
dist/nvi/docs/vitut/vi.summary [new file with mode: 0644]
dist/nvi/ex/ex.awk [new file with mode: 0644]
dist/nvi/ex/ex.c [new file with mode: 0644]
dist/nvi/ex/ex.h [new file with mode: 0644]
dist/nvi/ex/ex_abbrev.c [new file with mode: 0644]
dist/nvi/ex/ex_append.c [new file with mode: 0644]
dist/nvi/ex/ex_args.c [new file with mode: 0644]
dist/nvi/ex/ex_argv.c [new file with mode: 0644]
dist/nvi/ex/ex_at.c [new file with mode: 0644]
dist/nvi/ex/ex_bang.c [new file with mode: 0644]
dist/nvi/ex/ex_cd.c [new file with mode: 0644]
dist/nvi/ex/ex_cmd.c [new file with mode: 0644]
dist/nvi/ex/ex_cscope.c [new file with mode: 0644]
dist/nvi/ex/ex_def.h [new file with mode: 0644]
dist/nvi/ex/ex_delete.c [new file with mode: 0644]
dist/nvi/ex/ex_display.c [new file with mode: 0644]
dist/nvi/ex/ex_edit.c [new file with mode: 0644]
dist/nvi/ex/ex_equal.c [new file with mode: 0644]
dist/nvi/ex/ex_file.c [new file with mode: 0644]
dist/nvi/ex/ex_filter.c [new file with mode: 0644]
dist/nvi/ex/ex_global.c [new file with mode: 0644]
dist/nvi/ex/ex_init.c [new file with mode: 0644]
dist/nvi/ex/ex_join.c [new file with mode: 0644]
dist/nvi/ex/ex_map.c [new file with mode: 0644]
dist/nvi/ex/ex_mark.c [new file with mode: 0644]
dist/nvi/ex/ex_mkexrc.c [new file with mode: 0644]
dist/nvi/ex/ex_move.c [new file with mode: 0644]
dist/nvi/ex/ex_open.c [new file with mode: 0644]
dist/nvi/ex/ex_perl.c [new file with mode: 0644]
dist/nvi/ex/ex_preserve.c [new file with mode: 0644]
dist/nvi/ex/ex_print.c [new file with mode: 0644]
dist/nvi/ex/ex_put.c [new file with mode: 0644]
dist/nvi/ex/ex_quit.c [new file with mode: 0644]
dist/nvi/ex/ex_read.c [new file with mode: 0644]
dist/nvi/ex/ex_screen.c [new file with mode: 0644]
dist/nvi/ex/ex_script.c [new file with mode: 0644]
dist/nvi/ex/ex_set.c [new file with mode: 0644]
dist/nvi/ex/ex_shell.c [new file with mode: 0644]
dist/nvi/ex/ex_shift.c [new file with mode: 0644]
dist/nvi/ex/ex_source.c [new file with mode: 0644]
dist/nvi/ex/ex_stop.c [new file with mode: 0644]
dist/nvi/ex/ex_subst.c [new file with mode: 0644]
dist/nvi/ex/ex_tag.c [new file with mode: 0644]
dist/nvi/ex/ex_tcl.c [new file with mode: 0644]
dist/nvi/ex/ex_txt.c [new file with mode: 0644]
dist/nvi/ex/ex_undo.c [new file with mode: 0644]
dist/nvi/ex/ex_usage.c [new file with mode: 0644]
dist/nvi/ex/ex_util.c [new file with mode: 0644]
dist/nvi/ex/ex_version.c [new file with mode: 0644]
dist/nvi/ex/ex_visual.c [new file with mode: 0644]
dist/nvi/ex/ex_write.c [new file with mode: 0644]
dist/nvi/ex/ex_yank.c [new file with mode: 0644]
dist/nvi/ex/ex_z.c [new file with mode: 0644]
dist/nvi/ex/extern.h [new file with mode: 0644]
dist/nvi/ex/script.h [new file with mode: 0644]
dist/nvi/ex/tag.h [new file with mode: 0644]
dist/nvi/ex/version.h [new file with mode: 0644]
dist/nvi/gtk/extern.h [new file with mode: 0644]
dist/nvi/gtk/gtk.h [new file with mode: 0644]
dist/nvi/gtk/gtk_main.c [new file with mode: 0644]
dist/nvi/gtk/gtkvi.c [new file with mode: 0644]
dist/nvi/gtk/gtkvi.h [new file with mode: 0644]
dist/nvi/gtk/gtkviscreen.c [new file with mode: 0644]
dist/nvi/gtk/gtkviscreen.h [new file with mode: 0644]
dist/nvi/gtk/gtkviwindow.c [new file with mode: 0644]
dist/nvi/gtk/gtkviwindow.h [new file with mode: 0644]
dist/nvi/include/bitstring.h [new file with mode: 0644]
dist/nvi/include/sys/queue.h [new file with mode: 0644]
dist/nvi/ip/extern.h [new file with mode: 0644]
dist/nvi/ip/ip_funcs.c [new file with mode: 0644]
dist/nvi/ip/ip_main.c [new file with mode: 0644]
dist/nvi/ip/ip_read.c [new file with mode: 0644]
dist/nvi/ip/ip_screen.c [new file with mode: 0644]
dist/nvi/ip/ip_term.c [new file with mode: 0644]
dist/nvi/ip/vipc.pl [new file with mode: 0644]
dist/nvi/ipc/extern.h [new file with mode: 0644]
dist/nvi/ipc/ip.h [new file with mode: 0644]
dist/nvi/ipc/ip_run.c [new file with mode: 0644]
dist/nvi/ipc/ip_send.c [new file with mode: 0644]
dist/nvi/ipc/ip_trans.c [new file with mode: 0644]
dist/nvi/ipc/ipc.awk [new file with mode: 0644]
dist/nvi/ipc/ipc_cmd.c [new file with mode: 0644]
dist/nvi/ipc/ipc_def.h [new file with mode: 0644]
dist/nvi/ipc/ipc_gen.c [new file with mode: 0644]
dist/nvi/ipc/ipc_method.c [new file with mode: 0644]
dist/nvi/ipc/vipc.awk [new file with mode: 0644]
dist/nvi/motif/extern.h [new file with mode: 0644]
dist/nvi/motif/m_cde.c [new file with mode: 0644]
dist/nvi/motif/m_main.c [new file with mode: 0644]
dist/nvi/motif/nvi.xbm [new file with mode: 0644]
dist/nvi/motif/nvi.xpm [new file with mode: 0644]
dist/nvi/motif_l/TODO [new file with mode: 0644]
dist/nvi/motif_l/extern.h [new file with mode: 0644]
dist/nvi/motif_l/m_copypaste.c [new file with mode: 0644]
dist/nvi/motif_l/m_func.c [new file with mode: 0644]
dist/nvi/motif_l/m_menu.c [new file with mode: 0644]
dist/nvi/motif_l/m_motif.h [new file with mode: 0644]
dist/nvi/motif_l/m_options.c [new file with mode: 0644]
dist/nvi/motif_l/m_prompt.c [new file with mode: 0644]
dist/nvi/motif_l/m_ruler.c [new file with mode: 0644]
dist/nvi/motif_l/m_search.c [new file with mode: 0644]
dist/nvi/motif_l/m_tags.c [new file with mode: 0644]
dist/nvi/motif_l/m_util.c [new file with mode: 0644]
dist/nvi/motif_l/m_vi.c [new file with mode: 0644]
dist/nvi/motif_l/vi_mextern.h [new file with mode: 0644]
dist/nvi/motif_l/xtabbed.c [new file with mode: 0644]
dist/nvi/nvi2netbsd [new file with mode: 0644]
dist/nvi/perl_api/VI.pod [new file with mode: 0644]
dist/nvi/perl_api/extern.h [new file with mode: 0644]
dist/nvi/perl_api/nviperl.pod [new file with mode: 0644]
dist/nvi/perl_api/perl.xs [new file with mode: 0644]
dist/nvi/perl_api/perlsfio.c [new file with mode: 0644]
dist/nvi/perl_api/typemap [new file with mode: 0644]
dist/nvi/perl_scripts/forall.pl [new file with mode: 0644]
dist/nvi/perl_scripts/make.pl [new file with mode: 0644]
dist/nvi/perl_scripts/tk.pl [new file with mode: 0644]
dist/nvi/perl_scripts/wc.pl [new file with mode: 0644]
dist/nvi/regex/COPYRIGHT [new file with mode: 0644]
dist/nvi/regex/WHATSNEW [new file with mode: 0644]
dist/nvi/regex/cclass.h [new file with mode: 0644]
dist/nvi/regex/cname.h [new file with mode: 0644]
dist/nvi/regex/engine.c [new file with mode: 0644]
dist/nvi/regex/re_format.7 [new file with mode: 0644]
dist/nvi/regex/regcomp.c [new file with mode: 0644]
dist/nvi/regex/regerror.c [new file with mode: 0644]
dist/nvi/regex/regex.3 [new file with mode: 0644]
dist/nvi/regex/regex.h [new file with mode: 0644]
dist/nvi/regex/regex2.h [new file with mode: 0644]
dist/nvi/regex/regexec.c [new file with mode: 0644]
dist/nvi/regex/regfree.c [new file with mode: 0644]
dist/nvi/regex/utils.h [new file with mode: 0644]
dist/nvi/tcl_api/extern.h [new file with mode: 0644]
dist/nvi/tcl_api/tcl.c [new file with mode: 0644]
dist/nvi/tcl_scripts/errors.tcl [new file with mode: 0644]
dist/nvi/tcl_scripts/gnats.tcl [new file with mode: 0644]
dist/nvi/tcl_scripts/mailprocs.tcl [new file with mode: 0644]
dist/nvi/tcl_scripts/wc.tcl [new file with mode: 0644]
dist/nvi/vi/extern.h [new file with mode: 0644]
dist/nvi/vi/getc.c [new file with mode: 0644]
dist/nvi/vi/v_at.c [new file with mode: 0644]
dist/nvi/vi/v_ch.c [new file with mode: 0644]
dist/nvi/vi/v_cmd.c [new file with mode: 0644]
dist/nvi/vi/v_delete.c [new file with mode: 0644]
dist/nvi/vi/v_event.c [new file with mode: 0644]
dist/nvi/vi/v_ex.c [new file with mode: 0644]
dist/nvi/vi/v_increment.c [new file with mode: 0644]
dist/nvi/vi/v_init.c [new file with mode: 0644]
dist/nvi/vi/v_itxt.c [new file with mode: 0644]
dist/nvi/vi/v_left.c [new file with mode: 0644]
dist/nvi/vi/v_mark.c [new file with mode: 0644]
dist/nvi/vi/v_match.c [new file with mode: 0644]
dist/nvi/vi/v_paragraph.c [new file with mode: 0644]
dist/nvi/vi/v_put.c [new file with mode: 0644]
dist/nvi/vi/v_redraw.c [new file with mode: 0644]
dist/nvi/vi/v_replace.c [new file with mode: 0644]
dist/nvi/vi/v_right.c [new file with mode: 0644]
dist/nvi/vi/v_screen.c [new file with mode: 0644]
dist/nvi/vi/v_scroll.c [new file with mode: 0644]
dist/nvi/vi/v_search.c [new file with mode: 0644]
dist/nvi/vi/v_section.c [new file with mode: 0644]
dist/nvi/vi/v_sentence.c [new file with mode: 0644]
dist/nvi/vi/v_status.c [new file with mode: 0644]
dist/nvi/vi/v_txt.c [new file with mode: 0644]
dist/nvi/vi/v_ulcase.c [new file with mode: 0644]
dist/nvi/vi/v_undo.c [new file with mode: 0644]
dist/nvi/vi/v_util.c [new file with mode: 0644]
dist/nvi/vi/v_word.c [new file with mode: 0644]
dist/nvi/vi/v_xchar.c [new file with mode: 0644]
dist/nvi/vi/v_yank.c [new file with mode: 0644]
dist/nvi/vi/v_z.c [new file with mode: 0644]
dist/nvi/vi/v_zexit.c [new file with mode: 0644]
dist/nvi/vi/vi.c [new file with mode: 0644]
dist/nvi/vi/vi.h [new file with mode: 0644]
dist/nvi/vi/vs_line.c [new file with mode: 0644]
dist/nvi/vi/vs_msg.c [new file with mode: 0644]
dist/nvi/vi/vs_refresh.c [new file with mode: 0644]
dist/nvi/vi/vs_relative.c [new file with mode: 0644]
dist/nvi/vi/vs_smap.c [new file with mode: 0644]
dist/nvi/vi/vs_split.c [new file with mode: 0644]
distrib/sets/lists/minix/mi
etc/mtree/NetBSD.dist.base
lib/Makefile
lib/libedit/Makefile
lib/libedit/README [deleted file]
lib/libedit/TEST/Makefile [new file with mode: 0644]
lib/libedit/TEST/rl1.c [new file with mode: 0644]
lib/libedit/TEST/tc1.c [new file with mode: 0644]
lib/libedit/TEST/wtc1.c [new file with mode: 0644]
lib/libedit/chared.c [new file with mode: 0644]
lib/libedit/chared.h [new file with mode: 0644]
lib/libedit/chartype.c [new file with mode: 0644]
lib/libedit/chartype.h [new file with mode: 0644]
lib/libedit/common.c [new file with mode: 0644]
lib/libedit/complete.c [deleted file]
lib/libedit/config.h [new file with mode: 0644]
lib/libedit/editline.3 [new file with mode: 0644]
lib/libedit/editline.c [deleted file]
lib/libedit/editline.h [deleted file]
lib/libedit/editrc.5 [new file with mode: 0644]
lib/libedit/el.c [new file with mode: 0644]
lib/libedit/el.h [new file with mode: 0644]
lib/libedit/eln.c [new file with mode: 0644]
lib/libedit/emacs.c [new file with mode: 0644]
lib/libedit/filecomplete.c [new file with mode: 0644]
lib/libedit/filecomplete.h [new file with mode: 0644]
lib/libedit/hist.c [new file with mode: 0644]
lib/libedit/hist.h [new file with mode: 0644]
lib/libedit/histedit.h [new file with mode: 0644]
lib/libedit/history.c [new file with mode: 0644]
lib/libedit/keymacro.c [new file with mode: 0644]
lib/libedit/keymacro.h [new file with mode: 0644]
lib/libedit/makelist [new file with mode: 0644]
lib/libedit/map.c [new file with mode: 0644]
lib/libedit/map.h [new file with mode: 0644]
lib/libedit/parse.c [new file with mode: 0644]
lib/libedit/parse.h [new file with mode: 0644]
lib/libedit/prompt.c [new file with mode: 0644]
lib/libedit/prompt.h [new file with mode: 0644]
lib/libedit/read.c [new file with mode: 0644]
lib/libedit/read.h [new file with mode: 0644]
lib/libedit/readline.c [new file with mode: 0644]
lib/libedit/readline/Makefile [new file with mode: 0644]
lib/libedit/readline/readline.h [new file with mode: 0644]
lib/libedit/refresh.c [new file with mode: 0644]
lib/libedit/refresh.h [new file with mode: 0644]
lib/libedit/search.c [new file with mode: 0644]
lib/libedit/search.h [new file with mode: 0644]
lib/libedit/shlib_version [new file with mode: 0644]
lib/libedit/sig.c [new file with mode: 0644]
lib/libedit/sig.h [new file with mode: 0644]
lib/libedit/sys.h [new file with mode: 0644]
lib/libedit/sysunix.c [deleted file]
lib/libedit/terminal.c [new file with mode: 0644]
lib/libedit/terminal.h [new file with mode: 0644]
lib/libedit/testit.c [deleted file]
lib/libedit/tokenizer.c [new file with mode: 0644]
lib/libedit/tty.c [new file with mode: 0644]
lib/libedit/tty.h [new file with mode: 0644]
lib/libedit/unix.h [deleted file]
lib/libedit/vi.c [new file with mode: 0644]
man/man1/Makefile
man/man1/ctags.1 [deleted file]
man/man1/elvis.1 [deleted file]
man/man1/elvrec.1 [deleted file]
man/man1/fmt.1 [deleted file]
man/man1/ref.1 [deleted file]
man/man1x/Makefile
man/man1x/elvis.1x [deleted file]
man/man8/Makefile
man/man8/elvprsv.8 [deleted file]
releasetools/nbsd_ports
usr.bin/Makefile
usr.bin/ctags/C.c [new file with mode: 0644]
usr.bin/ctags/Makefile [new file with mode: 0644]
usr.bin/ctags/ctags.1 [new file with mode: 0644]
usr.bin/ctags/ctags.c [new file with mode: 0644]
usr.bin/ctags/ctags.h [new file with mode: 0644]
usr.bin/ctags/fortran.c [new file with mode: 0644]
usr.bin/ctags/lisp.c [new file with mode: 0644]
usr.bin/ctags/print.c [new file with mode: 0644]
usr.bin/ctags/test/ctags.test [new file with mode: 0644]
usr.bin/ctags/tree.c [new file with mode: 0644]
usr.bin/ctags/yacc.c [new file with mode: 0644]
usr.bin/nvi/Makefile [new file with mode: 0644]
usr.bin/nvi/Makefile.inc [new file with mode: 0644]
usr.bin/nvi/build/Makefile [new file with mode: 0644]
usr.bin/nvi/build/config.h [new file with mode: 0644]
usr.bin/nvi/build/pathnames.h [new file with mode: 0644]
usr.bin/nvi/build/port.h [new file with mode: 0644]
usr.bin/nvi/catalog/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/edit/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/edit/edit.vindex [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/exref/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vi.ref/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vi.ref/ex.cmd.roff [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vi.ref/merge.awk [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vi.ref/set.opt.roff [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vi.ref/vi.cmd.roff [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vi.ref/vi.ref [new file with mode: 0644]
usr.bin/nvi/docs/USD.doc/vitut/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/ev [new file with mode: 0644]
usr.bin/nvi/docs/help [new file with mode: 0644]
usr.bin/nvi/docs/info/Makefile [new file with mode: 0644]
usr.bin/nvi/docs/internals/autowrite [new file with mode: 0644]
usr.bin/nvi/docs/internals/context [new file with mode: 0644]
usr.bin/nvi/docs/internals/gdb.script [new file with mode: 0644]
usr.bin/nvi/docs/internals/input [new file with mode: 0644]
usr.bin/nvi/docs/internals/openmode [new file with mode: 0644]
usr.bin/nvi/docs/internals/quoting [new file with mode: 0644]
usr.bin/nvi/docs/internals/structures [new file with mode: 0644]
usr.bin/nvi/recover/Makefile [new file with mode: 0644]
usr.bin/nvi/recover/virecover [new file with mode: 0644]
usr.bin/nvi/recover/virecover.8 [new file with mode: 0644]

index ffd193b64cf99bcb2007755f158fdef5e1471425..4c2c94c0937a6bb56932fa658ee2230e51792014 100644 (file)
@@ -8,7 +8,7 @@ SUBDIR= add_route arp ash at backup banner basename btrace cal \
        comm compress cp crc cron crontab cut \
        dd decomp16 DESCRIBE devmand devsize df dhcpd \
        dhrystone diff dirname diskctl dumpcore \
-       eject elvis env expand factor fbdctl \
+       eject env expand factor fbdctl \
        find finger fingerd fix fold format fortune fsck.mfs \
        ftp101 gcore gcov-pull getty grep head hexdump host \
        hostaddr id ifconfig ifdef \
diff --git a/commands/elvis/.descr b/commands/elvis/.descr
deleted file mode 100644 (file)
index 2dcfedf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Lightweight vi
diff --git a/commands/elvis/Doc.sh b/commands/elvis/Doc.sh
deleted file mode 100755 (executable)
index 88479f1..0000000
+++ /dev/null
@@ -1,3314 +0,0 @@
-echo x - cflags.ms
-sed '/^X/s///' > cflags.ms << '/'
-X.Go 9 "CFLAGS"
-X.PP
-X\*E uses many preprocessor symbols to control compilation.
-XSome of these control the sizes of buffers and such.
-XThe "-DNO_XXXX" options remove small sets of related features.
-X.PP
-XMost \*E users will probably want to keep all features available.
-XMinix-PC users, though, will have to sacrifice some sets because otherwise
-X\*E would be too bulky to compile.
-XThe "asld" phase of the compiler craps out.
-X.IP "-DM_SYSV, -Dbsd, -DTOS, -DCOHERENT, -Damiga"
-XThese flags tell the compiler that \*E is being compiled for
-XSystem-V UNIX, BSD UNIX, Atari TOS, Coherent, or AmigaDos, respectively.
-XFor other systems, the config.h file can generally figure it out automatically.
-X.IP -DRAINBOW
-XFor MS-DOS systems, this causes support for the DEC Rainbow to be compiled
-Xinto \*E.
-X.IP -DS5WINSIZE
-XSome versions of SysV UNIX don't support support the "winsize"
-Xstyle of screen-size testing,
-Xso elvis ignores window size changes by default.
-X.IP
-XHowever, many of the newer SysV systems defines "winsize" in the
-Xfile "/usr/include/sys/ptem.h".
-XIf your SysV system has "winsize" then you should add
-X-DS5SWINSIZE to the CFLAGS setting.
-X.IP -DTERMIOS
-XPOSIX is a SysV-derived specification which uses a terminal control
-Xpackage called "termios", instead of "termio".
-XSome other SysV systems may also use termios.
-XYou can make elvis uses termios instead of the more common termio
-Xby adding -DTERMIOS to CFLAGS.
-X(Note: This hasn't been tested very well.)
-X.IP -DNBUFS=\fInumber\fP
-X\*E keeps most of your text in a temporary file;
-Xonly a small amount is actually stored in RAM.
-XThis flag allows you to control how much of the file can be in RAM at any time.
-XThe default is 5 blocks, and the minimum is 3 blocks.
-X(See the -DBLKSIZE flag, below.)
-X.IP
-XMore RAM allows global changes to happen a little faster.
-X f you're just making many small changes in one section of a file, though,
-Xextra RAM won't help much.
-X.IP -DBLKSIZE=\fInumber\fP
-XThis controls the size of blocks that \*E uses internally.
-XThe value of BLKSIZE must be a power of two.
-XEvery time you double BLKSIZE, you quadruple the size of a text file that
-X\*E can handle, but you also cause the temporary file to grow faster.
-XFor MS-DOS, Coherent, and Minix-PC, the default value is 1024, which allows
-Xyou to edit files up to almost 512K bytes long.
-XFor all other systems, the default value is 2048, which allows you to edit
-Xfiles that are nearly 2 megabytes long.
-X.IP
-XThe BLKSIZE also determines the maximum line length, and a few other limits.
-XBLKSIZE should be either 256, 512, 1024, or 2048.
-XValues other than these can lead to strange behaviour.
-X.IP -DTMPDIR=\fIstring\fP
-XThis sets the default value of the "directory" option, which specifies where
-Xthe temporary files should reside.
-XThe value of TMPDIR must be a string, so be sure your value includes the
-Xquote characters on each end.
-X.IP "-DEXRC=\fIstr\fP, -DHMEXRC=\fIstr\fP, -DSYSEXRC=\fIstr\fP, -DEXINIT=\fIstr\fP"
-XThis lets you control the names of the initialization files.
-XTheir values must be strings, so be careful about quoting.
-X.IP
-XEXRC is the name of the initialization file in the current directory.
-XIts default value is ".exrc" on UNIX systems -- the same as the real vi.
-XSince that isn't a legal DOS filename, under DOS the default is "elvis.rc".
-XFor other systems, check the config.h file.
-X.IP
-XHMEXRC is the name of the initialization file in your home directory.
-XBy default, it is the same as EXRC.
-X\*E will automatically prepend the name of your home directory to HMEXRC
-Xat run time, so don't give a full path name.
-X.IP
-XSYSEXRC is the name of a system-wide initialization file.
-XIt has no default value;
-Xif you don't define a value for it, then
-Xthe code that supports SYSEXRC just isn't compiled.
-XThe value of SYSEXRC should be a full pathname, in quotes.
-X.IP
-XEXINIT is the name of an environment variable that can contain initialization
-Xcommands.
-XNormally, its value is "EXINIT".
-X.IP -DKEYWORDPRG=\fIstring\fP
-XThis flag determines the default value of the "keywordprg" option.
-XIts value must be a string, so be careful about quoting.
-XThe default value of this flag is "ref", which is a C reference program.
-X.IP "-DCC_COMMAND=\fIstring\fP -DMAKE_COMMAND=\fIstring\fP -DERRLIST=\fIstring\fP"
-XThese control the names of the C compiler, the "make" utility, and the
-Xerror output file, respectively.
-XThey are only used if -DNO_ERRLIST is not given.
-X.IP
-XThe default value of CC_COMMAND depends on the Operating System and compiler
-Xthat you use to compile elvis;
-Xfor UNIX, the default is "cc".
-XThe default values of MAKE_COMMAND and ERRLIST are "make" and "errlist",
-Xrespectively.
-X.IP -DMAXRCLEN=\fInumber\fP
-XThis determines how large a :@ macro command can be (measured in bytes).
-XThe default is 1000 bytes.
-XIf you increase this value significantly,
-Xthen you may need to allocate extra memory for the stack.
-XSee the "CHMEM" setting in the Makefile.
-X.IP -DSHELL=\fIstring\fP
-XThis is the default value of the "shell" option, and hence
-Xthe default shell used from within \*E.
-XThis only controls the default;
-Xthe value you give here may be overridden at run-time by setting
-Xan environment variable named SHELL (or COMSPEC for MS-DOS).
-XIts value must be a string constant, so be careful about quoting.
-X.IP -DTAGS=\fIstring\fP
-XThis sets the name of the "tags" file,
-Xwhich is used by the :tag command.
-XIts value must be a string constant, so be careful about quoting.
-X.IP "-DCS_IBMPC -DCS_LATIN1 -DCS_SPECIAL"
-XThe digraph table and flipcase option will normally start out empty.
-XHowever, if you add -DCS_IBMPC or -DCS_LATIN1 to your CFLAGS,
-Xthen they will start out filled with values that are appropriate for the
-XIBM PC character set or the ISO Latin-1 character set, respectively.
-X.IP
-XYou can also use -DCS_IBMPC and -DCS_SPECIAL together to get digraphs
-Xthat produce the PC's graphic characters.
-X.IP "-DDEBUG -DEBUG2"
-X-DDEBUG adds the ":debug" and ":validate" commands,
-Xand also adds many internal consistency checks.
-XIt increases the size of the ".text" segment by about 6K.
-X.IP
-X-DDEBUG2 causes a line to be appended to a file called "debug.out"
-Xeverytime any change is made to the edit buffer.
-X.IP -DCRUNCH
-XThis flag removes some non-critical code, so that \*E is smaller.
-XFor example, it removes a short-cut from the regexp package, so that
-Xtext searches are slower.
-XAlso, screen updates are not as efficient.
-XA couple of obscure features are disabled by this, too.
-X.IP -DNO_MKEXRC
-XThis removes the ":mkexrc" command,
-Xso you have to create any .exrc files manually.
-XThe size of the .text segment will be reduced by about 600 bytes.
-X.IP -DNO_CHARATTR
-XPermanently disables the charattr option.
-XThis reduces the size of your ".text" segment by about 850 bytes.
-X.IP -DNO_RECYCLE
-XNormally, \*E will recycle space (from the temporary file) which contains
-Xtotally obsolete text.
-XThis flag disables this recycling.
-XWithout recycling, the ".text" segment is about 1K smaller
-Xthan it would otherwise be,
-Xbut the tmp file grows much faster.
-XIf you have a lot of free space on your hard disk,
-Xbut \*E is too bulky to run with recycling,
-Xthen try it without recycling.
-X.IP
-XWhen using a version of \*E that has been compiled with -DNO_RECYCLE,
-Xyou should be careful to avoid making many small changes to a file
-Xbecause each individual change will cause the tmp file to grow by at least 1k.
-XHitting "x" thirty times counts as thirty changes,
-Xbut typing "30x" counts as one change.
-XAlso, you should occasionally do a ":w" followed by a ":e" to start with a
-Xfresh tmp file.
-X.IP
-XInterestingly, the real vi never recycles space from its temporary file.
-X.IP -DNO_SENTENCE
-XLeaves out the "(" and ")" visual mode commands.
-XAlso, the "[[", "]]", "{", and "}" commands will not recognize *roff macros.
-XThe sections and paragraphs options go away.
-XThis saves about 650 bytes in the ".text" segment.
-X.IP -DNO_CHARSEARCH
-XLeaves out the visual commands which locate a given character
-Xin the current line:
-X"f", "t", "F", "T", "," and ";".
-XThis saves about 900 bytes.
-X.IP -DNO_EXTENSIONS
-XLeaves out the "K" and "#" visual commands.
-XAlso, the arrow keys will no longer work in input mode.
-XRegular expressions will no longer recognize the \\{\\} operator.
-X(Other extensions are either inherent in the design of \*E,
-Xor are controlled by more specific flags,
-Xor are too tiny to be worth removing.)
-XThis saves about 250 bytes.
-X.IP -DNO_MAGIC
-XPermanently disables the "magic" option, so that most meta-characters
-Xin a regular expression are *NOT* recognized.
-XThis saves about 3k of space in the ".text" segment, because
-Xthe complex regular expression code can be replaced by much simpler code.
-X.IP -DNO_SHOWMODE
-XPermanently disables the "showmode" option, saving about 250 bytes.
-X.IP -DNO_CURSORSHAPE
-XNormally, \*E tries to adjust the shape of the cursor as a reminder
-Xof which mode you're in.
-XThe -DNO_CURSORSHAPE flag disables this, saving about 150 bytes.
-X.IP -DNO_DIGRAPH
-XTo allow entry of non-ASCII characters, \*E supports digraphs.
-XA digraph is a single (non-ASCII) character which is entered as a
-Xcombination of two other (ASCII) characters.
-XIf you don't need to input non-ASCII characters,
-Xor if your keyboard supports a better way of entering non-ASCII characters,
-Xthen you can disable the digraph code and save about 450 bytes.
-X.IP -DNO_ERRLIST
-X\*E adds a ":errlist" command, which is useful to programmers.
-XIf you don't need this feature, you can disable it via the -DNO_ERRLIST flag.
-XThis will reduce the .text segment by about 900 bytes, and the .bss segment
-Xby about 300 bytes.
-X.IP -DNO_ABBR
-XThe -DNO_ABBR flag disables the ":abbr" command,
-Xand reduces the size of \*E by about 250 bytes.
-X.IP -DNO_OPTCOLS
-XWhen \*E displays the current options settings via the ":set" command,
-Xthe options are normally sorted into columns.
-XThe -DNO_OPTCOLS flag causes the options to be sorted across the rows,
-Xwhich is much simpler for the computer.
-XThe -DNO_OPTCOLS flag will reduce the size of your .text segment by about
-X500 bytes.
-X.IP -DNO_MODELINES
-XThis removes all support for modelines.
-X.IP -DNO_TAG
-XThis disables tag lookup.
-XIt reduces the size of the .text segment by about 750 bytes.
-X.IP "-DNO_ALT_FKEY -DNO_CTRL_FKEY -DNO_SHIFT_FKEY -DNO_FKEY"
-XThese remove explicit support of function keys.
-X-DNO_ALT_FKEY removes support for the <alternate> versions function keys.
-X-DNO_CTRL_FKEY removes support for the <control> and <alternate> versions function keys.
-X-DNO_SHIFT_FKEY removes support for the <shift>, <control>, and <alternate> versions function keys.
-X-DNO_FKEY removes all support of function keys.
-X.IP
-X\*E's ":map" command normally allows you to use the special sequence "#<n>"
-Xto map function key <n>.
-XFor example, ":map #1 {!}fmt^M" will cause the <F1> key to reformat a paragraph.
-X\*E checks the :k1=: field in the termcap description of your terminal
-Xto figure out what code is sent by the <F1> key.
-XThis is handy because it allows you to create a .exrc file which maps function
-Xkeys the same way regardless of what type of terminal you use.
-X.IP
-XThat behaviour is standard; most implementations of the real vi supports it too.
-X\*E extends this to allow you to use "#1s" to refer to <shift>+<F1>,
-X"#1c" to refer to <control>+<F1>, and
-X"#1a" to refer to <alt>+<F1>.
-XThe termcap description for the terminal should have fields named
-X:s1=:c1=:a1=: respectively, to define the code sent by these key conbinations.
-X(You should also have :k2=:s2=:c2=:a2=: for the <F2> key, and so on.)
-X.IP
-XBut there may be problems.
-XThe terminfo database doesn't support :s1=:c1=:a1=:, so no terminfo terminal
-Xdescription could ever support shift/control/alt function keys;
-Xso you might as well add -DNO_SHIFT_FKEY to CFLAGS if you're using terminfo.
-X.IP
-XNote that, even if you have -DNO_FKEYS, you can still configure \*E to use
-Xyour function keys my mapping the literal character codes sent by the key.
-XYou just couldn't do it in a terminal-independent way.
-XTERM_925
-X.IP "-DTERM_AMIGA -DTERM_VT100 -DTERM_VT52 etc."
-XThe tinytcap.c file contains descriptions of several terminal types.
-XFor each system that uses tinytcap, a reasonable subset of the available
-Xdescriptions is actually compiled into \*E.
-XIf you wish to enlarge this subset, then you can add the appropriate -DTERM_XXX
-Xflag to your CFLAGS settings.
-X.IP
-XFor a list of the available terminal types, check the tinytcap.c file.
-X.IP -DINTERNAL_TAGS
-XNormally, \*E uses the "ref" program to perform tag lookup.
-XThis is more powerful than the real vi's tag lookup,
-Xbut it can be much slower.
-X.IP
-XIf you add -DINTERNAL_TAGS to your CFLAGS setting,
-Xthen \* will use its own internal tag lookup code, which is faster.
-X.IP -DPRSVDIR=\fIdirectory\fR
-XThis controls where preserved files will be placed.
-XAn appropriate default has been chosen for each Operating System,
-Xso you probably don't need to worry about it.
-X.IP -DFILEPERMS=\fInumber\fR
-XThis affects the attributes of files that are created by \*E;
-Xit is used as the second argument to the creat() function.
-XThe default is 0666 which (on UNIX systems at least) means that
-Xanybody can read or write the new file, but nobody can execute it.
-XOn UNIX systems, the creat() call modifies this via the umask setting.
-X.IP -DKEYBUFSIZE=\fInumber\fR
-XThis determines the size of the type-ahead buffer that elvis uses.
-XIt also limits the size of keymaps that it can handle.
-XThe default is 1000 characters, which should be plenty.
-/
-echo x - cutbufs.ms
-sed '/^X/s///' > cutbufs.ms << '/'
-X.Go 6 "CUT BUFFERS"
-X.PP
-XWhen \*E deletes text, it stores that text in a cut buffer.
-XThis happens in both visual mode and EX mode.
-XThere is no practical limit to how much text a cut buffer can hold.
-X.PP
-XThere are 36 cut buffers:
-X26 named buffers ("a through "z),
-X9 anonymous buffers ("1 through "9),
-Xand 1 extra cut buffer (".).
-X.PP
-XIn EX mode, the :move and :copy commands use a cut buffer to temporarily
-Xhold the text to be moved/copied.
-X.NH 2
-XPutting text into a Cut Buffer
-X.PP
-XIn visual mode, text is copied into a cut buffer when you use the
-Xd, y, c, C, s, or x commands.
-XThere are also a few others.
-X.PP
-XBy default, the text goes into the "1 buffer.
-XThe text that used to be in "1 gets shifted into "2,
-X"2 gets shifted into "3, and so on.
-XThe text that used to be in "9 is lost.
-XThis way, the last 9 things you deleted are still accessible.
-X.PP
-XYou can also put the text into a named buffer -- "a through "z.
-XTo do this, you should type the buffer's name
-X(two keystrokes: a double-quote and a lowercase letter)
-Xbefore the command that will cut the text.
-XWhen you do this, "1 through "9 are not affected by the cut.
-X.PP
-XYou can append text to one of the named buffers.
-XTo do this, type the buffer's name in uppercase
-X(a double-quote and an uppercase letter)
-Xbefore the d/y/c/C/s/x command.
-X.PP
-XThe ". buffer is special.
-XIt isn't affected by the d/y/c/C/s/x command.
-XInstead, it stores the text that you typed in
-Xthe last time you were in input mode.
-XIt is used to implement the . visual command,
-Xand ^A in input mode.
-X.PP
-XIn EX mode (also known as colon mode),
-Xthe :delete, :change, and :yank commands all copy text into a cut buffer.
-XLike the visual commands, these EX commands normally use the "1 buffer,
-Xbut you can use one of the named buffers by giving its name after the command.
-XFor example,
-X.sp 1
-X.ti +0.5i
-X:20,30y a
-X.sp
-X.LP
-Xwill copy lines 20 through 30 into cut buffer "a.
-X.PP
-XYou can't directly put text into the ". buffer, or the "2 through "9 buffers.
-X.NH 2
-XPasting from a Cut Buffer
-X.PP
-XThere are two styles of pasting:
-Xline-mode and character-mode.
-XIf a cut buffer contains whole lines (from a command like "dd")
-Xthen line-mode pasting is used;
-Xif it contains partial lines (from a command like "dw")
-Xthen character-mode pasting is used.
-XThe EX commands always cut whole lines.
-X.PP
-XCharacter-mode pasting causes the text to be inserted into the line that
-Xthe cursor is on.
-X.PP
-XLine-mode pasting inserts the text on a new line above or below the line
-Xthat the cursor is on.
-XIt doesn't affect the cursor's line at all.
-X.PP
-XIn visual mode, the p and P commands insert text from a cut buffer.
-XUppercase P will insert it before the cursor,
-Xand lowercase p will insert it after the cursor.
-XNormally, these commands will paste from the "1 buffer, but you can
-Xspecify any other buffer to paste from.
-XJust type its name (a double-quote and another character)
-Xbefore you type the P or p.
-X.PP
-XIn EX mode, the (pu)t command pastes text after a given line.
-XTo paste from a buffer other that "1,
-Xenter its name after the command.
-X.NH 2
-XMacros
-X.PP
-XThe contents of a named cut buffer can be executed as a series of
-Xex/vi commands.
-X.PP
-XTo put the instructions into the cut buffer, you must first insert
-Xthem into the file, and then delete them into a named cut buffer.
-X.PP
-XTo execute a cut buffer's contents as EX commands,
-Xyou should give the EX command "@" and the name of the buffer.
-XFor example, :@z will execute "z as a series of EX commands.
-X.PP
-XTo execute a cut buffer's contents as visual commands,
-Xyou should give the visual command "@" and the letter of the buffer's name.
-XThe visual "@" command is different from the EX "@" command.
-XThey interpret the cut buffer's contents differently.
-X.PP
-XThe visual @ command can be rather finicky.
-XEach character in the buffer is interpretted as a keystroke.
-XIf you load the instructions into the cut buffer via a "zdd command,
-Xthen the newline character at the end of the line will be executed just
-Xlike any other character, so the cursor would be moved down 1 line.
-XIf you don't want the cursor to move down 1 line at the end of each
-X@z command, then you should load the cut buffer by saying 0"zD instead.
-X.PP
-XAlthough cut buffers can hold any amount of text,
-X\*E can only \fIexecute\fR small buffers.
-XThe size limit is roughly 1000 characters, for either EX macros or VI macros.
-XIf a buffer is too large to execute, an error message is displayed.
-X.PP
-XYou can't nest :@ commands.
-XYou can't run :@ commands from your .exrc file,
-Xor any other :source file either.
-XSimilarly, you can't run a :source command from within an @ command.
-XHopefully, these restrictions will be lifted in a later version.
-X.NH 2
-XThe Effect of Switching Files
-X.PP
-XWhen \*E first starts up, all cut buffers are empty.
-XWhen you switch to a different file
-X(via the :n or :e commands perhaps)
-Xthe 9 anonymous cut buffers are emptied again,
-Xbut the other 27 buffers ("a through "z, and ".) retain their text.
-/
-echo x - differ.ms
-sed '/^X/s///' > differ.ms << '/'
-X.Go 7 "DIFFERENCES BETWEEN \*E & BSD VI/EX"
-X.PP
-X\*E is not 100% compatible with the real vi/ex.
-X\*E has many small extensions, some omissions, and a few features which
-Xare implemented in a slightly different manner.
-X.NH 2
-XExtensions
-X.IP "Save Configuration" 1i
-XThe :mkexrc command saves the current :set and :map configurations in
-Xthe ".exrc" file in your current directory.
-X.IP "Previous File" 1i
-XThe :N or :prev command moves backwards through the args list.
-X.IP "Center Current Row" 1i
-XIn visual command mode, the (lowercase) "zz" command will center the current
-Xline on the screen, like "z=".
-X.IP "Changing Repeat Count" 1i
-XThe default count value for . is the same as the previous command
-Xwhich . is meant to repeat.
-XHowever, you can supply a new count if you wish.
-XFor example, after "3dw", "." will delete 3 words,
-Xbut "5." will delete 5 words.
-X.IP "Previous Text" 1i
-XThe text which was most recently input
-X(via a "cw" command, or something similar)
-Xis saved in a cut buffer called ". (which
-Xis a pretty hard name to write in an English sentence).
-X.IP "Keyword Lookup" 1i
-XIn visual command mode, you can move the cursor onto a word and press
-Xshift-K to have \*E run a reference program to look that word up.
-XThis command alone is worth the price of admission!
-XSee the ctags and ref programs.
-X.IP "Increment/Decrement" 1i
-XIn visual command mode, you can move the cursor onto a number and
-Xthen hit ## or #+ to increment that number by 1.
-XTo increment it by a larger amount,
-Xtype in the increment value before hitting the initial #.
-XThe number can also be decremented or set by hitting #- or #=, respectively.
-X.IP "Input Mode" 1i
-XYou can backspace past the beginning of the line.
-X.IP "" 1i
-XThe arrow keys work in input mode.
-X.IP "" 1i
-XIf you type control-A, then the text that you input last time is inserted.
-XYou will remain in input mode, so you can backspace over part of it,
-Xor add more to it.
-X(This is sort of like control-@ on the real vi,
-Xexcept that control-A really works.)
-X.IP "" 1i
-XControl-P will insert the contents of the cut buffer.
-X.IP "" 1i
-XReal vi can only remember up to 128 characters of input,
-Xbut \*E can remember any amount.
-X.IP "" 1i
-XThe ^T and ^D keys can adjust the indent of a line no matter where
-Xthe cursor happens to be in that line.
-X.IP "" 1i
-XYou can save your file and exit \*E directly from input mode by hitting
-Xcontrol-Z twice.
-X.IP "" 1i
-X\*E supports digraphs as a way to enter non-ASCII characters.
-X.IP "Start in Input Mode" 1i
-XIf you ":set inputmode" in your .exrc file, then \*E will start up in
-Xinput mode instead of visual command mode.
-X.IP "Visible Fonts" 1i
-XWith ":set charattr", \*E can display "backslash-f" style character attributes on the
-Xscreen as you edit.
-XThe following example shows the recognized atributes:
-X.sp
-X.ti +0.5i
-Xnormal \\fBboldface\\fR \\fIitalics\\fR \\fUunderlined\\fR normal
-X.sp
-XNOTE: you must compile \*E without the -DNO_CHARATTR flag for
-Xthis to work.
-X.IP "File Syncing" 1i
-XAfter a crash, you can usually recover the altered form of the file
-Xfrom the temporary file that \*E uses -- unless the temporary file was
-Xcorrupted.
-X.IP "" 1i
-XUNIX systems use a delayed-write cache, which means that when \*E tries to
-Xwrite to the temporary file, the information might still be in RAM instead
-Xof on the disk.
-XA power failure at that time would cause the in-RAM information to be lost.
-XUNIX's sync() call will force all such information to disk.
-X.IP "" 1i
-XMS-DOS and Atari TOS don't write a file's length to disk until that file
-Xis closed.
-XConsequently, the temporary file would appear to be 0 bytes long if power
-Xfailed when we were editing.
-XTo avoid this problem, a sync() function has been written which will close
-Xthe temporary file and then immediately reopen it.
-X.IP "Cursor Shape" 1i
-X\*E changes the shape of the cursor to indicate which mode you're in,
-Xif your terminal's termcap entry includes the necessary capabilities.
-X.IP "Hide nroff Lines" 1i
-XTh ":set hideformat" option hides nroff format control lines.
-X(They are displayed on the screen as blank lines.)
-X.ne 7
-X.IP "Compiler Interface" 1i
-X\*E is clever enough to parse the error messages emitted by many compilers.
-XTo use this feature,
-Xyou should collect your compiler's error messages into a file called "errlist";
-X\*E will read this file,
-Xdetermine which source file caused the error messages,
-Xstart editing that file,
-Xmove the cursor to the line where the error was detected,
-Xand display the error message on the status line.
-XNifty!
-X.IP "Visible Text Selection" 1i
-XIn visual command mode, 'v' starts visibly selecting characters and
-X\&'V' starts visibly selecting whole lines.
-XThe character or line where the cursor is located becomes one
-Xendpoint of the selection.
-XYou can then use the standard cursor movement commands to move the cursor
-Xto the other endpoint, and then press one of the operator commands
-X(c/d/y/</>/!/=/\\).
-XThe operator will then immediately be applied to the selected text.
-X.IP "Pop-up Menu Operator" 1i
-XThe '\\' key is a new operator,
-Xsimilar in operation to the c/d/y/</>/! operators
-XIt conjures up a menu, from which you can select any of the other
-Xoperators plus a few other common commands.
-X.IP "Preset Filter Operator" 1i
-XThe '=' key is another new operator.
-XIt is similar to the '!' operator, except that while
-X\&'!' asks you to type in a filter command each time,
-X\&'=' assumes it should always run the command stored in the \fIequalprg\fR option.
-X.IP "Move to a Given Percentage" 1i
-XThe '%' movement key can now accept an optional count.
-XWithout a count, the '%' key still moves to a matching parenthesis
-Xlike it always did.
-XWith a count somewhere between 1 and 100, though, it moves the cursor to
-Xapproximately a given percentage of the way through the file.
-XFor example, typing "50%" will move the cursor to the middle of the file.
-X.IP "Regular Expressions"
-XIn regular expressions, several new forms of closure operators are supported:
-X\\{\fIn\fR}, \\{\fIn\fR,\fIm\fR}, \\+, and \\?.
-X.NH 2
-XOmissions
-X.PP
-XThe replace mode is a hack.
-XIt doesn't save the text that it overwrites.
-X.PP
-XLong lines are displayed differently -- where the real vi would
-Xwrap a long line onto several rows of the screen, \*E simply
-Xdisplays part of the line, and allows you to scroll the screen
-Xsideways to see the rest of it.
-X.PP
-XThe ":preserve" and ":recover" commands are missing.
-XSo is the -r flag.
-XI've never had a good reason to use ":preserve",
-Xand since ":recover" is used so rarely
-XI decided to implement it as a separate program.
-XThere's no need to load the recovery code into memory every
-Xtime you edit a file, I figured.
-X.PP
-XLISP support is missing.
-XHowever, the = key is still an operator that reformats lines of text.
-XBy default, it reformats lines by sending them through the \fIfmt\fP filter,
-Xbut you could write your own LISP beautifier and configure elvis to use it.
-XKey mappings could take care of most other differences.
-XAuto-indent is the only thing that is irrecoverably lost.
-X.PP
-XAutoindent mode acts a little different from the real vi, anyway.
-XIt doesn't handle ^^D or 0^D correctly.
-XOn the other hand, it \fIdoes\fP allow ^D and ^T to be used anywhere in the
-Xline, to adjust the indentation for the whole line.
-/
-echo x - environ.ms
-sed '/^X/s///' > environ.ms << '/'
-X.Go 11 "ENVIRONMENT VARIABLES"
-X.PP
-X\*E examines several environment variables when it starts up.
-XThe values of these variables are used internally for a variety
-Xof purposes.
-XYou don't need to define all of these;
-Xon most systems, \*E only requires TERM to be defined.
-XOn AmigaDOS, MS-DOS or TOS systems, even that is optional.
-X.SH
-XTERM, TERMCAP
-X.PP
-XTERM tells \*E the name of the termcap entry to use.
-XTERMCAP may contain either the entire termcap entry,
-Xor the full pathname of the termcap file to search through.
-X.PP
-XIf your version of \*E is using tinytcap instead of the full termcap library,
-Xthen the value of TERMCAP \fIcannot\fR contain any backslash escapes (\\E, \\r, etc.)
-Xor carat escapes (^[, ^M, etc.), because tinytcap doesn't understand them.
-XInstead, you should embed the actual control character into the string.
-X.SH
-XTMP, TEMP
-X.PP
-XThese only work for AmigaDOS, MS-DOS and Atari TOS.
-XEither of these variables may be used to set the "directory" option,
-Xwhich controls where temporary files are stored.
-XIf you define them both, then TMP is used, and TEMP is ignored.
-X.SH
-XLINES, COLUMNS
-X.PP
-XThe termcap entry for your terminal should specify the size of your screen.
-XIf you're using a windowing interface, then there is an ioctl() call which
-Xwill provide the size of the window; the ioctl() values will override the
-Xvalues in the termcap entry.
-XThe LINES and COLUMNS environment variables (if defined)
-Xwill override either of these sources.
-XThey, in turn, can be overridden by a ":set" command.
-X.PP
-XNormally, the LINES and COLUMNS variables shouldn't need to be defined.
-X.SH
-XEXINIT
-X.PP
-XThis variable's value may contain one or more colon-mode commands,
-Xwhich will be executed after all of the ".exrc" files
-Xbut before interactive editing begins.
-X.PP
-XTo put more than one command in EXINIT, you can separate the commands
-Xwith either a newline or a '|' character.
-X.SH
-XSHELL, COMSPEC
-X.PP
-XYou can use COMSPEC in MS-DOS, or SHELL in any other system,
-Xto specify which shell should be used for executing commands and
-Xexpanding wildcards.
-X.SH
-XHOME
-X.PP
-XThis variable should give the full pathname of your home directory.
-X\*E needs to know the name of your home directory so it can locate
-Xthe ".exrc" file there.
-X.SH
-XTAGPATH
-X.PP
-XThis variable is used by the "ref" program.
-XIt contains a list of directories that might contain a relevent "tags" file.
-XUnder AmigaDOS, MS-DOS or Atari TOS, the names of the directories should be separated by
-Xsemicolons (";").
-XUnder other operating systems, the names should be separated by colons (":").
-X.PP
-XIf you don't define TAGPATH, then "ref" will use a default list which includes
-Xthe current directory and a few other likely places.
-XSee the definition of DEFTAGPATH at the start of ref.c for an accurate list.
-/
-echo x - ex.ms
-sed '/^X/s///' > ex.ms << '/'
-X.Go 3 "COLON MODE COMMANDS"
-X.ID
-X.ps
-X.in 0.8i
-X.ta 2i 3.i
-X.\" NOTE: The following macro is used to output a single line of the
-X.\" command chart.  Its usage is:
-X.\"
-X.\"           .Cm <linespecs> <name> <arguments>...
-X.\"
-X.de Cm
-X.if "\\$1"0" \t\\$2\t\\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
-X.if "\\$1"1" \s-2[line]\s+2\t\\$2\t\\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
-X.if "\\$1"2" \s-2[line][,line]\s+2\t\\$2\t\\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
-X..
-X.if t .ds Q ``
-X.if t .ds U ''
-X.if n .ds Q "
-X.if n .ds U "
-X\s+2LINES     COMMAND ARGUMENTS\s-2
-X.Cm 0 ab[br] [short] [expanded form]
-X.Cm 1 a[ppend][!]
-X.Cm 0 ar[gs] [files]
-X.Cm 0 cc [files]
-X.Cm 0 cd[!] [directory]
-X.Cm 2 c[hange]
-X.Cm 0 chd[ir][!] [directory]
-X.Cm 2 co[py] line
-X.Cm 0 col[or] [when] [[\*Qlight\*U] color] [\*Qon\*U color]
-X.Cm 2 d[elete] [\*Ux]
-X.Cm 0 dig[raph][!] [XX [Y]]
-X.Cm 0 e[dit][!] [file]
-X.Cm 0 er[rlist][!] [errlist]
-X.Cm 0 f[ile] [file]
-X.Cm 2 g[lobal] /regexp/ command
-X.Cm 1 i[nsert]
-X.Cm 2 j[oin][!]
-X.Cm 2 l[ist]
-X.Cm 0 mak[e] [target]
-X.Cm 0 map[!] key mapped_to
-X.Cm 1 ma[rk]  \*Ux
-X.Cm 0 mk[exrc]
-X.Cm 2 m[ove] line
-X.Cm 0 n[ext][!] [files]
-X.Cm 0 N[ext][!]
-X.Cm 2 nu[mber]
-X.Cm 2 p[rint]
-X.Cm 1 pu[t] [\*Ux]
-X.Cm 0 q[uit][!]
-X.Cm 1 r[ead] file
-X.Cm 0 rew[ind][!]
-X.Cm 0 se[t] [options]
-X.Cm 0 so[urce] file
-X.Cm 2 s[ubstitute] /regexp/replacement/[p][g][c]
-X.Cm 0 ta[g][!] tagname
-X.Cm 0 una[bbr] [short]
-X.Cm 0 u[ndo]
-X.Cm 0 unm[ap][!] key
-X.Cm 0 ve[rsion]
-X.Cm 2 v[global] /regexp/ command
-X.Cm 0 vi[sual] [filename]
-X.Cm 0 wq 
-X.Cm 2 w[rite][!] [[>>]file]
-X.Cm 0 x[it][!]
-X.Cm 2 y[ank] [\*Ux]
-X.Cm 2 ! command
-X.Cm 2 < 
-X.Cm 2 = 
-X.Cm 2 > 
-X.Cm 2 & 
-X.Cm 0 @ "" \*Ux
-X.DE
-X.TA
-X.PP
-XTo use colon mode commands, you must switch from visual command
-Xmode to colon command mode.
-XThe visual mode commands to do this are ":" for a single colon command,
-Xor "Q" for many colon mode commands.
-X.NH 2
-XLine Specifiers
-X.PP
-XLine specifiers are always optional.
-XThe first line specifier of most commands usually defaults to the current line.
-XThe second line specifier usually defaults to be the same
-Xas the first line specifier.
-XExceptions are :write, :global, and :vglobal, which act on all lines of the
-Xfile by default, and :!, which acts on no lines by default.
-X.PP
-XLine specifiers consist of an absolute part and a relative part.
-XThe absolute part of a line specifier may be either an explicit line number,
-Xa mark, a dot to denote the current line, a dollar sign to denote the last
-Xline of the file, or a forward or backward search.
-X.PP
-XAn explicit line number is simply a decimal number, expressed as a
-Xstring of digits.
-X.PP
-XA mark is typed in as an apostrophe followed by a letter.
-XMarks must be set before they can be used.
-XYou can set a mark in visual command mode by typing "m" and a letter,
-Xor you can set it in colon command mode via the "mark" command.
-X.PP
-XA forward search is typed in as a regular expression surrounded by
-Xslash characters; searching begins at the default line.
-XA backward search is typed in as a regular expression surrounded by
-Xquestion marks; searching begins at the line before the default line.
-X.PP
-XIf you omit the absolute part, then the default line is used.
-X.PP
-XThe relative part of a line specifier is typed as a "+" or "-" character
-Xfollowed by a decimal number.
-XThe number is added to or subtracted from the absolute part
-Xof the line specifier to produce the final line number.
-X.PP
-XAs a special case, the % character may be used to specify all lines of the file.
-XIt is roughly equivelent to saying 1,$.
-XThis can be a handy shortcut.
-X.PP
-XSome examples:
-X.LD
-X.ps
-X.ta 0.5i 1.8i
-X      :p      print the current line
-X      :37p    print line 37
-X      :'gp    print the line which contains mark g
-X      :/foo/p print the next line that contains "foo"
-X      :$p     print the last line of the file
-X      :20,30p print lines 20 through 30
-X      :1,$p   print all lines of the file
-X      :%p     print all lines of the file
-X      :/foo/-2,+4p    print 5 lines around the next "foo"
-X.TA
-X.DE
-X.NH 2
-XText Entry Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line] append
-X[line][,line] change ["x]
-X[line] insert
-X.DE
-X.PP
-XThe \fBa\fRppend command inserts text after the specified line.
-X.PP
-XThe \fBi\fRnsert command inserts text before the specified line.
-X.PP
-XThe \fBc\fRhange command copies the range of lines into a cut buffer,
-Xdeletes them, and inserts new text where the old text used to be.
-X.PP
-XFor all of these commands, you indicate the end of the text you're
-Xinserting by hitting ^D or by entering a line which contains only a
-Xperiod.
-X.NH 2
-XCut & Paste Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line][,line] delete ["x]
-X[line][,line] yank ["x]
-X[line] put ["x]
-X[line][,line] copy line
-X[line][,line] to line
-X[line][,line] move line
-X.DE
-X.PP
-XThe \fBd\fRelete command copies the specified range of lines into a
-Xcut buffer, and then deletes them.
-X.PP
-XThe \fBy\fRank command copies the specified range of lines into a cut
-Xbuffer, but does *not* delete them.
-X.PP
-XThe \fBpu\fRt command inserts text from a cut buffer after the
-Xspecified line.
-X.PP
-XThe \fBco\fRpy and \fBt\fRo commands yank the specified range of lines and
-Xthen immediately paste them after some other line.
-X.PP
-XThe \fBm\fRove command deletes the specified range of lines and then
-Ximmediately pastes them after some other line.
-XIf the destination line comes after the deleted text,
-Xthen it will be adjusted automatically to account for the deleted lines.
-X.NH 2
-XDisplay Text Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line][,line] print
-X[line][,line] list
-X[line][,line] number
-X.DE
-X.PP
-XThe \fBp\fRrint command displays the specified range of lines.
-X.PP
-XThe \fBnu\fRmber command displays the lines, with line numbers.
-X.PP
-XThe \fBl\fRist command also displays them, but it is careful to make
-Xcontrol characters visible.
-X.NH 2
-XGlobal Operations Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line][,line] global /regexp/ command
-X[line][,line] vglobal /regexp/ command
-X.DE
-X.PP
-XThe \fBg\fRlobal command searches through the lines of the specified range
-X(or through the whole file if no range is specified)
-Xfor lines that contain a given regular expression.
-XIt then moves the cursor to each of these lines and
-Xruns some other command on them.
-X.PP
-XThe \fBv\fRglobal command is similar, but it searches for lines that \fIdon't\fR
-Xcontain the regular expression.
-X.NH 2
-XLine Editing Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line][,line] join[!]
-X[line][,line] ! program
-X[line][,line] <
-X[line][,line] >
-X[line][,line] substitute /regexp/replacement/[p][g][c]
-X[line][,line] &
-X.DE
-X.PP
-XThe \fBj\fRoin command catenates all lines in the specified range together
-Xto form one big line.
-XIf only a single line is specified, then the following line is catenated
-Xonto it.
-XThe normal ":join" inserts one or two spaces between the lines;
-Xthe ":join!" variation (with a '!') doesn't insert spaces.
-X.PP
-XThe \fB!\fR command runs an external filter program,
-Xand feeds the specified range of lines to it's stdin.
-XThe lines are then replaced by the output of the filter.
-XA typical example would be ":'a,'z!sort" to sort the lines 'a,'z.
-X.PP
-XThe \fB<\fR and \fB>\fR commands shift the specified range of lines left or right,
-Xnormally by the width of 1 tab character.
-XThe "shiftwidth" option determines the shifting amount.
-X.PP
-XThe \fBs\fRubstitute command finds the regular expression in each line,
-Xand replaces it with the replacement text.
-XThe "p" option causes the altered lines to be printed.
-XThe "g" option permits all instances of the regular expression
-Xto be found & replaced.
-X(Without "g", only the first occurrence in each line is replaced.)
-XThe "c" option asks for confirmation before each substitution.
-X.PP
-XThe \fB&\fR command repeats the previous substitution command.
-XActually, "&" is equivelent to "s//~/" with the same options as last time.
-XIt searches for the last regular expression that you specified for any purpose,
-Xand replaces it with the the same text
-Xthat was used in the previous substitution.
-X.NH 2
-XUndo Command
-X.if n .ul 0
-X.ID
-X.ps
-Xundo
-X.DE
-X.PP
-XThe \fBu\fRndo command restores the file to the state it was in before
-Xyour most recent command which changed text.
-X.NH 2
-XConfiguration & Status Commands
-X.if n .ul 0
-X.ID
-X.ps
-Xmap[!] [key mapped_to]
-Xunmap[!] key
-Xabbr [word expanded_form_of_word]
-Xunabbr word
-Xdigraph[!] [XX [Y]]
-Xset [options]
-Xmkexrc
-X[line] mark "x
-Xvisual
-Xversion
-X[line][,line] =
-Xfile [file]
-Xsource file
-X@ "x
-Xcolor [when] [["light"] color] ["on" color]
-X.DE
-X.PP
-XThe \fBma\fRp command allows you to configure \*E to recognize your function keys,
-Xand treat them as though they transmitted some other sequence of characters.
-XNormally this mapping is done only when in the visual command mode,
-Xbut with the [!] present it will map keys under input and replace modes as well.
-XWhen this command is given with no arguments,
-Xit prints a table showing all mappings currently in effect.
-XWhen called with two arguments, the first is the sequence that your
-Xfunction key really sends, and the second is the sequence that you want
-X\*E to treat it as having sent.
-XAs a special case, if the first argument is a number then \*E will map the
-Xcorresponding function key;
-Xfor example, ":map 7 dd" will cause the <F7> key to delete a line.
-X.PP
-XThe \fBunm\fRap command removes key definitions that were made via the map command.
-X.PP
-XThe \fBab\fRbr command is used to define/list a table of abbreviations.
-XThe table contains both the abbreviated form and the fully spelled-out form.
-XWhen you're in visual input mode, and you type in the abbreviated form,
-X\*E will replace the abbreviated form with the fully spelled-out form.
-XWhen this command is called without arguments, it lists the table;
-Xwith two or more arguments, the first argument is taken as the abbreviated
-Xform, and the rest of the command line is the fully-spelled out form.
-X.PP
-XThe \fBuna\fRbbr command deletes entries from the abbr table.
-X.PP
-XThe \fBdi\fRgraph command allows you to display the set of digraphs that \*E is
-Xusing, or add/remove a digraph.
-XTo list the set of digraphs, use the digraph command with no arguments.
-XTo add a digraph, you should give the digraph command two arguments.
-XThe first argument is the two ASCII characters that are to be combined;
-Xthe second is the non-ASCII character that they represent.
-XThe non-ASCII character's most significant bit is automatically set by the
-Xdigraph command, unless to append a ! to the command name.
-XRemoval of a digraph is similar to adding a digraph, except that you should
-Xleave off the second argument.
-X.PP
-XThe \fBse\fRt command allows you examine or set various options.
-XWith no arguments, it displays the values of options that have been changed.
-XWith the single argument "all" it displays the values of all options,
-Xregardless of whether they've been explicitly set or not.
-XOtherwise, the arguments are treated as options to be set.
-X.PP
-XThe \fBmk\fRexrc command saves the current configuration to a file
-Xcalled ".exrc" in the current directory.
-X.PP
-XThe mar\fBk\fR command defines a named mark to refer to a specific place
-Xin the file.
-XThis mark may be used later to specify lines for other commands.
-X.PP
-XThe \fBvi\fRsual command puts the editor into visual mode.
-XInstead of emulating ex, \*E will start emulating vi.
-X.PP
-XThe \fBve\fRrsion command tells you that what version of \*E this is.
-X.PP
-XThe \fB=\fR command tells you what line you specified, or,
-Xif you specified a range of lines, it will tell you both endpoints and
-Xthe number of lines included in the range.
-X.PP
-XThe \fBf\fRile command tells you the name of the file,
-Xwhether it has been modified,
-Xthe number of lines in the file,
-Xand the current line number.
-XYou can also use it to change the name of the current file.
-X.PP
-XThe \fBso\fRurce command reads a sequence of colon mode commands from a file,
-Xand interprets them.
-X.PP
-XThe \fB@\fR command executes the contents of a cut-buffer as EX commands.
-X.PP
-XThe \fBcol\fRor command only works under MS-DOS, or if you have an ANSI-compatible
-Xcolor terminal.
-XIt allows you to set the foreground and background colors
-Xfor different types of text:
-Xnormal, bold, italic, underlined, standout, pop-up menu, and visible selection.
-XBy default, it changes the "normal" colors;
-Xto change other colors, the first argument to the :color command should be
-Xthe first letter of the type of text you want.
-XThe syntax for the colors themselves is fairly intuitive.
-XFor example, ":color light cyan on blue" causes normal text to be displayed
-Xin light cyan on a blue background, and
-X":color b bright white" causes bold text to be displayed in bright white on
-Xa blue background.
-XThe background color always defaults to the current background color of
-Xnormal text.
-XYour first :color command \fImust\fP specify both the foreground and background
-Xfor normal text.
-X.NH 2
-XMultiple File Commands
-X.if n .ul 0
-X.ID
-X.ps
-Xargs [files]
-Xnext[!] [files]
-XNext[!]
-Xprevious[!]
-Xrewind[!]
-X.DE
-X.PP
-XWhen you invoke \*E from your shell's command line,
-Xany filenames that you give to \*E as arguments are stored in the args list.
-XThe \fBar\fRgs command will display this list, or define a new one.
-X.PP
-XThe \fBn\fRext command switches from the current file to the next one
-Xin the args list.
-XYou may specify a new args list here, too.
-X.PP
-XThe \fBN\fRext and \fBpre\fRvious commands
-X(they're really aliases for the same command)
-Xswitch from the current file to the preceding file in the args list.
-X.PP
-XThe \fBrew\fRind command switches from the current file to the first file
-Xin the args list.
-X.NH 2
-XSwitching Files
-X.if n .ul 0
-X.ID
-X.ps
-Xedit[!] [file]
-Xtag[!] tagname
-X.DE
-X.PP
-XThe \fBe\fRdit command allows to switch from the current file to some other file.
-XThis has nothing to do with the args list, by the way.
-X.PP
-XThe \fBta\fRg command looks up a given tagname in a file called "tags".
-XThis tells it which file the tag is in, and how to find it in that file.
-X\*E then switches to the tag's file and finds the tag.
-X.NH 2
-XWorking with a Compiler
-X.if n .ul 0
-X.ID
-X.ps
-Xcc [files]
-Xmake [target]
-Xerrlist[!] [errlist]
-X.DE
-X.PP
-XThe \fBcc\fR and \fBmak\fRe commands execute your compiler or "make" utility
-Xand redirect any error messages into a file called "errlist".
-XBy default, cc is run on the current file.
-X(You should write it before running cc.)
-XThe contents of the "errlist" file are then scanned for error messages.
-XIf an error message is found, then the cursor is moved to the line where
-Xthe error was detected,
-Xand the description of the error is displayed on the status line.
-X.PP
-XAfter you've fixed one error, the \fBer\fRrlist command will move
-Xthe cursor to the next error.
-XIn visual command mode,
-Xhitting `*' will do this, too.
-X.PP
-XYou can also create an "errlist" file from outside of \*E,
-Xand use "\*E -m" to start elvis and have the cursor moved to the
-Xfirst error.
-XNote that you don't need to supply a filename with "\*E -m" because
-Xthe error messages always say which source file an error is in.
-X.PP
-XNote:
-XWhen you use errlist repeatedly to fix several errors in a single file,
-Xit will attempt to adjust the reported line numbers to allow for lines
-Xthat you have inserted or deleted.
-XThese adjustments are made with the assumption that you will work though
-Xthe file from the beginning to the end.
-X.NH 2
-XExit Commands
-X.if n .ul 0
-X.ID
-X.ps
-Xquit[!]
-Xwq
-Xxit
-X.DE
-X.PP
-XThe \fBq\fRuit command exits from the editor without saving your file.
-X.PP
-XThe \fBwq\fR command writes your file out, then then exits.
-X.PP
-XThe \fBx\fRit command is similar to the \fBwq\fR command, except that
-X\fBx\fRit won't bother to write your file if you haven't modified it.
-X.NH 2
-XFile I/O Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line] read file
-X[line][,line] write[!] [[>>]file]
-X.DE
-X.PP
-XThe \fBr\fRead command gets text from another file and inserts it
-Xafter the specified line.
-XIt can also read the output of a program;
-Xsimply precede the program name by a '!' and use it in place of the file name.
-X.PP
-XThe \fBw\fRrite command writes the whole file, or just part of it,
-Xto some other file.
-XThe !, if present, will permit the lines to be written even if you've set
-Xthe readonly option.
-XIf you precede the filename by >> then the lines will be appended to the file.
-XYou can send the lines to the standard input of a program by replacing the
-Xfilename with a '!' followed by the command and its arguments.
-X.PP
-XNote: Be careful not to confuse ":w!filename" and ":w !command".
-XTo write to a program, you must have at least one blank before the '!'.
-X.NH 2
-XDirectory Commands
-X.if n .ul 0
-X.ID
-X.ps
-Xcd [directory]
-Xchdir [directory]
-Xshell
-X.DE
-X.PP
-XThe \fBcd\fR and \fBchd\fRir commands
-X(really two names for one command)
-Xswitch the current working directory.
-X.PP
-XThe \fBsh\fRell command starts an interactive shell.
-X.NH 2
-XDebugging Commands
-X.if n .ul 0
-X.ID
-X.ps
-X[line][,line] debug[!]
-Xvalidate[!]
-X.DE
-X.PP
-XThese commands are only available if you compile \*E with the -DDEBUG flag.
-X.PP
-XThe de\fBb\fRug command lists statistics for the blocks which contain
-Xthe specified range of lines.
-XIf the ! is present, then the contents of those blocks is displayed, too.
-X.PP
-XThe \fBva\fRlidate command checks certain variables for internal consistency.
-XNormally it doesn't output anything unless it detects a problem.
-XWith the !, though, it will always produce *some* output.
-/
-echo x - index.ms
-sed '/^X/s///' > index.ms << '/'
-X.XS 1
-XINTRODUCTION
-XWhat E\s-2LVIS\s+2 does,
-XCopyright,
-XHow to compile E\s-2LVIS\s+2,
-XOverview
-X.XA 2
-XVISUAL MODE COMMANDS
-XNormal interactive editing,
-XInput mode,
-XArrow keys,
-XDigraphs,
-XAbbreviations,
-XAuto-indentation
-X.XA 3
-XCOLON MODE COMMANDS
-XLine specifiers,
-XText entry,
-XCut & paste,
-XDisplay text,
-XGlobal operations,
-XLine editing,
-XUndo,
-XConfiguration & status,
-XMultiple files,
-XSwitching files,
-XWorking with a compiler,
-XExiting,
-XFile I/O,
-XDirectory & shell,
-XDebugging
-X.XA 4
-XREGULAR EXPRESSIONS
-XSyntax,
-XOptions,
-XSubstitutions,
-XExamples
-X.XA 5
-XOPTIONS
-XAutoindent,
-XAutoprint,
-Xetc.
-X.XA 6
-XCUT BUFFERS
-XPutting text into a cut buffer,
-XPasting from a cut buffer,
-XMacros,
-XThe effect of switching files
-X.XA 7
-XDIFFERENCES BETWEEN E\s-2LVIS\s+2 AND THE REAL VI/EX
-XExtensions,
-XOmissions
-X.XA 8
-XINTERNAL
-XFor programmers only,
-XThe temporary file,
-XImplementation of editing,
-XMarks and the cursor,
-XColon command interpretation,
-XScreen control,
-XPortability
-X.XA 9
-XCFLAGS
-X.XA 10
-XTERMCAP
-X.XA 11
-XENVIRONMENT VARIABLES
-X.XA 12
-XVERSIONS
-X.XA 13
-XQUESTIONS & ANSWERS
-X.XE
-X.PX
-X.sp 0.3i
-X.ce 1
-XUNIX-style "man" pages appear at the end of this manual.
-/
-echo x - internal.ms
-sed '/^X/s///' > internal.ms << '/'
-X.Go 8 "INTERNAL"
-X.PP
-XYou don't need to know the material in this section to use \*E.
-XYou only need it if you intend to modify \*E.
-X.PP
-XYou should also check out the CFLAGS, TERMCAP, ENVIRONMENT VARIABLES,
-XVERSIONS, and QUIESTIONS & ANSWERS sections of this manual.
-X.NH 2
-XThe temporary file
-X.PP
-XThe temporary file is divided into blocks of 1024 bytes each.
-XThe functions in "blk.c" maintain a cache of the five most recently used blocks,
-Xto minimize file I/O.
-X.PP
-XWhen \*E starts up, the file is copied into the temporary file
-Xby the function \fBtmpstart()\fR in "tmp.c".
-XSmall amounts of extra space are inserted into the temporary file to
-Xinsure that no text lines cross block boundaries.
-XThis speeds up processing and simplifies storage management.
-XThe extra space is filled with NUL characters.
-Xthe input file must not contain any NULs, to avoid confusion.
-XThis also limits lines to a length of 1023 characters or less.
-X.PP
-XThe data blocks aren't necessarily stored in sequence.
-XFor example, it is entirely possible that the data block containing
-Xthe first lines of text will be stored after the block containing the
-Xlast lines of text.
-X.PP
-XIn RAM, \*E maintains two lists: one that describes the "proper"
-Xorder of the disk blocks, and another that records the line number of
-Xthe last line in each block.
-XWhen \*E needs to fetch a given line of text, it uses these tables
-Xto locate the data block which contains that line.
-X.PP
-XBefore each change is made to the file, these lists are copied.
-XThe copies can be used to "undo" the change.
-XAlso, the first list
-X-- the one that lists the data blocks in their proper order --
-Xis written to the first data block of the temp file.
-XThis list can be used during file recovery.
-X.PP
-XWhen blocks are altered, they are rewritten to a \fIdifferent\fR block in the file,
-Xand the order list is updated accordingly.
-XThe original block is left intact, so that "undo" can be performed easily.
-X\*E will eventually reclaim the original block, when it is no longer needed.
-X.NH 2
-XImplementation of Editing
-X.PP
-XThere are three basic operations which affect text:
-X.ID
-X\(bu delete text      - delete(from, to)
-X\(bu add text - add(at, text)
-X\(bu yank text        - cut(from, to)
-X.DE
-X.PP
-XTo yank text, all text between two text positions is copied into a cut buffer.
-XThe original text is not changed.
-XTo copy the text into a cut buffer,
-Xyou need only remember which physical blocks that contain the cut text,
-Xthe offset into the first block of the start of the cut,
-Xthe offset into the last block of the end of the cut,
-Xand what kind of cut it was.
-X(Cuts may be either character cuts or line cuts;
-Xthe kind of a cut affects the way it is later "put".)
-XYanking is implemented in the function \fBcut()\fR,
-Xand pasting is implemented in the function \fBpaste()\fR.
-XThese functions are defined in "cut.c".
-X.PP
-XTo delete text, you must modify the first and last blocks, and
-Xremove any reference to the intervening blocks in the header's list.
-XThe text to be deleted is specified by two marks.
-XThis is implemented in the function \fBdelete()\fR.
-X.PP
-XTo add text, you must specify
-Xthe text to insert (as a NUL-terminated string)
-Xand the place to insert it (as a mark).
-XThe block into which the text is to be inserted may need to be split into
-Xas many as four blocks, with new intervening blocks needed as well...
-Xor it could be as simple as modifying a single block.
-XThis is implemented in the function \fBadd()\fR.
-X.PP
-XThere is also a \fBchange()\fR function,
-Xwhich generally just calls delete() and add().
-XFor the special case where a single character is being replaced by another
-Xsingle character, though, change() will optimize things somewhat.
-XThe add(), delete(), and change() functions are all defined in "modify.c".
-X.PP
-XThe \fBinput()\fR function reads text from a user and inserts it into the file.
-XIt makes heavy use of the add(), delete(), and change() functions.
-XIt inserts characters one at a time, as they are typed.
-X.PP
-XWhen text is modified, an internal file-revision counter, called \fBchanges\fR,
-Xis incremented.
-XThis counter is used to detect when certain caches are out of date.
-X(The "changes" counter is also incremented when we switch to a different file,
-Xand also in one or two similar situations -- all related to invalidating caches.)
-X.NH 2
-XMarks and the Cursor
-X.PP
-XMarks are places within the text.
-XThey are represented internally as 32-bit values which are split
-Xinto two bitfields:
-Xa line number and a character index.
-XLine numbers start with 1, and character indexes start with 0.
-XLines can be up to 1023 characters long, so the character index is 10 bits
-Xwide and the line number fills the remaining 22 bits in the long int.
-X.PP
-XSince line numbers start with 1,
-Xit is impossible for a valid mark to have a value of 0L.
-X0L is therefore used to represent unset marks.
-X.PP
-XWhen you do the "delete text" change, any marks that were part of
-Xthe deleted text are unset, and any marks that were set to points
-Xafter it are adjusted.
-XMarks are adjusted similarly after new text is inserted.
-X.PP
-XThe cursor is represented as a mark.
-X.NH 2
-XColon Command Interpretation
-X.PP
-XColon commands are parsed, and the command name is looked up in an array
-Xof structures which also contain a pointer to the function that implements
-Xthe command, and a description of the arguments that the command can take.
-XIf the command is recognized and its arguments are legal,
-Xthen the function is called.
-X.PP
-XEach function performs its task; this may cause the cursor to be
-Xmoved to a different line, or whatever.
-X.NH 2
-XScreen Control
-X.PP
-XIn input mode or visual command mode,
-Xthe screen is redrawn by a function called \fBredraw()\fR.
-XThis function is called in the getkey() function before each keystroke is
-Xread in, if necessary.
-X.PP
-XRedraw() write to the screen via a package which looks like the "curses"
-Xlibrary, but isn't.
-XIt is actually much simpler.
-XMost curses operations are implemented as macros which copy characters
-Xinto a large I/O buffer, which is then written with a single large
-Xwrite() call as part of the refresh() operation.
-X.PP
-X(Note: Under MS-DOS, the pseudo-curses macros check to see whether you're
-Xusing the pcbios interface.  If you are, then the macros call functions
-Xin "pc.c" to implement screen updates.)
-X.PP
-XThe low-level functions which modify text (namely add(), delete(), and change())
-Xsupply redraw() with clues to help redraw() decide which parts of the
-Xscreen must be redrawn.
-XThe clues are given via a function called \fBredrawrange()\fR.
-X.PP
-XMost EX commands use the pseudo-curses package to perform their output,
-Xlike redraw().
-X.PP
-XThere is also a function called \fBmsg()\fR which uses the same syntax as printf().
-XIn EX mode, msg() writes message to the screen and automatically adds a
-Xnewline.
-XIn VI mode, msg() writes the message on the bottom line of the screen
-Xwith the "standout" character attribute turned on.
-X.NH 2
-XOptions
-X.PP
-XFor each option available through the ":set" command,
-X\*E contains a character array variable, named "o_\fIoption\fR".
-XFor example, the "lines" option uses a variable called "o_lines".
-X.PP
-XFor boolean options, the array has a dimension of 1.
-XThe first (and only) character of the array will be NUL if the
-Xvariable's value is FALSE, and some other value if it is TRUE.
-XTo check the value, just by dereference the array name,
-Xas in "if (*o_autoindent)".
-X.PP
-XFor number options, the array has a dimension of 3.
-XThe array is treated as three unsigned one-byte integers.
-XThe first byte is the current value of the option.
-XThe second and third bytes are the lower and upper bounds of that
-Xoption.
-X.PP
-XFor string options, the array usually has a dimension of about 60
-Xbut this may vary.
-XThe option's value is stored as a normal NUL-terminated string.
-X.PP
-XAll of the options are declared in "opts.c".
-XMost are initialized to their default values;
-Xthe \fBinitopts()\fR function is used to perform any environment-specific
-Xinitialization.
-X.NH 2
-XPortability
-X.PP
-XTo improve portability, \*E collects as many of the system-dependent
-Xdefinitions as possible into the "config.h" file.
-XThis file begins with some preprocessor instructions which attempt to
-Xdetermine which compiler and operating system you have.
-XAfter that, it conditionally defines some macros and constants for your system.
-X.PP
-XOne of the more significant macros is \fBttyread()\fR.
-XThis macro is used to read raw characters from the keyboard, possibly
-Xwith timeout.
-XFor UNIX systems, this basically reads bytes from stdin.
-XFor MSDOS, TOS, and OS9, ttyread() is a function defined in curses.c.
-XThere is also a \fBttywrite()\fR macro.
-X.PP
-XThe \fBtread()\fR and \fBtwrite()\fR macros are versions of read() and write() that are
-Xused for text files.
-XOn UNIX systems, these are equivelent to read() and write().
-XOn MS-DOS, these are also equivelent to read() and write(),
-Xsince DOS libraries are generally clever enough to convert newline characters
-Xautomatically.
-XFor Atari TOS, though, the MWC library is too stupid to do this,
-Xso we had to do the conversion explicitly.
-X.PP
-XOther macros may substitute index() for strchr(), or bcopy() for memcpy(),
-Xor map the "void" data type to "int", or whatever.
-X.PP
-XThe file "tinytcap.c" contains a set of functions that emulate the termcap
-Xlibrary for a small set of terminal types.
-XThe terminal-specific info is hard-coded into this file.
-XIt is only used for systems that don't support real termcap.
-XAnother alternative for screen control can be seen in
-Xthe "curses.h" and "pc.c" files.
-XHere, macros named VOIDBIOS and CHECKBIOS are used to indirectly call
-Xfunctions which perform low-level screen manipulation via BIOS calls.
-X.PP
-XThe stat() function must be able to come up with UNIX-style major/minor/inode
-Xnumbers that uniquely identify a file or directory.
-X.PP
-XPlease try to keep you changes localized,
-Xand wrap them in #if/#endif pairs,
-Xso that \*E can still be compiled on other systems.
-XAnd PLEASE let me know about it, so I can incorporate your changes into
-Xmy latest-and-greatest version of \*E.
-/
-echo x - intro.ms
-sed '/^X/s///' > intro.ms << '/'
-X.Go 1 "INTRODUCTION"
-X.PP
-X\*E is a clone of vi/ex, the standard UNIX editor.
-X\*E supports nearly all of the vi/ex commands,
-Xin both visual mode and colon mode.
-X.PP
-XLike vi/ex, \*E stores most of the text in a temporary file, instead of RAM.
-XThis allows it to edit files that are too large to fit
-Xin a single process' data space.
-XAlso, the edit buffer can survive a power failure or crash.
-X.PP
-X\*E runs under BSD UNIX, AT&T SysV UNIX, Minix, MS-DOS, Atari TOS,
-XCoherent, OS9/68000, VMS and AmigaDos.
-XThe next version is also expected to add MS-Windows, OS/2 and MacOS.
-XContact me before you start porting it to some other OS,
-Xbecause somebody else may have already done it for you.
-X.PP
-X\*E is freely redistributable, in either source form or executable form.
-XThere are no restrictions on how you may use it.
-X.NH 2
-XCompiling
-X.PP
-XSee the "Versions" section of this manual for instructions on how to compile
-X\*E.
-X.PP
-XIf you want to port \*E to another O.S. or compiler, then
-Xyou should start be reading the "Portability" part of the "Internal" section.
-X.NH 2
-XOverview of \*E
-X.PP
-XThe user interface of \*E/vi/ex is weird.
-XThere are two major command modes in \*E, and a few text input modes as well.
-XEach command mode has a command which allows you to switch to the other mode.
-X.PP
-XYou will probably use the \fIvisual command mode\fR
-Xmost of the time.
-XThis is the mode that \*E normally starts up in.
-X.PP
-XIn visual command mode, the entire screen is filled with lines of text
-Xfrom your file.
-XEach keystroke is interpretted as part of a visual command.
-XIf you start typing text, it will \fInot\fR be inserted,
-Xit will be treated as part of a command.
-XTo insert text, you must first give an "insert text" command.
-XThis will take some getting used to.
-X(An alternative exists.
-XLookup the "inputmode" option.)
-X.PP
-XThe \fIcolon mode\fR is quite different.
-X\*E displays a ":" character on the bottom line of the screen, as a prompt.
-XYou are then expected to type in a command line and hit the <Return> key.
-XThe set of commands recognized in the colon mode is different
-Xfrom visual mode's.
-/
-echo x - options.ms
-sed '/^X/s///' > options.ms << '/'
-X.Go 5 "OPTIONS"
-X.PP
-XOptions may be set or examined via the colon command "set".
-XThe values of options will affect the operation of later commands.
-X.PP
-XFor convenience, options have both a long descriptive name and a short name
-Xwhich is easy to type.
-XYou may use either name interchangably.
-XI like the short names, myself.
-X.PP
-XThere are three types of options: Boolean, string, and numeric.
-XBoolean options are made TRUE by giving the name of the option as an
-Xargument to the "set" command;
-Xthey are made FALSE by prefixing the name with "no".
-XFor example, "set autoindent" makes the autoindent option TRUE,
-Xand "set noautoindent" makes it FALSE.
-X\*E also allows boolean options to be toggled by prefixing the name with "neg".
-XSo, ":map g :set neglist^M" will cause the <g> key to alternately toggle the
-X"list" option on and off.
-X(The "neg" prefix is an extension; the real vi doesn't support it.)
-X.PP
-XTo change the value of a string or numeric option, pass the "set" command
-Xthe name of the option, followed by an "=" sign and the option's new value.
-XFor example, "set tabstop=8" will give the tabstop option a value of 8.
-XFor string options, you may enclose the new value in quotes.
-X.LD
-X.ta 1.9i 2.4i 3.8i
-X.ps +2
-X\fBNAMES      TYPE    DEFAULT MEANING\fP
-X.ps
-Xautoindent, ai        Bool    noai    auto-indent during input
-Xautoprint, ap Bool    ap      in EX, print the current line
-Xautotab, at   Bool    at      auto-indent allowed to use tabs?
-Xautowrite, aw Bool    noaw    auto-write when switching files
-Xbeautify,  bf Bool    nobf    strip control chars from file?
-Xcharattr, ca  Bool    noca    interpret \\fX sequences?
-Xcc, cc        Str     cc="cc -c"      name of the C compiler
-Xcolumns, co   Num     co=80   width of the screen
-Xdigraph, dig  Bool    nodig   recognize digraphs?
-Xdirectory, dir        Str     dir="/usr/tmp"  where tmp files are kept
-Xedcompatible, ed      Bool    noed    remember ":s//" options
-Xequalprg, ep  Bool    ep="fmt"        program to run for = operator
-Xerrorbells, eb        Bool    eb      ring bell on error
-Xexrc, exrc    Bool    noexrc  read "./.exrc" file?
-Xexrefresh, er Bool    er      write lines indiviually in EX
-Xflash, vbell  Bool    flash   use visible alternative to bell
-Xflipcase, fc  Str     fc=""   non-ASCII chars flipped by ~
-Xhideformat, hf        Bool    hf      hide text formatter commands
-Xignorecase, ic        Bool    noic    upper/lowercase match in search
-Xinputmode, im Bool    noim    start vi in insert mode?
-Xkeytime, kt   Num     kt=2    timeout for mapped key entry
-Xkeywordprg, kp        Str     kp="ref"        full pathname of shift-K prog
-Xlines, ln     Num     ln=25   number of lines on the screen
-Xlist, li      Bool    noli    display lines in "list" mode
-Xmagic, ma     Bool    ma      use regular expression in search
-Xmake, mk      Str     mk="make"       name of the "make" program
-Xmesg, ms      Bool    ms      allow messages from other users?
-Xmodelines, ml Bool    noml    are modelines processed?
-Xmore, more    Bool    more    pause between messages?
-Xnovice, nov   Bool    nonovice        set options for ease of use
-Xparagraphs, para      Str     para="PPppIPLPQP"       names of "paragraph" nroff cmd
-Xprompt, pr    Bool    pr      show ':' prompt in \fIex\fR mode
-Xreadonly, ro  Bool    noro    prevent overwriting of orig file
-Xremap, rem    Bool    remap   allow key maps to call key maps
-Xreport, re    Num     re=5    report when 5 or more changes
-Xruler, ru     Bool    noru    display line/column numbers
-Xscroll, sc    Num     sc=12   scroll amount for ^U and ^D
-Xsections, sect        Str     sect="NHSHSSSEse"       names of "section" nroff cmd
-Xshell, sh     Str     sh="/bin/sh"    full pathname of the shell
-Xshowmatch, sm Bool    nosm    show matching ()[]{}
-Xshowmode, smd Bool    nosmd   say when we're in input mode
-Xshiftwidth, sw        Num     sw=8    shift amount for < and >
-Xsidescroll, ss        Num     ss=8    amount of sideways scrolling
-Xsync, sy      Bool    nosy    call sync() often
-Xtabstop, ts   Num     ts=8    width of tab characters
-Xtaglength, tl Num     tl=0    significant chars in tag name
-Xterm, te      Str     te="$TERM"      name of the termcap entry
-Xterse, tr     Bool    notr    give shorter error messages
-Xtimeout, to   Bool    to      distinguish <esc> from <arrow>?
-Xwarn, wa      Bool    wa      warn for ! if file modified
-Xwindow, wi    Num     wi=24   lines to redraw after long move
-Xwrapmargin, wm        Num     wm=0    wrap long lines in input mode
-Xwrapscan, ws  Bool    ws      at EOF, searches wrap to line 1
-Xwriteany, wr  Bool    nowr    allow :w to clobber files
-X.DE
-X.TA
-X.ne 6
-X.IP "autoindent, ai"
-XDuring input mode, the autoindent option will cause each added line
-Xto begin with the same amount of leading whitespace as the line above it.
-XWithout autoindent, added lines are initially empty.
-X.IP "autoprint, ap"
-XThis option only affects EX mode.
-XIf the autoprint option on,
-Xand either the cursor has moved to a different line
-Xor the previous command modified the file,
-Xthen \*E will print the current line.
-X.IP "autotab, at"
-XThis option affects the behaviour of the autoindent mode.
-XIf autoindent is turned off, then autotab has no effect.
-X.IP
-XWhen autotab is turned on, elvis will use a mixture of spaces and tabs
-Xto create the proper amount of indentation.
-XThis is the default.
-X.IP
-XWhen autotab is turned off, elvis will only use spaces for auto-indent.
-X\*E will still insert a real tab character when you hit the <Tab> key, though;
-Xthe autotab option only affects \fIautomatic\fR indentation.
-X.IP "autowrite, aw"
-XWhen you're editing one file and decide to switch to another
-X\- via the :tag command, or :next command, perhaps \-
-Xif your current file has been modified,
-Xthen \*E will normally print an error message and refuse to switch.
-X.IP
-XHowever, if the autowrite option is on,
-Xthen \*E will write the modified version of the current file
-Xand successfully switch to the new file.
-X.IP "beautify, bf"
-XThis option causes all control characters to be deleted from the text file,
-Xat the time when you start editing it.
-XIf you're already editing a file when you turn on the beautify option,
-Xthen that file won't be affected.
-X.IP cc
-XThe :cc command runs the C compiler.
-XThis option should be set to the name of your compiler.
-X.IP "charattr, ca"
-XMany text formatting programs allow you to designate portions of
-Xyour text to be underlined, italicized, or boldface by embedding
-Xthe special strings \\fU, \\fI, and \\fB in your text.
-XThe special string \\fP marks the end of underlined or boldface text.
-X.IP
-X\*E normally treats those special strings just like any other text.
-X.IP
-XHowever, if the charattr option is on, then \*E will interpret
-Xthose special strings correctly,
-Xto display underlined or boldface text on the screen.
-X(This only works, of course, if your terminal can display
-Xunderlined and boldface, and if the TERMCAP entry says how to do it.)
-X.IP "columns, co"
-XThis option shows how wide your screen is.
-X.IP "digraph, dig"
-XThis option is used to enable/disable recognition of digraphs.
-XThe default value is nodigraph, which means that digraphs will not be
-Xrecognized.
-X.IP "directory, dir"
-X\*E stores text in temporary files.
-XThis option allows you to control which directory those temporary files will
-Xappear in.
-XThe default is /usr/tmp.
-X.IP
-XThis option can only be set in a .exrc file;
-Xafter that, \*E will have already started making temporary files
-Xin some other directory, so it would be too late.
-X.IP "edcompatible, ed"
-XThis option affects the behaviour of the ":s/regexp/text/options" command.
-XIt is normally off (:se noed) which causes all of the substitution options
-Xto be off unless explicitly given.
-X.IP
-XHowever, with edcompatible on (:se ed), the substitution command remembers
-Xwhich options you used last time.
-XThose same options will continue to be used until you change them.
-XIn edcompatible mode, when you explicitly give the name of a
-Xsubstitution option, you will toggle the state of that option.
-X.IP
-XThis all seems very strange to me, but its implementation was almost free
-Xwhen I added the ":&" command to repeat the previous substitution,
-Xso there it is.
-X.IP "equalprg, ep"
-XThis holds the name & arguments of the external filter program
-Xused the the visual = operator.
-XThe defualt value is "fmt",
-Xso the = operator will adjust line breaks in text.
-X.IP "errorbells, eb"
-X\*E normally rings a bell when you do something wrong.
-XThis option lets you disable the bell.
-X.IP exrc
-XThis option specifies whether a .exrc file in the current directory
-Xshould be executed.
-XBy default, this option is off (":set noexrc") which prevents elvis from
-Xexecuting .exrc in the current directory.
-XIf the .exrc file in your home directory turns this option on (":set exrc")
-Xthen the \*E will attempt to execute the .exrc file in the current directory.
-X.IP
-XThis option exist mainly for security reasons.
-XA mean-spirited person could do something like
-X.br
-X      echo >/tmp/.exrc '!rm -rf $HOME'
-X.br
-Xand then anybody who attempted to edit or view a file in the /tmp directory
-Xwould lose most of their files.
-XWith the exrc option turned off, this couldn't happen to you.
-X.IP "exrefresh, er"
-XThe EX mode of \*E writes many lines to the screen.
-XYou can make \*E either write each line to the screen separately,
-Xor save up many lines and write them all at once.
-X.IP
-XThe exrefresh option is normally on, so each line is written to the
-Xscreen separately.
-X.IP
-XYou may wish to turn the exrefresh option off (:se noer) if the
-X"write" system call is costly on your machine, or if you're using a
-Xwindowing environment.
-X(Windowing environments scroll text a lot faster when you write
-Xmany lines at once.)
-X.IP
-XThis option has no effect in visual command mode or input mode.
-X.IP "flash, vbell"
-XIf your termcap entry describes a visible alternative to ringing
-Xyour terminal's bell, then this option will say whether the visible
-Xversion gets used or not.
-XNormally it will be.
-X.IP
-XIf your termcap does NOT include a visible bell capability,
-Xthen the flash option will be off, and you can't turn it on.
-X.IP "flipcase, fc"
-XThe flipcase option allows you to control how the non-ASCII characters are
-Xaltered by the "~" command.
-X.IP
-XThe string is divided into pairs of characters.
-XWhen "~" is applied to a non-ASCII character,
-X\*E looks up the character in the flipcase string to see which pair it's in,
-Xand replaces it by the other character of the pair.
-X.IP "hideformat, hf"
-XMany text formatters require you to embed format commands in your text,
-Xon lines that start with a "." character.
-X\*E normally displays these lines like any other text,
-Xbut if the hideformat option is on,
-Xthen format lines are displayed as blank lines.
-X.IP "ignorecase, ic"
-XNormally, when \*E searches for text, it treats uppercase letters
-Xas being different for lowercase letters.
-X.IP
-XWhen the ignorecase option is on, uppercase and lowercase are treated as equal.
-X.IP "inputmode, im"
-XThis option allows you to have \*E start up in insert mode.
-XYou can still exit insert mode at any time by hitting the ESC key, as usual.
-XUsually, this option would be set in your ".exrc" file.
-X.IP "keytime, kt"
-XThe arrow keys of most terminals send a multi-character sequence.
-XIt takes a measurable amount of time for these sequences to be transmitted.
-XThe keytime option allows you to control the maximum amount of time
-Xto allow for an arrow key (or other mapped key) to be received in full.
-X.IP
-XOn most systems, the setting is the number of tenths of a second to allow
-Xbetween characters.
-XOn some other systems, the setting is in whole seconds.
-X.IP
-XTry to avoid setting keytime=1.
-XMost systems just count clock beats, so if you tried to read a character
-Xshortly before a clock beat, you could allow almost no time at all for
-Xreading the characters.
-XFor higher keytime settings, the difference is less critical.
-X.IP
-XIf your system's response time is poor, you might want to increase the keytime.
-XIn particular, I've found that when keystrokes must be sent through a network
-X(via X windows, rlogin, or telnet, for example) the keytime should be set to
-Xat least 1 second.
-X.IP
-XAs a special case,
-Xyou can set keytime to 0 to disable this time limit stuff altogether.
-XThe big problem here is:
-XIf your arrow keys' sequences start with an ESC,
-Xthen every time you hit your ESC key \*E will wait... and wait...
-Xto see if maybe that ESC was part of an arrow key's sequence.
-X.IP
-XNOTE: this option is a generalization of the timeout option of the real vi.
-X.IP "keywordprg, kp"
-X\*E has a special keyword lookup feature.
-XYou move the cursor onto a word, and hit shift-K,
-Xand \*E uses another program to look up the word
-Xand display information about it.
-X.IP
-XThis option says which program gets run.
-X.IP
-XThe default value of this option is "ref",
-Xwhich is a program that looks up the definition of a function in C.
-XIt looks up the function name in a file called "refs" which is created by ctags.
-X.IP
-XYou can subtitute other programs, such as an English dictionary program
-Xor the online manual.
-X\*E runs the program, using the keyword as its only argument.
-XThe program should write information to stdout.
-XThe program's exit status should be 0, unless you want \*E to print
-X"<<< failed >>>".
-X.IP "lines, ln"
-XThis option says how many lines you screen has.
-X.IP "list, li"
-XIn nolist mode (the default), \*E displays text in a "normal" manner
-X-- with tabs expanded to an appropriate number of spaces, etc.
-X.IP
-XHowever, sometimes it is useful to have tab characters displayed differently.
-XIn list mode, tabs are displayed as "^I",
-Xand a "$" is displayed at the end of each line.
-X.IP "magic, ma"
-XThe search mechanism in \*E can accept "regular expressions"
-X-- strings in which certain characters have special meaning.
-X.IP
-XThe magic option is normally on, which causes these characters to be treated
-Xspecially.
-X.IP
-XIf you turn the magic option off (:se noma),
-Xthen all characters except ^ and $ are treated literally.
-X^ and $ retain their special meanings regardless of the setting of magic.
-X.IP "make, mk"
-XThe :make command runs your "make" program.
-XThis option defines the name of your "make" program.
-X.IP mesg
-XWith the real vi, running under real UNIX,
-X":set nomesg" would prevent other users from sending you messages.
-X\*E ignores it, though.
-X.IP "modelines, ml"
-X\*E supports modelines.
-XModelines are lines near the beginning or end of your text file which
-Xcontain "ex:yowza:",
-Xwhere "yowza" is any EX command.
-XA typical "yowza" would be something like "set ts=5 ca kp=spell wm=15".
-XOther text may also appear on a modeline,
-Xso you can place the "ex:yowza:" in a comment:
-X.br
-X.ID
-X/* ex:set sw=4 ai: */
-X.DE
-X.IP
-XNormally these lines are ignored, for security reasons,
-Xbut if you have "set modelines" in your .exrc file
-Xthen "yowza" is executed.
-X.IP "novice, nov"
-XThe command ":set novice" is equivelent to ":set nomagic report=1 showmode".
-X.IP "paragraphs, pa"
-XThe { and } commands move the cursor forward or backward in increments
-Xof one paragraph.
-XParagraphs may be separated by blank lines, or by a "dot" command of
-Xa text formatter.
-XDifferent text formatters use different "dot" commands.
-XThis option allows you to configure \*E to work with your text formatter.
-X.IP
-XIt is assumed that your formatter uses commands that start with a
-X"." character at the front of a line,
-Xand then have a one- or two-character command name.
-X.IP
-XThe value of the paragraphs option is a string in which each pair
-Xof characters is one possible form of your text formatter's paragraph
-Xcommand.
-X.IP "more"
-XWhen \*E must display a sequence of messages at the bottom line of the screen
-Xin visual mode, it normally pauses after all but the last one, so you have
-Xtime to read them all.
-X.IP
-XIf you turn off the "more" option, then \*E will not pause.
-XThis means you can only read the last message, but it is usually the most
-Ximportant one anyway.
-X.IP "prompt, pr"
-XIf you ":set noprompt", then \*E will no longer emit a ':' when it
-Xexpects you to type in an \fIex\fR command.
-XThis is slightly useful if you're using an astonishingly slow UNIX machine,
-Xbut the rest of us can just ignore this one.
-X.IP "readonly, ro"
-XNormally, \*E will let you write back any file to which you have
-Xwrite permission.
-XIf you don't have write permission, then you can only write the changed
-Xversion of the file to a \fIdifferent\fP file.
-X.IP
-XIf you set the readonly option,
-Xthen \*E will pretend you don't have write permission to \fIany\fP file you edit.
-XIt is useful when you really only mean to use \*E to look at a file,
-Xnot to change it.
-XThis way you can't change it accidentally.
-X.IP
-XThis option is normally off, unless you use the "view" alias of \*E.
-X"View" is like "vi" except that the readonly option is on.
-X.IP "remap"
-XThe ":map" command allows you to convert one key sequence into another.
-XThe remap option allows you to specify what should happen if portions of
-Xthat other sequence are also in the map table.
-XIf remap is on, then those portions will also be mapped, just as if they
-Xhad been typed on the keyboard.
-XIf remap is off, then the matching portions will not be mapped.
-X.IP
-XFor example, if you enter the commands ":map A B" and ":map B C",
-Xthen when remap is on, A will be converted to C.
-XBut when remap is off, A will be converted only to B.
-X.IP "report, re"
-XCommands in \*E may affect many lines.
-XFor commands that affect a lot of lines, \*E will output a message saying
-Xwhat was done and how many lines were affected.
-XThis option allows you to define what "a lot of lines" means.
-XThe default is 5, so any command which affects 5 or more lines will cause
-Xa message to be shown.
-X.IP "ruler, ru"
-XThis option is normally off.
-XIf you turn it on, then \*E will constantly display the line/column numbers
-Xof the cursor, at the bottom of the screen.
-X.IP "scroll, sc"
-XThe ^U and ^D keys normally scroll backward or forward by half a screenful,
-Xbut this is adjustable.
-XThe value of this option says how many lines those keys should scroll by.
-XIf you invoke ^U or ^D with a count argument (for example, "33^D") then
-Xthis option's value is set to the count.
-X.IP "sections, se"
-XThe [[ and ]] commands move the cursor backward or forward in increments of
-X1 section.
-XSections may be delimited by a { character in column 1
-X(which is useful for C source code)
-Xor by means of a text formatter's "dot" commands.
-X.IP
-XThis option allows you to configure \*E to work with your text formatter's
-X"section" command, in exectly the same way that the paragraphs option makes
-Xit work with the formatter's "paragraphs" command.
-X.IP "shell, sh"
-XWhen \*E forks a shell
-X(perhaps for the :! or :shell commands)
-Xthis is the program that is uses as a shell.
-XThis is "/bin/sh" by default,
-Xunless you have set the SHELL (or COMSPEC, for MS-DOS) environment variable,
-Xit which case the default value is copied from the environment.
-X.IP "shiftwidth, sw"
-XThe < and > commands shift text left or right by some uniform number of columns.
-XThe shiftwidth option defines that "uniform number".
-XThe default is 8.
-X.IP "showmatch, sm"
-XWith showmatch set,
-Xin input mode every time you hit one of )}],
-X\*E will momentarily move the cursor to the matching ({[.
-X.IP "showmode, smd"
-XIn visual mode, it is easy to forget whether you're in the visual command mode
-Xor input/replace mode.
-XNormally, the showmode option is off, and you haven't a clue as to which mode
-Xyou're in.
-XIf you turn the showmode option on, though, a little message will appear in the
-Xlower right-hand corner of your screen, telling you which mode you're in.
-X.IP "sidescroll, ss"
-XFor long lines, \*E scrolls sideways.
-X(This is different from the real vi,
-Xwhich wraps a single long line onto several rows of the screen.)
-X.IP
-XTo minimize the number of scrolls needed,
-X\*E moves the screen sideways by several characters at a time.
-XThe value of this option says how many characters' widths to scroll at a time.
-X.IP
-XGenerally, the faster your screen can be redrawn,
-Xthe lower the value you will want in this option.
-X.IP "sync, sy"
-XIf the system crashes during an edit session, then most of your work
-Xcan be recovered from the temporary file that \*E uses to store
-Xchanges.
-XHowever, sometimes the OS will not copy changes to the
-Xhard disk immediately, so recovery might not be possible.
-XThe [no]sync option lets you control this.
-X.IP
-XIn nosync mode (which is the default, for UNIX), \*E lets the operating system
-Xcontrol when data is written to the disk.
-XThis is generally faster.
-X.IP
-XIn sync mode (which is the default for MS-DOS, AmigaDos, and Atari TOS),
-X\*E forces all changes out
-Xto disk every time you make a change.
-XThis is generally safer, but slower.
-XIt can also be a rather rude thing to do on a multi-user system.
-X.IP "tabstop, ts"
-XTab characters are normally 8 characters wide,
-Xbut you can change their widths by means of this option.
-X.IP "taglength, tl"
-XThis option allows you to specify how many characters of a tag's name
-Xmust match when performing tag lookup.
-XAs a special case, ":set taglength=0" means that all characters of a tag's
-Xname must match.
-X.IP
-XNote: some configurations of \*E don't support this option.
-X.IP "term, te"
-XThis read-only option shows the name of the termcap entry that
-X\*E is using for your terminal.
-X.IP "terse, tr"
-XThe real vi uses this option to select longer vs. shorter error messages.
-X\*E has only one set of error messages, though, so this option has no effect.
-X.IP "timeout, to"
-XThe command ":set notimeout" is equivelent to ":set keytime=0",
-Xand ":set timeout" is equivelent to ":set keytime=1".
-XThis affects the behaviour of the <Esc> key.
-XSee the discussion of the "keytime" option for more information.
-X.IP "warn, wa"
-XIf you have modified a file but not yet written it back to disk, then
-X\*E will normally print a warning before executing a ":!cmd" command.
-XHowever, in nowarn mode, this warning is not given.
-X.IP
-X\*E also normally prints a message after a successful search that
-Xwrapped at EOF.
-XThe [no]warn option can also disable this warning.
-X.IP "window, wi"
-XThis option controls how many lines are redrawn after a long move.
-X.IP
-XOn fast terminals, this is usually set to the number of rows that the
-Xterminal can display, minus one.
-XThis causes the entire screen to be filled with text around the cursor.
-X.IP
-XOn slow terminals, you may wish to reduce this value to about 7 or so.
-XThat way, if you're doing something like repeatedly hitting 'n' to search
-Xfor each occurrence of some string and trying to find a particular occurrence,
-Xthen you don't need to wait as long for \*E to redraw the screen after each
-Xsearch.
-X.IP "wrapmargin, wm"
-XNormally (with wrapmargin=0) \*E will let you type in extremely long
-Xlines, if you wish.
-X.IP
-XHowever, with warpmargin set to something other that 0 (wrapmargin=10
-Xis nice), \*E will automatically cause long lines to be "wrapped"
-Xon a word break for lines come too close to the right-hand margin.
-XFor example: On an 80-column screen, ":set wm=10" will cause lines to
-Xwrap when their length exceeds 70 columns.
-X.IP "wrapscan, ws"
-XNormally, when you search for something, \*E will find it no matter
-Xwhere it is in the file.
-X\*E starts at the cursor position, and searches forward.
-XIf \*E hits EOF without finding what you're looking for,
-Xthen it wraps around to continue searching from line 1.
-XIf you turn off the wrapscan option (:se nows),
-Xthen when \*E hits EOF during a search, it will stop and say so.
-X.IP "writeany, wr"
-XWith "writeany" turned off, elvis will prevent you from accidentally
-Xoverwriting a file.
-XFor example, if "foo" exists then ":w foo" will fail.
-XIf you turn on the "writeany" option, then ":w foo" will work.
-X.IP
-XRegardless of the setting of "writeany", though, ":w! foo" will work.
-XThe '!' forces the ":w" command to write the file unless the operating system
-Xwon't allow it.
-/
-echo x - question.ms
-sed '/^X/s///' > question.ms << '/'
-X.nr Qn 0 1
-X.de QQ
-X.sp
-X.IP \fB\\n+(Qn) 0.3i
-X..
-X.de AA
-X.IP \fR 0.75i
-X..
-X.Go 13 "QUESTIONS & ANSWERS"
-X.QQ
-XHow can I make elvis run faster under DOS?
-X.AA
-XThere are several things you can do.
-XThe first thing to do is get a good screen driver such as NANSI.SYS.
-XThis can speed up screen redrawing by as much as a factor of eight!
-XThe DOS-specific part of section 12 tells you how to do this.
-X.AA
-XYou might also consider reducing the size of the blocks that elvis uses.
-XYou'll need to recompile \*E to do this.
-XThe default BLKSIZE is 1024 byte for the DOS version of \*E, which means
-Xthat for each keystroke that you insert, elvis must shift an average of
-Xabout 500 bytes.
-XThat's a lot to ask from a little old 5MHz 8088.
-XA BLKSIZE of 512 bytes might be more appropriate.
-X.AA
-XIf you're \fIreally\fR desperate for more speed, you might want to make
-X\*E store its temporary files on a RAM disk.
-XHowever, this limits the size of the file you can edit, and it eliminates any
-Xchance you may have had to recover your work after a power failure
-Xor system crash, but it might be worth it; you decide.
-XTo do this, add ":set dir=R:\\" (or whatever your RAM disk's name is)
-Xto the \fIelvis.rc\fP file.
-X.AA
-XNext, consider turning off the "sync" option.
-XWhen the sync option is turned on, \*E will close the temporary file
-Xand reopen it after every change, in order to force DOS to update
-Xthe file's directory entry.
-XIf you put ":set nosync" into the \fIelvis.rc\fP file, then elvis will
-Xonly close the file when you start editing a different text file, or
-Xwhen you're exiting \*E.
-XConsequently, there is no chance that you'll be able to recover your
-Xchanges after a power failure... so if you're going to this, then you
-Xmight as well store the temp files on the RAM disk, too.
-X.QQ
-XWhere's the <Esc> key on a DEC keyboard?
-X.AA
-XI don't know.  Maybe the <F11> key?
-XYou could always use ":map!" to make some other key act like the <Esc> key.
-XIf all else fails, use <Control><[>.
-X.QQ
-XIs there a way to show which keys do what?
-X.AA
-XYes.  The command ":map" will show what each key does in command mode,
-Xand ":map!" (with an exclamation mark) shows what each key does in
-Xinput mode.
-X.AA
-XThe table is divided into three columns: the key's label, the characters
-Xthat it sends, and the characters that \*E pretends you typed.
-X.QQ
-XHow can I make \*E display long lines like the real vi?
-X.AA
-XYou can't yet.
-XThe next version of \*E shouldsupport this, though.
-X.QQ
-XI can't recover my text [under MS-DOS or Atari TOS].
-XAccording to the directory listing, the temporary file is 0 bytes long.
-XWhat went wrong?
-X.AA
-XMS-DOS and TOS only update a file's directory entry when the file is closed.
-XIf the system crashes while the file is still open, then the file's length
-Xis stored as 0 bytes.
-XThe ":set sync" option is supposed to prevent this;
-Xyou probably turned it off in the interest of speed, right?
-X.AA
-XUnder MS-DOS [I don't know about TOS], you should delete the empty
-Xtemporary file, and then run CHKDSK/F.
-XThis \fImight\fP find the data that belonged in the empty file,
-Xand place it in a new file with a name like "000001.CHK" -- something like that.
-XYou can then try to extract the text from that temporary file by giving the
-Xcommand "elvprsv -R 000001.chk >goodnews.txt".
-XIf you're lucky, then your text might be in GOODNEWS.TXT.
-X.QQ
-XWhat is the most current version of \*E?
-X.AA
-XEach version of \*E that is released to the public has a version number
-Xof the form "number point number".
-XAs I write this, the most current version of elvis is 1.5.
-X.AA
-XThe intermediate steps between one release and the next are labeled with
-Xthe \fInext\fP version number, with a letter appended.
-XFor example, after 1.4 was released, I started working on 1.5a.
-XI am currently working on 2.0a.
-XWhen \*E reaches a stable state, I'll call it 2.0 and release it.
-X.AA
-XSometimes a beta-test version of elvis will be available via anonymous FTP
-Xfrom m2xenix.psg.com, in the directory "pub/elvis/beta".
-X.QQ
-XI only got executables, but now I want the source code.
-XWhere can I get it?
-X.AA
-XIf you have access to the Internet, then you should be able to fetch it
-Xfrom one of the public archives such as \fBplains.nodak.edu\fP.
-XIt is accessible via anonymous FTP, or via an email server named
-X"archive-server@plains.nodak.edu".
-XElvis is located in the directory "/pub/Minix/all.contrib".
-X.AA
-XI will also offer it to the C Users' Group.
-XThey sell C source code for us$8 per diskette
-X(or slightly more outside  North  America).
-XTheir phone number is (913) 841-1631,
-Xand their address is:
-X.ID
-XThe C Users' Group
-XPO Box 3127
-XLawrence KS 66046-0127
-X.DE
-X.QQ
-XIs this shareware, or public domain, or what?
-X.AA
-XIt is not public domain; it is copyrighted by me, Steve Kirkendall.
-XHowever, this particular version is freely redistributable, in either
-Xsource form or executable form.
-X(I would prefer that you give copies away for free, complete with the
-Xfull source code... but I'm not going to force you.)
-X.AA
-XIt is not shareware; you aren't expected to send me anything.
-XYou can use it without guilt.
-X.AA
-XIt is not "copylefted."
-XI hold a copyright, but currently I have not added any of the usual restrictions
-Xthat you would find on copylefted software.
-XIf people start doing really obnoxious things to \*E, then I will start
-Xadding restrictions to subsequent versions, but earlier versions won't
-Xbe affected.
-X(So far, everybody has been pretty good about this so no restrictions
-Xhave been necessary.)
-X.QQ
-XCan I reuse parts of your source code?
-X.AA
-XYes.  Please be careful, though, to make sure that the code really is mine.
-XSome of the code was contributed by other people, and I don't have the
-Xauthority to give you permission to use it.
-XThe author's name can be found near the top of each source file.
-XIf it says "Steve Kirkendall" then you may use it;
-Xotherwise, you'd better contact the author first.
-X.AA
-XPlease don't remove my name from the source code.
-XIf you modify the source, please make a note of that fact in a comment
-Xnear the top of the source code.
-XAnd, finally, please mention my name in your documentation.
-X.QQ
-XCan \*E work with non-ASCII files?
-X.AA
-X\*E can't edit binary files because it can't handle the NUL character,
-Xand because of line-length limitations.
-XHowever, it is 8-bit clean so you should be able to edit any European
-Xextended ASCII file without any surprises.
-X.AA
-X\*E has also been modified to work with 16-bit character sets.
-XYongguang Zhang (ygz@cs.purdue.edu) has created a Chinese version of \*E
-Xthat uses 16-bit characters and runs under cxterm (Chinese X-term)
-Xon X-windows systems.
-XJunichiro Itoh (itojun@foretune.co.jp) has modified \*E to edit Japanese
-Xtext under MS-DOS.
-/
-echo x - regexp.ms
-sed '/^X/s///' > regexp.ms << '/'
-X.Go 4 "REGULAR EXPRESSIONS"
-X
-X.PP
-X\*E uses regular expressions for searching and substututions.
-XA regular expression is a text string in which some characters have
-Xspecial meanings.
-XThis is much more powerful than simple text matching.
-X.SH
-XSyntax
-X.PP
-X\*E' regexp package treats the following one- or two-character
-Xstrings (called meta-characters) in special ways:
-X.IP "\\\\\\\\(\fIsubexpression\fP\\\\\\\\)" 0.8i
-XThe \\( and \\) metacharacters are used to delimit subexpressions.
-XWhen the regular expression matches a particular chunk of text,
-X\*E will remember which portion of that chunk matched the \fIsubexpression\fP.
-XThe :s/regexp/newtext/ command makes use of this feature.
-X.IP "^" 0.8i
-XThe ^ metacharacter matches the beginning of a line.
-XIf, for example, you wanted to find "foo" at the beginning of a line,
-Xyou would use a regular expression such as /^foo/.
-XNote that ^ is only a metacharacter if it occurs
-Xat the beginning of a regular expression;
-Xanyplace else, it is treated as a normal character.
-X.IP "$" 0.8i
-XThe $ metacharacter matches the end of a line.
-XIt is only a metacharacter when it occurs at the end of a regular expression;
-Xelsewhere, it is treated as a normal character.
-XFor example, the regular expression /$$/ will search for a dollar sign at
-Xthe end of a line.
-X.IP "\\\\\\\\<" 0.8i
-XThe \\< metacharacter matches a zero-length string at the beginning of
-Xa word.
-XA word is considered to be a string of 1 or more letters and digits.
-XA word can begin at the beginning of a line
-Xor after 1 or more non-alphanumeric characters.
-X.IP "\\\\\\\\>" 0.8i
-XThe \\> metacharacter matches a zero-length string at the end of a word.
-XA word can end at the end of the line
-Xor before 1 or more non-alphanumeric characters.
-XFor example, /\\<end\\>/ would find any instance of the word "end",
-Xbut would ignore any instances of e-n-d inside another word
-Xsuch as "calendar".
-X.IP "\&." 0.8i
-XThe . metacharacter matches any single character.
-X.IP "[\fIcharacter-list\fP]" 0.8i
-XThis matches any single character from the \fIcharacter-list\fP.
-XInside the \fIcharacter-list\fP, you can denote a span of characters
-Xby writing only the first and last characters, with a hyphen between
-Xthem.
-XIf the \fIcharacter-list\fP is preceded by a ^ character, then the
-Xlist is inverted -- it will match character that \fIisn't\fP mentioned
-Xin the list.
-XFor example, /[a-zA-Z]/ matches any letter, and /[^ ]/ matches anything
-Xother than a blank.
-X.IP "\\\\\\\\{\fIn\fP\\\\\\\\}" 0.8i
-XThis is a closure operator,
-Xwhich means that it can only be placed after something that matches a
-Xsingle character.
-XIt controls the number of times that the single-character expression
-Xshould be repeated.
-X.IP "" 0.8i
-XThe \\{\fIn\fP\\} operator, in particular, means that the preceding
-Xexpression should be repeated exactly \fIn\fP times.
-XFor example, /^-\\{80\\}$/ matches a line of eighty hyphens, and
-X/\\<[a-zA-Z]\\{4\\}\\>/ matches any four-letter word.
-X.IP "\\\\\\\\{\fIn\fP,\fIm\fP\\\\\\\\}" 0.8i
-XThis is a closure operator which means that the preceding single-character
-Xexpression should be repeated between \fIn\fP and \fIm\fP times, inclusive.
-XIf the \fIm\fP is omitted (but the comma is present) then \fIm\fP is
-Xtaken to be inifinity.
-XFor example, /"[^"]\\{3,5\\}"/ matches any pair of quotes which contains
-Xthree, four, or five non-quote characters.
-X.IP "*" 0.8i
-XThe * metacharacter is a closure operator which means that the preceding
-Xsingle-character expression can be repeated zero or more times.
-XIt is equivelent to \\{0,\\}.
-XFor example, /.*/ matches a whole line.
-X.IP "\\\\\\\\+" 0.8i
-XThe \\+ metacharacter is a closure operator which means that the preceding
-Xsingle-character expression can be repeated one or more times.
-XIt is equivelent to \\{1,\\}.
-XFor example, /.\\+/ matches a whole line, but only if the line contains
-Xat least one character.
-XIt doesn't match empty lines.
-X.IP "\\\\\\\\?" 0.8i
-XThe \\? metacharacter is a closure operator which indicates that the
-Xpreceding single-character expression is optional -- that is, that it
-Xcan occur 0 or 1 times.
-XIt is equivelent to \\{0,1\\}.
-XFor example, /no[ -]\\?one/ matches "no one", "no-one", or "noone".
-X.PP
-XAnything else is treated as a normal character which must exactly match
-Xa character from the scanned text.
-XThe special strings may all be preceded by a backslash to
-Xforce them to be treated normally.
-X.SH
-XSubstitutions
-X.PP
-XThe :s command has at least two arguments: a regular expression,
-Xand a substitution string.
-XThe text that matched the regular expression is replaced by text
-Xwhich is derived from the substitution string.
-X.br
-X.ne 15 \" so we don't mess up the table
-X.PP
-XMost characters in the substitution string are copied into the
-Xtext literally but a few have special meaning:
-X.LD
-X.ta 0.75i 1.3i
-X      &       Insert a copy of the original text
-X      ~       Insert a copy of the previous replacement text
-X      \\1     Insert a copy of that portion of the original text which
-X              matched the first set of \\( \\) parentheses
-X      \\2-\\9 Do the same for the second (etc.) pair of \\( \\)
-X      \\U     Convert all chars of any later & or \\# to uppercase
-X      \\L     Convert all chars of any later & or \\# to lowercase
-X      \\E     End the effect of \\U or \\L
-X      \\u     Convert the first char of the next & or \\# to uppercase
-X      \\l     Convert the first char of the next & or \\# to lowercase
-X.TA
-X.DE
-X.PP
-XThese may be preceded by a backslash to force them to be treated normally.
-XIf "nomagic" mode is in effect,
-Xthen & and ~ will be treated normally,
-Xand you must write them as \\& and \\~ for them to have special meaning.
-X.SH
-XOptions
-X.PP
-X\*E has two options which affect the way regular expressions are used.
-XThese options may be examined or set via the :set command.
-X.PP
-XThe first option is called "[no]magic".
-XThis is a boolean option, and it is "magic" (TRUE) by default.
-XWhile in magic mode, all of the meta-characters behave as described above.
-XIn nomagic mode, only ^ and $ retain their special meaning.
-X.PP
-XThe second option is called "[no]ignorecase".
-XThis is a boolean option, and it is "noignorecase" (FALSE) by default.
-XWhile in ignorecase mode, the searching mechanism will not distinguish between
-Xan uppercase letter and its lowercase form.
-XIn noignorecase mode, uppercase and lowercase are treated as being different.
-X.PP
-XAlso, the "[no]wrapscan" option affects searches.
-X.SH
-XExamples
-X.PP
-XThis example changes every occurence of "utilize" to "use":
-X.sp
-X.ti +1i
-X:%s/utilize/use/g
-X.PP
-XThis example deletes all whitespace that occurs at the end of a line anywhere
-Xin the file.
-X(The brackets contain a single space and a single tab.):
-X.sp
-X.ti +1i
-X:%s/[   ]\\+$//
-X.PP
-XThis example converts the current line to uppercase:
-X.sp
-X.ti +1i
-X:s/.*/\\U&/
-X.PP
-XThis example underlines each letter in the current line,
-Xby changing it into an "underscore backspace letter" sequence.
-X(The ^H is entered as "control-V backspace".):
-X.sp
-X.ti +1i
-X:s/[a-zA-Z]/_^H&/g
-X.PP
-XThis example locates the last colon in a line,
-Xand swaps the text before the colon with the text after the colon.
-XThe first \\( \\) pair is used to delimit the stuff before the colon,
-Xand the second pair delimit the stuff after.
-XIn the substitution text, \\1 and \\2 are given in reverse order
-Xto perform the swap:
-X.sp
-X.ti +1i
-X:s/\\(.*\\):\\(.*\\)/\\2:\\1/
-/
-echo x - termcap.ms
-sed '/^X/s///' > termcap.ms << '/'
-X.Go 10 "TERMCAP"
-X.PP
-X\*E uses fairly standard termcap fields for most things.
-XI invented the cursor shape names
-Xbut other than that there should be few surprises.
-X.SH
-XRequired numeric fields
-X.if n .ul 0
-X.ID
-X:co#: number of columns on the screen (chars per line)
-X:li#: number of lines on the screen
-X.DE
-X.SH
-XRequired string fields
-X.ID
-X.if n .ul 0
-X:ce=: clear to end-of-line
-X:cl=: home the cursor & clear the screen
-X:cm=: move the cursor to a given row/column
-X:up=: move the cursor up one line
-X.DE
-X.SH
-XBoolean fields
-X.if n .ul 0
-X.ID
-X:am:  auto margins - wrap when char is written in last column?
-X:xn:  brain-damaged auto margins - newline ignored after wrap
-X:pt:  physical tabs?
-X.DE
-X.SH
-XOptional string fields
-X.if n .ul 0
-X.ID
-X:al=: insert a blank row on the screen
-X:dl=: delete a row from the screen
-X:cd=: clear to end of display
-X:ei=: end insert mode
-X:ic=: insert a blank character
-X:im=: start insert mode
-X:dc=: delete a character
-X:sr=: scroll reverse (insert row at top of screen)
-X:vb=: visible bell
-X:ti=: terminal initialization string, to start full-screen mode
-X:te=: terminal termination, to end full-screen mode
-X:ks=: enables the cursor keypad
-X:ke=: disables the cursor keypad
-X.DE
-X.SH
-XOptional strings received from the keyboard
-X.if n .ul 0
-X.ID
-X:kd=: sequence sent by the <down arrow> key
-X:kl=: sequence sent by the <left arrow> key
-X:kr=: sequence sent by the <right arrow> key
-X:ku=: sequence sent by the <up arrow> key
-X:kP=: sequence sent by the <PgUp> key
-X:kN=: sequence sent by the <PgDn> key
-X:kh=: sequence sent by the <Home> key
-X:kH=: sequence sent by the <End> key
-X:kI=: sequence sent by the <Insert> key
-X.DE
-X.PP
-XOriginally, termcap didn't have any names for the <PgUp>, <PgDn>, <Home>,
-Xand <End> keys.
-XAlthough the capability names shown in the table above are the most common,
-Xthey are \fInot\fR universal.
-XSCO Xenix uses :PU=:PD=:HM=:EN=: for those keys.
-XAlso, if the four arrow keys happen to be part of a 3x3 keypad,
-Xthen the five non-arrow keys may be named :K1=: through :K5=:,
-Xso an IBM PC keyboard may be described using those names instead.
-X\*E can find any of these names.
-X.SH
-XOptional strings sent by function keys
-X.if n .ul 0
-X.ID
-X:k1=:...:k9=:k0=:     codes sent by <F1> through <F10> keys
-X:s1=:...:s9=:s0=:     codes sent by <Shift F1> ... <Shift F10>
-X:c1=:...:c9=:c0=:     codes sent by <Ctrl F1> ... <Ctrl F10>
-X:a1=:...:a9=:a0=:     codes sent by <Alt F1> ... <Alt F10>
-X.DE
-X.PP
-XNote that :k0=: is used to describe the <F10> key.
-XSome termcap documents recommend :ka=: or even :k;=: for describing
-Xthe <F10> key, but \*E doesn't support that.
-X.PP
-XAlso, the :s1=:..., :c1=:..., and :a1=:... codes are very non-standard.
-XThe terminfo library doesn't support them.
-X.SH
-XOptional fields that describe character attributes
-X.if n .ul 0
-X.ID
-X:so=:se=:     start/end standout mode (We don't care about :sg#:)
-X:us=:ue=:     start/end underlined mode
-X:md=:me=:     start/end boldface mode
-X:as=:ae=:     start/end alternate character set (italics)
-X:ug#:         visible gap left by :us=:ue=:md=:me=:as=:ae=:
-X.DE
-X.SH
-XOptional fields that affect the cursor's shape
-X.PP
-XThe :cQ=: string is used by \*E immediately before exiting to undo
-Xthe effects of the other cursor shape strings.
-XIf :cQ=: is not given, then all other cursor shape strings are ignored.
-X.ID
-X:cQ=: normal cursor
-X:cX=: cursor used for reading EX command
-X:cV=: cursor used for reading VI commands
-X:cI=: cursor used during VI input mode
-X:cR=: cursor used during VI replace mode
-X.DE
-X.PP
-XIf the capabilities above aren't given, then \*E will try to use the
-Xfollowing values instead.
-X.ID
-X:ve=: normal cursor, used as :cQ=:cX=:cI=:cR=:
-X:vs=: gaudy cursor, used as :cV=:
-X.DE
-X.SH
-XAn example
-X.PP
-XHere's the termcap entry I use on my Minix-ST system.
-XSome of the fields in it have nothing to do with \*E.
-XSome can only work on my system;
-XI have modified my kernel's screen driver.
-X.sp
-X.LD
-X.ne 14
-Xmx|minix|minixst|ansi:\\
-X      :is=\\E[0~:co#80:li#25:bs:pt:\\
-X      :cm=\\E[%i%d;%dH:up=\\E[A:do=^J:nd=\\E[C:sr=\\EM:\\
-X      :cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:\\
-X      :al=\\E[L:dl=\\E[M:ic=\\E[@:dc=\\E[P:im=:ei=:\\
-X      :so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:\\
-X      :md=\\E[1m:me=\\E[m:as=\\E[1;3m:ae=\\E[m:\\
-X      :ku=\\E[A:kd=\\E[B:kr=\\E[C:kl=\\E[D:\\
-X      :k1=\\E[1~:k2=\\E[2~:k3=\\E[3~:k4=\\E[4~:k5=\\E[5~:\\
-X      :k6=\\E[6~:k7=\\E[17~:k8=\\E[18~:k9=\\E[19~:k0=\\E[20~:\\
-X      :kU=\\E[36~:kQ=\\E[32~:kH=\\E[28~:\\
-X      :GV=3:GH=D:G1=?:G2=Z:G3=@:G4=Y:GC=E:GL=4:GR=C:GU=A:GD=B:\\
-X      :cQ=\\E[k:cX=\\E[2;0k:cV=\\E[16;0k:cI=\\E[k:cR=\\E[16;20k:
-X.DE
-/
-echo x - title.ms
-sed '/^X/s///' > title.ms << '/'
-X.de tE
-X.ps 80
-X.ce 1
-X\*E
-X..
-X.de nE
-X.ce 7
-X#######                                
-X#        #       #    #     #     #### 
-X#        #       #    #     #    #     
-X#####    #       #    #     #     #### 
-X#        #       #    #     #         #
-X#        #        #  #      #    #    #
-X#######  ######    ##       #     #### 
-X..
-X.sp |2i
-X.if t .tE
-X.if n .nE
-X.ps 10
-X.sp 1
-X.ce 2
-X- a clone of vi/ex -
-Xversion \*V
-X.sp |7.5i
-X.IP Author: 0.9i
-XSteve Kirkendall
-X.br
-X14407 SW Teal Blvd., Apt C
-X.br
-XBeaverton, OR 97005
-X.IP E-Mail: 0.9i
-Xkirkenda@cs.pdx.edu
-X.IP Phone: 0.9i
-X(503) 643-6980
-/
-echo x - ver.ms
-sed '/^X/s///' > ver.ms << '/'
-X.ds V 1.5j-betatest
-X.if t .ds E E\s-2LVIS\s+2
-X.if n .ds E Elvis
-X.\"
-X.\" usage: .Go <section#> <title>
-X.de Go
-X.ds LH "\\$1-\\\\n%
-X.ds RH "\\$1-\\\\n%
-X.ds CH "\\$2
-X.NH S \\$1
-X\\$2
-X.\"if !\\n%=1 .bp 1
-X.if n .ul 0
-X..
-/
-echo x - versions.ms
-sed '/^X/s///' > versions.ms << '/'
-X.Go 12 "VERSIONS"
-X.PP
-X\*E currently works under BSD UNIX, AT&T System-V UNIX, SCO XENIX,
-XMinix, Coherent, MS-DOS, Atari TOS, OS9/68k, VAX/VMS, and AmigaDos.
-XThis section of the manual provides special information that applies to each
-Xparticular version of \*E.
-X.PP
-XFor all versions except MS-DOS,
-Xthe file "Makefile.mix" should be copied to "Makefile",
-Xand then edited to select the correct set of options for your system.
-XThere is more information about this embedded in the file itself.
-X.NH 2
-XBSD UNIX
-X.PP
-XTemporary files are stored in /tmp.
-X.PP
-XYou should modify /etc/rc so that
-Xthe temp files are preserved when the system is rebooted.
-XFind a line in /etc/rc which reads
-X.br
-X.ti +0.5i
-Xex4.3preserve /tmp
-X.PP
-Xor something like that, and append the following line after it:
-X.br
-X.ti +0.5i
-Xelvprsv /tmp/elv*
-X.PP
-XIf you do not have permission to modify /etc/rc, don't fret.
-XThe above modification is only needed to allow you to recover your changes
-Xafter a system crash.
-XYou can still run \*E without that modification,
-Xand you can still recover your changes when \*E crashes
-Xor when your dialup modem looses the carrier signal, or something like that.
-XOnly a system crash or power failure could hurt you.
-X.PP
-XBoth \*E and the real Vi
-Xread initialization commands from a file called ".exrc",
-Xbut the commands in that file might work on one but not the other.
-XFor example, "set keywordprg=man" will work for \*E,
-Xbut Vi will complain because it doesn't have a "keywordprg" option.
-XIf the warning messages annoy you, then you can edit the config.h file
-Xto change the name of the initialization file ".exrc" to something else,
-Xsuch as ".elvisrc".
-X.PP
-XIf you use X windows, you may wish to add "-DCS_LATIN1" to CFLAGS.
-XThis will cause the digraph table and the flipcase option to have default
-Xvalues that are appropriate for the LATIN-1 character set.
-XThat's the standard character set for X.
-X.PP
-XThe default keyboard macro time-out value is larger for BSD than it is for
-Xsome other systems, because I've had trouble running \*E via rlogin or Xterm.
-XI guess it takes a while for those keystokes to squirt through the net.
-X.NH 2
-XSystem-V UNIX
-X.PP
-XMost SysV UNIX systems use terminfo instead of termcap,
-Xbut  the  terminfo  library  doesn't seem to have a standard name.
-XAs shipped, Elvis' Makefile.mix  is  configured  with "LIBS=-lterm".
-XYou may need to change it to "LIBS=-ltermcap" or "LIBS=-lterminfo"
-Xor even "LIBS=-lcurses".
-X.PP
-XThe /etc/rc file should be modified as described for BSD systems, above.
-XThe only difference is that SysV systems tend to have directories for
-Xinitialization, instead of a single large /etc/rc file.
-XEditor recovery is usually done somewhere in the /etc/rc2.d directory.
-X.PP
-XThe potential trouble with ".exrc" described above for BSD UNIX applies
-Xto System-V UNIX as well.
-X.PP
-X\*E uses control-C as the interrupt key, not Delete.
-X.NH 2
-XSCO Xenix
-X.PP
-XFor Xenix-386, you can use the generic System-V settings.
-XYou may wish to add "-DCS_IBMPC" to CFLAGS, to have the digraph table and
-Xflipcase option start up in a mode that is appropriate for the console.
-X
-XThere is a separate group of settings for use with Xenix-286.
-XIt already has "-DCS_IBMPC" in CFLAGS.
-X.PP
-XBecause Xenix is so similar to System-V, everything I said earlier about
-XSystem-V applies to the Xenix version too, except that editor recovery
-Xprobably belongs in a directory called /etc/rc.d/8.
-X.NH 2
-XMinix
-X.PP
-XThere are separate settings in Makefile.mix for Minix-PC and Minix-68k.
-XThe differences between these two are that
-Xthe 68k version uses ".o" for the object file extension where
-Xthe PC version uses ".s", and
-Xthe PC version has some extra flags in CFLAGS to reduce the size of \*E.
-XThe PC version also uses tinytcap (instead of the full termcap) to make it smaller.
-X.PP
-XMinix-PC users should read the CFLAGS section of this manual very carefully.
-XYou have some choices to make...
-X.PP
-XThe temporary files are stored in /usr/tmp.
-XThe /usr/tmp directory must exist before you run \*E,
-Xand it must be readable/writable by everybody.
-XWe use /usr/tmp instead of /tmp because
-Xafter a system crash or power failure,
-Xyou can recover the altered version of a file from the temporary file
-Xin /usr/tmp.
-XIf it was stored in /tmp, though, then it would be lost because /tmp is
-Xnormally located on the RAM disk.
-X.PP
-X\*E uses control-C as the interrupt key, not Delete.
-X.NH 2
-XCoherent
-X.PP
-X\*E was ported to Coherent by Esa Ahola.
-X.PP
-X\*E is too large to run under Coherent unless you eliminate some
-Xfeatures via the CFLAGS setting.
-XThe recommended settings, in Makefile.mix, produce a working version
-Xof \*E which emulates Vi faithfully, but lacks most of the extensions.
-XYou should read the CFLAGS section of this manual carefully.
-X.PP
-XYou can probably reduce the size of \*E by using tinytcap.c instead of -lterm.
-XThis would allow you to keep most features of \*E,
-Xat the expense of terminal independence.
-X(Tinytcap.c has ANSI escape sequences hard-coded into it.)
-XTo use tinytcap, just add "tinytcap.o" to the "EXTRA=" line in the Makefile,
-Xand remove "-lterm" from the "LIBS=" line.
-X.PP
-XThe temporary files are stored in /tmp.
-XYou should modify your /etc/rc file as described for BSD earlier.
-X.NH 2
-XMS-DOS
-X.PP
-X\*E was ported to MS-DOS by Guntram Blohm and Martin Patzel.
-XWillett Kempton added support for the DEC Rainbow.
-X.PP
-XIdeally, \*E should be compiled with Microsoft C 5.10 and the standard
-XMicrosoft Make utility,
-Xvia the command "make elvis.mak".
-XThis will compile \*E and all related utilities.
-X.PP
-XWith Microsoft C 6.00, you may have trouble compiling regexp.c.
-XIf so, try compiling it without optimization.
-X.PP
-XThe "Makefile.mix" file contains a set of suggested settings for compiling
-Xelvis with Turbo-C or Borland C.
-X(If you have Turbo-C, but not the Make utility,
-Xthen you can \fIalmost\fR use the "\*E.prj" file to compile \*E,
-Xbut you must explicitly force Turbo-C to compile it with the "medium" memory model.
-XMost of the related programs [ctags, ref, virec, refont, and wildcard] are
-Xonly one file long, so you should have no trouble compiling them.)
-XThe "alias.c" file is meant to be compiled once into an executable named
-X"ex.exe".
-XYou should then copy "ex.exe" to "vi.exe" and "view.exe".
-X.PP
-X\*E stores its temporary files in C:\\tmp.
-XIf this is not satisfactory, then you should edit the CFLAGS line of
-Xyour Makefile to change TMPDIR to something else before compiling.
-XYou can also control the name of the temp directory via an environment
-Xvariable named TMP or TEMP.
-XThe directory must exist before you can run \*E.
-X.PP
-XThe TERM environment variable determines how elvis will write to the screen.
-XIt can be set to any one of the following values:
-X.LD
-X.ta 1.5i 2.5i
-X      pcbios  Use BIOS calls on an IBM-PC clone.
-X      rainbow Use DEC Rainbow interface.
-X      ansi    Use ANSI.SYS driver.
-X      nansi   User faster NANSI.SYS driver.
-X.DE
-X.PP
-XIf the TERM variable isn't set, then elvis will automatically select either
-Xthe "rainbow" interface (when run on a Rainbow) or "pcbios" (on an IBM clone).
-X.PP
-XYou may prefer to use NANSI.SYS for speed;
-Xor you may NEED to use ANSI.SYS for a non-clone, such as a lap-top.
-XIf so, you should
-Xinstall one of these drivers by adding "driver = nansi.sys" (or whatever)
-Xto your CONFIG.SYS file,
-Xand then you should define TERM to be "nansi" (or whatever) by adding
-X"set TERM=nansi" to your AUTOEXEC.BAT file.
-XYou must then reboot for these changes to take effect.
-XAfter that, \*E will notice the "TERM" setting and use the driver.
-X.PP
-XSince ".exrc" is not a valid DOS filename,
-Xthe name of the initialization file has been changed to "elvis.rc".
-XElvis will look for an "elvis.rc" file first in your home directory,
-Xand then in the current directory.
-XNote that you must set an environment variable named "HOME" to the
-Xfull pathname of your home directory, for Elvis to check there;
-Xif "HOME" isn't set, then Elvis will only look in the current directory.
-XTo set "HOME", you would typically add the following line to your
-XAUTOEXEC.BAT file:
-X.br
-X.ti +0.5i
-Xset HOME c:\\
-X.PP
-XAn extra program, called "wildcard", is needed for MS-DOS.
-XIt expands wildcard characters in file names.
-XIf \*E flashes a "Bad command or filename" message when it starts,
-Xthen you've probably lost the WILDCARD.EXE program somehow.
-X.PP
-X\*E can run under Windows, but only in full-screen mode.
-XAlso, Windows uses an environment variable called TEMP which interferes with
-Xelvis' usage of TEMP;
-Xto work around this, you can simply set an environment variable named
-XTMP (with no 'E') to the name of elvis' temporary directory.
-XWhen TEMP and TMP are both set, \*E uses TMP and ignored TEMP.
-X.NH 2
-XAtari TOS
-X.PP
-X\*E was ported to Atari TOS by Guntram Blohm and Martin Patzel.
-XIt is very similar to the MS-DOS version.
-XIt has been tested with the Mark Williams C compiler and also GNU-C.
-X.PP
-XThe TERM environment variable is ignored;
-Xthe ST port always assumes that TERM=vt52.
-XThe SHELL (not COMSPEC!) variable should be set to
-Xthe name of a line-oriented shell.
-X.PP
-XA simple shell in included with \*E.
-XIts source is in "shell.c", and the name of the executable is "shell.ttp".
-XThe file "profile.sh" should contain a set of instructions to be executed
-Xwhen the shell first starts up.
-XAn example of this file is included, but you will almost certainly want to
-Xedit it right away to match your configuration.
-X(If you already have a command-line shell,
-Xthen you'll probably want to continue using it.
-XThe shell that comes with \*E is very limited.)
-X.PP
-XCurrently, character attributes cannot be displayed on the screen.
-X.PP
-X\*E runs under MiNT (a free multi-tasking extension to TOS)
-Xbut it can be a CPU hog because of the way that \*E reads from the
-Xkeyboard with timeout.
-XAlso, \*E doesn't use any of the special features of MiNT.
-XI have received a set of patches that optimize \*E for MiNT,
-Xbut they arrived too late to integrate into this release.
-X.NH 2
-XOS9/68k
-X.PP
-X\*E was ported to OS9/68k by Peter Reinig.
-X.PP
-XThe Makefile is currently configured to install \*E and the related
-Xprograms in /dd/usr/cmds
-XIf this this is unacceptable, then you should change the BIN setting
-Xto some other directory.
-XSimilarly, it expects the source code to reside in /dd/usr/src/elvis;
-Xthe ODIR setting is used to control this.
-X.PP
-XTemporary files are stored in the /dd/tmp directory.
-XYour /dd/startup file may need to be modified
-Xto prevent it from deleting \*E' temporary files;
-Xmake /dd/startup run the \fIelvprsv\fR program before it wipes out /dd/tmp.
-X.PP
-XThe program in alias.c is linked repeatedly to produce the
-X"vi", "view", and "input" aliases for \*E.
-XSadly, the "ex" alias is impossible to implement under OS9
-Xbecause the shell has a built-in command by that name.
-X.PP
-XFor some purposes,
-Xyou must give `make' the "-b" option.
-XSpecifically, you need this for "make -b clean" and "make -b install".
-X.NH 2
-XVAX/VMS
-X.PP
-XJohn Campbell ported \*E to VAX/VMS.
-X.PP
-XA heavily laden VAX can take half an hour to compile elvis.
-XThis is normal.
-XDon't panic.
-X.PP
-XWhile running, elvis will create temporary files in SYS$SCRATCH.
-XEnter SHOW LOGICAL SYS$SCRATCH to see what actual directory you are using.
-XMany sites have SYS$SCRATCH equivalenced to SYS$LOGIN.
-XThe elvis temporary files look like the following on VMS while elvis is running:
-X.br
-X.ti 0.75i
-XELV_1123A.1;1       ELV_1123A.2;1       SO070202.;1
-X.PP
-XAlso, filtering commands (like !!dir and !}fmt) should work on VMS.
-XThis assumes, however, that you can create temporary mailboxes and that
-Xyour mailbox quota (a sysgen parameter) is at least 256 bytes for a
-Xsingle write to the mailbox.
-XThis is the default sysgen parameter,
-Xso there should be few people who experience filter problems.
-X.PP
-XAdditionally, an attempt was made to support the standard terminals on VMS:
-X"vt52", "vt100", "vt200", "vt300", "vt101", "vt102".
-XNon-standard terminals could be supported by setting your terminal type to
-XUNKNOWN (by entering SET TERM/UNKNOWN)
-Xand defining the logical name ELVIS_TERM.
-XWhatever ELVIS_TERM translates to, however, will have to be included in
-Xtinytcap.c.
-XNote that the upper/lowercase distinctions are significant,
-Xand that DCL will upshift characters that are not quoted strings, so
-Xenter DEFINE ELVIS_TERM "hp2621a".
-XAs distributed, it would probably not be a good idea to have more than the
-Xstandard terminals in tinytcap.c (else it wouldn't be tiny, would it?).
-XChanges here, of course, would require a recompilation to take effect.
-X.PP
-XIf you have a version of the "termcap" library and database on your system,
-Xthen you may wish to replace tinytcap with the real termcap.
-X.NH 2
-XAmigaDOS
-X.PP
-XMike Rieser and Dale Rahn ported \*E to AmigaDOS.
-X.PP
-XThe port was done using Manx Aztec C version 5.2b.
-X\*E uses about as much space as it can and still be small code and data.
-X\*E should also compile under DICE, though there may be a little trouble with
-Xsigned versus unsigned chars.
-X.PP
-XThe port has been done so the same binary will run under both versions of AmigaDOS.
-XUnder AmigaDOS 2.04, \*E supports all the documented features.
-XIt also uses an external program ref to do tag lookup.
-XSo, the accompanying programs: ref and ctags are recommended.
-XUnder AmigaDOS 1.2/1.3 \*E works, buts lacks the more advanced features.
-X.PP
-XFor the port to AmigaDOS 2.04, we tried to use as many Native AmigaDOS
-Xcalls as we could.
-XThis should increase Elvis's chances at being compiled with other compilers.
-XDICE seems to have a different default char type.
-XYou may need to use the UCHAR() macro in tio.c.
-XTo test it, try the :map command; if it looks right, things are cool.
-X.PP
-XFor the port to AmigaDOS 1.3, we tried to make sure the program was at
-Xleast usable.
-XMany features are missing, most notably running commands in subshells.
-XAlso, what we could get working, we used Aztec functions to support them,
-Xso this part is little more compiler dependent.
-X.PP
-XAztec is compatible with the SAS libcall #pragma.
-XI personally prefer using the includes that come from Commodore over the ones
-Xsupplied with Aztec, but for people with a straight Aztec installation,
-XI went with the default names for the Aztec pragmas.
-X.PP
-XOne include you'll need is <sys/types.h>.
-XIts a common include when porting software just make yourself one.
-XIts a two line file that saves a lot of hassle especially in the elvis source.
-XSo, make a directory where your includes are located called `sys'
-Xand in a file below that type:
-X.br
-X.ti +0.8i
-X/* sys/types.h */
-X.br
-X.ti +0.8i
-X#include <exec/types.h>
-X.PP
-XWhen setting environment variables (either local or global) for
-Xvariables that specify a directory, make sure the variable ends in `:'
-Xor `/'.
-XThis saved from having to change much of the way elvis works.
-XThe default temporary directory (if TEMP and TMP aren't specified) is "T:".
-XThe default if HOME directory (if no HOME environment variable is set) is "S:".
-X.PP
-XTo avoid conlict with other uses, \*E uses elvis.rc instead of .exrc or
-Xwhere it looks for macros.
-X.NH 2
-XOther Systems
-X.PP
-XFor Sun workstations, use the BSD configuration.
-XEarlier versions of elvis didn't link correctly due to a quirk in Sun's
-Xversion of the "make" utility, but this version of elvis has a work-around
-Xfor that quirk so you should have no trouble at all.
-X.PP
-XFor Linux, use the SysV settings.
-XYou can probably just remove the "-lterm" from the "LIBS= -lterm" line,
-Xsince linux keeps the termcap functions in the standard C library.
-X.PP
-XFor other UNIXoid systems, I suggest you start with the Minix-68k settings
-Xand then grow from that.
-XMinix is a nice starting point because it is a clone of Version 7 UNIX,
-Xwhich was the last common ancestor of BSD UNIX and SysV UNIX.
-XAny Operating System which claims any UNIX compatibility what so ever
-Xwill therefore support V7/Minix code.
-XYou may need to fiddle with #include directives or something, though.
-XMinix-68k is a better starting point than Minix-PC because the PC compiler
-Xhas some severe quirks.
-/
-echo x - visual.ms
-sed '/^X/s///' > visual.ms << '/'
-X.Go 2 "VISUAL MODE COMMANDS"
-X.PP
-XMost visual mode commands are one keystroke long.
-XThe following table lists the operation performed by each keystroke,
-Xand also denotes any options or arguments that it accepts.
-XNotes at the end of the table describe the notation used in this table.
-X.PP
-XIn addition to the keys listed here, your keyboard's "arrow" keys
-Xwill be interpretted as the appropriate cursor movement commands.
-XThe same goes for <PgUp> and <PgDn>, if your keyboard has them.
-XThe <Insert> key will toggle between insert mode and replace mode.
-XThere is a colon mode command (":map", to be described later)
-Xwhich will allow you to define other keys, such as function keys.
-X.PP
-XA tip: visual command mode looks a lot like text input mode.
-XIf you forget which mode you're in, just hit the <Esc> key.
-XIf \*E beeps, then you're in visual command mode.
-XIf \*E does not beep, then you were in input mode,
-Xbut by hitting <Esc> you will have switched to visual command mode.
-XSo, one way or another, after <Esc> \*E will be ready for a command.
-X.LD
-X.ta 0.7i 1.3i
-X\s+2COMMAND   DESCRIPTION\s-2
-X      ^A      Search for next occurence of word at cursor (MOVE)(EXT)
-X      ^B      Move toward the top of the file by 1 screenful
-X      ^C      --- (usually sends SIGINT, to interupt a command)
-Xcount ^D      Scroll down <count> lines (default 1/2 screen)
-Xcount ^E      Scroll up <count> lines
-X      ^F      Move toward the bottom of the file by 1 screenful
-X      ^G      Show file status, and the current line #
-Xcount ^H      Move left, like h (MOVE)
-X      ^I      ---
-Xcount ^J      Move down (MOVE)
-X      ^K      ---
-X      ^L      Redraw the screen
-Xcount ^M      Move to the front of the next line (MOVE)
-Xcount ^N      Move down (MOVE)
-X      ^O      ---
-Xcount ^P      Move up (MOVE)
-X      ^Q      --- (typically XON, which restarts screen updates)
-X      ^R      Redraw the screen
-X      ^S      --- (typically XOFF, which stops screen updates)
-X      ^T      ---
-Xcount ^U      Scroll up <count> lines (default 1/2 screen)
-X      ^V      ---
-X      ^W      ---
-Xcount ^X      Move to a physical column number on the screen (MOVE) (EXT)
-Xcount ^Y      Scroll down <count> lines
-X      ^Z      --- (sometimes sends SIGSUSP, to suspend execution)
-X      ESC     ---
-X      ^\\     --- (usually sends SIGQUIT, which is ignored)
-X      ^]      If the cursor is on a tag name, go to that tag
-X      ^^      Switch to the previous file, like ":e #"
-X      ^_      ---
-Xcount SPC     Move right,like l (MOVE)
-X      ! \s-2mv\s+2    Run the selected lines thru an external filter program
-X      " \s-2key\s+2   Select which cut buffer to use next
-Xcount # \s-2+\s+2     Increment a number (EDIT) (EXT)
-X      $       Move to the rear of the current line (MOVE)
-Xcount %       Move to matching (){}[] or to a given % of file (MOVE) (EXT)
-Xcount &       Repeat the previous ":s//" command here (EDIT)
-X      ' \s-2key\s+2   Move to a marked line (MOVE)
-Xcount (       Move backward <count> sentences (MOVE)
-Xcount )       Move forward <count> sentences (MOVE)
-X      *       Go to the next error in the errlist (EXT)
-Xcount +       Move to the front of the next line (MOVE)
-Xcount ,       Repeat the previous [fFtT] but in the other direction (MOVE)
-Xcount -       Move to the front of the preceding line (MOVE)
-Xcount .       Repeat the previous "edit" command
-X      / \s-2text\s+2  Search forward for a given regular expression (MOVE)
-X      0       If not part of count, move to 1st char of this line (MOVE)
-X      1       Part of count
-X      2       Part of count
-X      3       Part of count
-X      4       Part of count
-X      5       Part of count
-X      6       Part of count
-X      7       Part of count
-X      8       Part of count
-X      9       Part of count
-X      : \s-2text\s+2  Run single EX cmd
-Xcount ;       Repeat the previous [fFtT] cmd (MOVE)
-X      < \s-2mv\s+2    Shift text left (EDIT)
-X      = \s-2mv\s+2    Reformat
-X      > \s-2mv\s+2    Shift text right (EDIT)
-X      ? \s-2text\s+2  Search backward for a given regular expression (MOVE)
-X      @ \s-2key\s+2   Execute the contents of a cut-buffer as VI commands
-Xcount A \s-2inp\s+2   Append at end of the line (EDIT)
-Xcount B       Move back Word (MOVE)
-X      C \s-2inp\s+2   Change text from the cursor through the end of the line (EDIT)
-X      D       Delete text from the cursor through the end of the line (EDIT)
-Xcount E       Move end of Word (MOVE)
-Xcount F \s-2key\s+2   Move leftward to a given character (MOVE)
-Xcount G       Move to line #<count> (default is the bottom line) (MOVE)
-Xcount H       Move to home row (the line at the top of the screen)
-Xcount I \s-2inp\s+2   Insert at the front of the line (after indents) (EDIT)
-Xcount J       Join lines, to form one big line (EDIT)
-X      K       Look up keyword (EXT)
-Xcount L       Move to last row (the line at the bottom of the screen)
-X      M       Move to middle row
-X      N       Repeat previous search, but in the opposite direction (MOVE)
-Xcount O \s-2inp\s+2   Open up a new line above the current line (EDIT)
-X      P       Paste text before the cursor (EDIT)
-X      Q       Quit to EX mode
-X      R \s-2inp\s+2   Overtype (EDIT)
-Xcount S \s-2inp\s+2   Change lines, like <count>cc
-Xcount T \s-2key\s+2   Move leftward *almost* to a given character (MOVE)
-X      U       Undo all recent changes to the current line
-X      V       Start marking lines for c/d/y/</>/!/\\ (EXT)
-Xcount W       Move forward <count> Words (MOVE)
-Xcount X       Delete the character(s) to the left of the cursor (EDIT)
-Xcount Y       Yank text line(s) (copy them into a cut buffer)
-X      Z Z     Save the file & exit
-X      [ [     Move back 1 section (MOVE)
-X      \\ \s-2mv\s+2   Pop-up menu for modifying text (EXT)
-X      ] ]     Move forward 1 section (MOVE)
-X      ^       Move to the front of the current line (after indent) (MOVE)
-Xcount _       Move to the current line
-X      ` \s-2key\s+2   Move to a marked character (MOVE)
-Xcount a \s-2inp\s+2   Insert text after the cursor (EDIT)
-Xcount b       Move back <count> words (MOVE)
-X      c \s-2mv\s+2    Change text (EDIT)
-X      d \s-2mv\s+2    Delete text (EDIT)
-Xcount e       Move forward to the end of the current word (MOVE)
-Xcount f \s-2key\s+2   Move rightward to a given character (MOVE)
-X      g       ---
-Xcount h       Move left (MOVE)
-Xcount i \s-2inp\s+2   Insert text at the cursor (EDIT)
-Xcount j       Move down (MOVE)
-Xcount k       Move up (MOVE)
-Xcount l       Move right (MOVE)
-X      m \s-2key\s+2   Mark a line or character
-X      n       Repeat the previous search (MOVE)
-Xcount o \s-2inp\s+2   Open a new line below the current line (EDIT)
-X      p       Paste text after the cursor (EDIT)
-X      q       ---
-Xcount r \s-2key\s+2   Replace <count> chars by a given character (EDIT)
-Xcount s \s-2inp\s+2   Replace <count> chars with text from the user (EDIT)
-Xcount t \s-2key\s+2   Move rightward *almost* to a given character (MOVE)
-X      u       Undo the previous edit command
-X      v       Start marking characters for c/d/y/</>/!/\\ (EXT)
-Xcount w       Move forward <count> words (MOVE)
-Xcount x       Delete the character that the cursor's on (EDIT)
-X      y \s-2mv\s+2    Yank text (copy it into a cut buffer)
-X      z \s-2key\s+2   Scroll current line to the screen's +=top -=bottom .=middle
-Xcount {       Move back <count> paragraphs (MOVE)
-Xcount |       Move to column <count> (the leftmost column is 1)
-Xcount }       Move forward <count> paragraphs (MOVE)
-Xcount ~       Switch a character between uppercase & lowercase (EDIT)
-X      DEL     --- (usually mapped to shift-X, so it deletes one character)
-X.DE
-X.IP count
-XMany commands may be preceded by a count.  This is a sequence of digits
-Xrepresenting a decimal number.  For most commands that use a count,
-Xthe command is repeated <count> times.  The count is always optional,
-Xand usually defaults to 1.
-X.IP key
-XSome commands require two keystrokes.  The first key always determines
-Xwhich command is to be executed.  The second key is used as a parameter
-Xto the command.
-X.IP mv
-XSome commands (! < > c d y \\ =) operate on text between the cursor and some
-Xother position.
-XThere are three ways that you can specifify that other position.
-X.IP
-XThe first way is to follow the command keystroke with a movement command.
-XFor example, "dw" deletes a single word.
-X"d3w" and "3dw" both delete three words.
-X.IP
-XThe second way is to type the command keystroke twice.
-XThis causes whole lines to be acted upon.
-XFor example, ">>" indents the current line.
-X"3>>" indents the current line and the following two lines.
-X.IP
-XThe last way is to move the cursor to one end of the text,
-Xtype 'v' or 'V' to start marking,
-Xmove the cursor to the other end,
-Xand then type the desired command key.
-X.IP inp
-XMany commands allow the user to interactively enter text.
-XSee the discussion of "input mode" in the following section.
-X.IP (EXT)
-XThese commands are extensions -- the real vi doesn't have them.
-X.IP (EDIT)
-XThese commands affect text, and may be repeated by the "." command.
-X.IP (MOVE)
-XThese commands move the cursor, and may be used to specify the extent
-Xof a member of the "mv" class of commands.
-X.NH 2
-XInput Mode
-X.PP
-XYou can't type text into your file directly from visual command mode.
-XInstead, you must first give a command which will put you into input mode.
-XThe commands to do this are A/C/I/O/R/S/a/i/o/s.
-X.PP
-XThe S/s/C/c commands temporarily place a $ at the end of the text that
-Xthey are going to change.
-X.PP
-XIn input mode, all keystrokes are inserted into the text at the
-Xcursor's position, except for the following:
-X.ID
-X^A    insert a copy of the last input text
-X^D    delete one indent character
-X^H    (backspace) erase the character before the cursor
-X^L    redraw the screen
-X^M    (carriage return) insert a newline (^J, linefeed)
-X^O    execute next key as a visual command (limited!)
-X^P    insert the contents of the cut buffer
-X^R    redraw the screen, like ^L
-X^T    insert an indent character
-X^U    backspace to the beginning of the line
-X^V    insert the following keystroke, even if special
-X^W    backspace to the beginning of the current word
-X^Z^Z  write the file & exit \*E
-X^[    (ESCape) exit from input mode, back to command mode
-X.DE
-X.PP
-XAlso, on some systems, ^S may stop output, ^Q may restart output,
-Xand ^C may interupt execution.
-X^@ (the NUL character) cannot be inserted.
-X.PP
-XThe R visual command puts you in overtype mode,
-Xwhich is a slightly different form of input mode.
-XIn overtype mode, each time you insert a character,
-Xone of the old characters is deleted from the file.
-X.NH 2
-XArrow keys in Input Mode
-X.PP
-XThe arrow keys can be used to move the cursor in input mode.
-X(This is an extension; the real Vi doesn't support arrow keys in input mode.)
-XThe <PgUp>, <PgDn>, <Home>, and <End> keys work in input mode, too.
-XThe <Delete> key deletes a single character in input mode.
-XThe <Insert> key toggles between input mode and replace mode.
-X.PP
-XThe best thing about allowing arrow keys to work in input mode is that
-Xas long as you're in input mode,
-X\*E seems to have a fairly ordinary user interface.
-XWith most other text editors, you are always in either insert mode or
-Xreplace mode, and you can use the arrow keys at any time to move the cursor.
-XNow, \*E can act like that, too.
-XIn fact, with the new "inputmode" option and the "control-Z control-Z" input
-Xcommand, you may never have to go into visual command mode for simple edit
-Xsessions.
-X.NH 2
-XDigraphs
-X.PP
-X\*E supports digraphs as a way to enter non-ASCII characters.
-XA digraph is a character which is composed of two other characters.
-XFor example, an apostrophe and the letter i could be defined as a digraph
-Xwhich is to be stored & displayed as an accented i.
-X.PP
-XThere is no single standard for extended ASCII character sets.
-X\*E can be compiled to fill the digraph with values appropriate for
-Xeither the IBM PC character set, or the LATIN-1 character set used by
-XX windows, or neither.
-X(See the discussions of -DCS_IBMPC and -DCS_LATIN1 in the CFLAGS section
-Xof this manual.)
-XYou can view or edit the digraph table via the ":digraph" colon command.
-X.PP
-XDigraphs will not be recognized until you've entered ":set digraph".
-X.PP
-XTo actually use a digraph
-Xtype the first character, then hit <Backspace>, and then type the
-Xsecond character.
-X\*E will then substitute the non-ASCII character in their place.
-X.NH 2
-XAbbreviations
-X.PP
-X\*E can expand abbreviations for you.
-XYou define an abbreviation with the :abbr command,
-Xand then whenever you type in the abbreviated form while in input mode,
-X\*E will immediately replace it with the long form.
-XCOBOL programmers should find this useful. :-)
-X.PP
-X\*E doesn't perform the substitution until you type a non-alphanumeric
-Xcharacter to mark the end of the word.
-XIf you type a control-V before that non-alphanumeric character, then
-X\*E will not perform the substitution.
-X.NH 2
-XAuto-Indent
-X.PP
-XWith the ":set autoindent" option turned on,
-X\*E will automatically insert leading whitespace at the beginning of each
-Xnew line that you type in.
-XThe leading whitespace is copied from the preceding line.
-X.PP
-XTo add more leading whitespace, type control-T.
-XTo remove some whitespace, type control-D.
-X.PP
-XIf you ":set noautotab", then the whitespace generated by control-T will
-Xalways consist of spaces -- never tabs.
-XSome people seem to prefer this.
-X.PP
-X\*E' autoindent mode isn't 100% compatible with vi's.
-XIn \*E, 0^D and ^^D don't work,
-X^U can wipeout all indentation, 
-Xand sometimes \*E will use a different amount of indentation than vi would.
-/
diff --git a/commands/elvis/Knownbug.txt b/commands/elvis/Knownbug.txt
deleted file mode 100644 (file)
index 740074d..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-The following options are missing:
-       [no]optimize    - affects screen redrawing method
-       [no]redraw      - simulate character insertion by redrawing line
-       [no]slowopen    - don't use character insertion
-       tags="tags"     - list of tags, used as TAGPATH
-
-I'd like to improve the versatility of the options whose value is a command:
-cc, make, kp, and ep.  I'd like to add some notation that allows you to say
-where to insert the current filename or current word.
--------------------------------------------------------------------------------
-Currently, elvis is configured to look for | only in .exrc files.  It doesn't
-look for | in any interactively entered command lines, yet.
--------------------------------------------------------------------------------
-The 'p', '#', and 'l' flags aren't supported.  Also, ex commands don't accept
-counts; e.g., ":c5" can't be used to change five lines. 
--------------------------------------------------------------------------------
-The following have been reported, but have not been verified.  If you have
-experienced any of the following, and haven't reported it yet, then please
-report it now!  I need more information about these bugs.
-
-[Bugs that are not in this list should also be reported, of course.]
-
-- Under VMS on an 80-column screen, after scolling sideways to approximately
-  column 110, a ^L will not redraw the part of the line after the cursor.
-- On an Atari ST running under TOS: some ASCII keys seem to send '#' plus
-  another key.  (This is normal for non-ASCII keys like <F1> or <Help>, but
-  ASCII keys should always send a single ASCII character.)
--------------------------------------------------------------------------------
-BIG JOBS:
-  Desirable extension: merge input mode and visual command mode.
-  Display long lines by wrapping, like the real vi (if ":set sidescroll=0")
--------------------------------------------------------------------------------
-
-- In the ":w >>filename" command, elvis doesn't allow any whitespace between
-  the ">>" and "filename".
-
-- Elvis doesn't allow "backslash newline" inside a single EX command.
-
-- VMS intercepts the control-T character, which is normally used to increase
-  indentation.  The <Tab> key works, but it doesn't do quite the same thing.
-  (":map! ^I ^T" helps.)
-
-- Under VMS, file I/O is very slow.  Looking over the vmsio.c file, I get the
-  impression that it is rather over-done for elvis.  Its speed could
-  probably be inproved.
-
-- The errlist feature doesn't seem to work with the Borland compilers.  Perhaps
-  they write to stderr instead of stdout?  This will probably be easy to solve
-  once I modify the "cc" and "make" options, as described earlier.
-
-- The command ":0" should move the cursor to line 1.  Currently, it doesn't
-  move the cursor at all.
-
-- File preservation is still flakey.  On DOS/TOS/VMS systems, it is also more
-  complex that it should be.
-
-- The act of appending to a cut buffer (as in "Ayy) sets file modification
-  flag.  It shouldn't!
-
-- The .exrc file is limited to BLKSIZE bytes -- 2048 on most systems, but
-  1024 on Minicx-PC, Coherent, and MS-DOS.
-
-- I *still* haven't quite perfected the screen update code.  If you suspect
-  that the screen doesn't accurately reflect the contents of the edit buffer,
-  then you should try doing a control-L.
-
-  I'll be overhauling the screen update code soon to make it wrap long lines
-  like the real vi.  I expect to fix this bug then.
diff --git a/commands/elvis/Makedoc b/commands/elvis/Makedoc
deleted file mode 100755 (executable)
index 2320263..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-# This is the Makefile for Elvis' "doc" directory.  It makes use of a
-# troff-like formatter called mroff.  Since you probably don't have mroff,
-# you'll need to edit this Makefile before you can fully use it.  It can
-# also use nroff, though, so you should be able to get something out of it.
-#
-# make         Use nroff to create an ASCII version of the manual.
-# make foo.doc Use nroff to create an ASCII version of foo.man or foo.ms
-# make manual  Use MROFF to print a typeset manual on a laser printer
-# make foo.1200        Use MROFF to print a typeset version of foo.man or foo.ms
-# make foo.100 Use MROFF to print a draft-quality version of foo.man or foo.ms
-# make foo.more        Use MROFF to preview foo.man or foo.more on your terminal
-#
-
-###############################################################################
-# Definitions...
-
-MAN=   ctags.man elvis.man elvprsv.man elvrec.man fmt.man ref.man
-MS=    title.ms index.ms intro.ms visual.ms ex.ms regexp.ms options.ms\
-       cutbufs.ms differ.ms internal.ms cflags.ms termcap.ms environ.ms\
-       versions.ms question.ms
-ASC=   title.doc index.doc intro.doc visual.doc ex.doc regexp.doc options.doc\
-       cutbufs.doc differ.doc internal.doc cflags.doc termcap.doc environ.doc\
-       versions.doc question.doc\
-       ctags.doc elvis.doc elvprsv.doc elvrec.doc fmt.doc ref.doc
-MANUAL=        title.1200 index.1200 intro.1200 visual.1200 ex.1200 regexp.1200 options.1200\
-       cutbufs.1200 differ.1200 internal.1200 cflags.1200 termcap.1200 environ.1200\
-       versions.1200\
-       ctags.1200 elvis.1200 elvprsv.1200 elvrec.1200 fmt.1200 ref.1200
-VER=   ver.ms
-TROFF= mroff
-NROFF= nroff
-
-###############################################################################
-# Rules...
-
-.SUFFIXES: .tmp .100 .1200 .more .doc .man .ms .vga .vgas
-
-.ms.tmp:
-       $(TROFF) -ms $(VER) $< >tmp
-
-.man.tmp:
-       $(TROFF) -man $< >tmp
-
-.ms.more:
-       $(TROFF) -ms $(VER) $< | draft | more
-
-.man.more:
-       $(TROFF) -man $< | draft | more
-
-.ms.1200:
-       $(TROFF) -ms $(VER) $< | hp2 1200 | lp -og $(PRINTER)
-
-.man.1200:
-       $(TROFF) -man $< | hp2 1200 | lp -og $(PRINTER)
-
-.ms.100:
-       $(TROFF) -ms $(VER) $< | hp2 100 | lp -og $(PRINTER)
-
-.man.100:
-       $(TROFF) -man $< | hp2 100 | lp -og $(PRINTER)
-
-.ms.doc:
-       $(NROFF) -ms $(VER) $< >$@
-
-.man.doc:
-       $(NROFF) -man $< >$@
-
-.ms.vga:
-       $(TROFF) -ms $(VER) $< >/tmp/foo
-       -vga /tmp/foo
-       rm /tmp/foo
-
-.ms.vgas:
-       $(TROFF) -ms $(VER) $< >/tmp/foo
-       -vgas /tmp/foo
-       rm /tmp/foo
-
-#############################################################################
-# Targets...
-
-asc: $(ASC)
-       cat $(ASC) >asc
-
-manual: $(MANUAL)
-
-clean:
-       rm -f *.doc *.sh
diff --git a/commands/elvis/Makefile b/commands/elvis/Makefile
deleted file mode 100644 (file)
index b0f8d85..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# Makefile for elvis
-#
-# Several groups of Makefile settings are included below.  Choose *ONE* group
-# of settings for your particular system, and leave the others commented out.
-# The meanings of these settings are:
-#      EXTRA   version-specific object files used in elvis
-#      CC      the C compiler command, possibly with "memory model" flags
-#      CFLAGS  compiler flags used to select compile-time options
-#      PROGS   the list of all programs
-#      SORT    if the "tags" file must be sorted, then SORT=-DSORT
-
-PROGS= elvis ctags ref elvrec fmt elvprsv
-CPPFLAGS+= -w -DCRUNCH \
-       -DNO_MKEXRC -DNO_CURSORSHAPE -DNO_CHARATTR -DNO_SHOWMODE \
-       -DNO_MODELINE -DNO_OPTCOLS -DNO_DIGRAPH -DNO_EXTENSIONS \
-       -DNO_ERRLIST -DNO_FKEY -DNO_VISIBLE -DNO_COLOR -DNO_POPUP
-
-# LSC Force usage of local getline, this is required here as long as
-# we do not fix elvis.
-CPPFLAGS+= -D__NBSD_LIBC
-
-###########################################################################
-###     The rest of this Makefile contains no user-serviceable parts    ###
-###########################################################################
-
-SRCS.elvis= blk.c cmd1.c cmd2.c ctype.c curses.c cut.c ex.c input.c \
-   main.c misc.c modify.c move1.c move2.c move3.c move4.c move5.c \
-   opts.c recycle.c redraw.c regexp.c regsub.c system.c tio.c tmp.c \
-   unix.c vars.c vcmd.c vi.c
-
-BINDIR= /usr/bin
-
-# Do not overwrite vi and ex if they already exist, only install the links
-# as a default fallback in their absence
-.if !exists(${DESTDIR}/${BINDIR}/vi)
-LINKS+= ${BINDIR}/elvis ${BINDIR}/vi
-.endif
-
-.if !exists(${DESTDIR}/${BINDIR}/ex)
-LINKS+= ${BINDIR}/elvis ${BINDIR}/ex
-.endif
-
-MAN.elvis=
-MAN.ctags=
-MAN.ref=
-MAN.elvrec=
-MAN.fmt=
-MAN.elvprsv=
-
-.include <bsd.prog.mk>
diff --git a/commands/elvis/Man.sh b/commands/elvis/Man.sh
deleted file mode 100755 (executable)
index 5dc7f87..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-echo x - ctags.man
-sed '/^X/s///' > ctags.man << '/'
-X.TH CTAGS 1
-X.SH NAME
-Xctags - Generates "tags" and (optionally) "refs" files
-X.SH SYNOPSIS
-X\fBctags\fP [\fB-stvra\fP] \fIfilesnames\fP...
-X.SH DESCRIPTION
-X\fIctags\fP generates the "tags" and "refs" files
-Xfrom a group of C source files.
-XThe "tags" file is used by Elvis' ":tag" command,
-Xcontrol-] command,
-Xand -t option.
-XThe "refs" file is sometimes used by the \fIref(1)\fP program.
-X.PP
-XEach C source file is scanned for #define statements and
-Xglobal function definitions.
-XThe name of the macro or function becomes the name of a tag.
-XFor each tag, a line is added to the "tags" file which contains:
-X.RS
-X.nf
-X       - the name of the tag
-X       - a tab character
-X       - the name of the file containing the tag
-X       - a tab character
-X       - a way to find the particular line within the file.
-X.RE
-X.fi
-X.PP
-XThe filenames list will typically be the names of all C source
-Xfiles in the current directory, like this:
-X.RS
-X.nf
-X$ ctags -stv *.[ch]
-X.RE
-X.fi
-X.SH OPTIONS
-X.IP \fB-t\fR
-XInclude typedefs.
-XA tag will be generated for each user-defined type.
-XAlso tags will be generated for struct and enum names.
-XTypes are considered to be global if they are defined in a header file,
-Xand static if they are defined in a C source file.
-X.IP \fB-v\fR
-XInclude variable declarations.
-XA tag will be generated for each variable, except for those that are declared
-Xinside the body of a function.
-X.IP \fB-s\fR
-XInclude static tags.
-X\fICtags\fR will normally put global tags in the "tags" file, and silently ignore
-Xthe static tags.
-XThis flag causes both global and static tags to be added.
-XThe name of a static tag is generated by prefixing the name of the declared
-Xitem with the name of the file where it is defined, with a colon in between.
-XFor example, "static foo(){}" in "bar.c" results in a tag named "bar.c:foo".
-X.IP \fB-r\fP
-XThis causes \fIctags\fP to generate both "tags" and "refs".
-XWithout \fB-r\fP, it would only generate "tags".
-X.IP \fB-a\fR
-XAppend to "tags", and maybe "refs".
-XNormally, \fIctags\fR overwrites these files each time it is invoked.
-XThis flag is useful when you have to many files in the current directory
-Xfor you to list them on a single command-line;
-Xit allows you to split the arguments among several invocations.
-X.SH FILES
-X.IP tags
-XA cross-reference that lists each tag name, the name of the source file that
-Xcontains it, and a way to locate a particular line in the source file.
-X.IP refs
-XThe "refs" file contains the definitions for each tag in the "tags" file,
-Xand very little else.
-XThis file can be useful, for example, when licensing restrictions prevent
-Xyou from making the source code to the standard C library readable by everybody,
-Xbut you still everybody to know what arguments the library functions need.
-X.SH BUGS
-X.PP
-X\fIctags\fR is sensitive to indenting and line breaks.
-XConsequently, it might not discover all of the tags in a file that
-Xis formatted in an unusual way.
-X.SH "SEE ALSO"
-Xelvis(1), refs(1)
-X.SH AUTHOR
-X.nf
-XSteve Kirkendall
-Xkirkenda@cs.pdx.edu
-X.fi
-/
-echo x - elvis.man
-sed '/^X/s///' > elvis.man << '/'
-X.TH ELVIS 1
-X.SH NAME
-Xelvis, ex, vi, view, input - The editor
-X.SH SYNOPSIS
-X\fBelvis\fP [\fIflags\fP] [\fB+\fP\fIcmd\fP] [\fIfiles\fP...]
-X.SH DESCRIPTION
-X\fIElvis\fP is a text editor which emulates \fIvi\fP/\fIex\fP.
-X.PP
-XOn systems which pass the program name as an argument, such as Unix and Minix,
-Xyou may also install \fIelvis\fP under the names "ex", "vi", "view", and "input".
-XThese extra names would normally be links to elvis;
-Xsee the "ln" shell command.
-X.PP
-XWhen \fIelvis\fP is invoked as "vi",
-Xit behaves exactly as though it was invoked as "elvis".
-XHowever, if you invoke \fIelvis\fP as "view",
-Xthen the readonly option is set as though you had given it the "-R" flag.
-XIf you invoke \fIelvis\fP as "ex",
-Xthen \fIelvis\fP will start up in the colon command mode
-Xinstead of the visual command mode,
-Xas though you had given it the "-e" flag.
-XIf you invoke \fIelvis\fP as "input" or "edit",
-Xthen \fIelvis\fP will start up in input mode,
-Xas though the "-i" flag was given.
-X.SH OPTIONS
-X.IP \fB-r\fP
-XTo the real vi, this flag means that a previous edit should be recovered.
-X\fIElvis\fP, though, has a separate program, called \fIelvrec(1)\fP, for recovering
-Xfiles.
-XWhen you invoke \fIelvis\fP with -r, \fIelvis\fP will tell you to run \fIelvrec\fP.
-X.IP \fB-R\fP
-XThis sets the "readonly" option,
-Xso you won't accidentally overwrite a file.
-X.IP "\fB-t\fP \fItag\fP"
-XThis causes \fIelvis\fP to start editing at the given tag.
-X.IP "\fB-m\fP [\fIfile\fP]"
-X\fIElvis\fP will search through \fIfile\fP for something that looks like
-Xan error message from a compiler.
-XIt will then begin editing the source file that caused the error,
-Xwith the cursor sitting on the line where the error was detected.
-XIf you don't explicitly name a \fIfile\fP, then "errlist" is assumed.
-X.IP \fB-e\fP
-X\fIElvis\fP will start up in colon command mode.
-X.IP \fB-v\fP
-X\fIElvis\fP will start up in visual command mode.
-X.IP \fB-i\fP
-X\fIElvis\fP will start up in input mode.
-X.IP "\fB-w\fR \fIwinsize\fR"
-XSets the "window" option's value to \fIwinsize\fR.
-X.IP "\fB+\fP\fIcommand\fP or \fB-c\fP \fIcommand\fP"
-XIf you use the +\fIcommand\fP parameter,
-Xthen after the first file is loaded
-X\fIcommand\fP is executed as an EX command.
-XA typical example would be "elvis +237 foo",
-Xwhich would cause \fIelvis\fP to start editing foo and
-Xthen move directly to line 237.
-XThe "-c \fIcommand\fP" variant was added for UNIX SysV compatibility.
-X.SH FILES
-X.IP /tmp/elv*
-XDuring editing,
-X\fIelvis\fP stores text in a temporary file.
-XFor UNIX, this file will usually be stored in the /tmp directory,
-Xand the first three characters will be "elv".
-XFor other systems, the temporary files may be stored someplace else;
-Xsee the version-specific section of the documentation.
-X.IP tags
-XThis is the database used by the \fI:tags\fP command and the \fB-t\fP option.
-XIt is usually created by the \fIctags(1)\fP program.
-X.IP ".exrc or elvis.rc"
-XOn UNIX-like systems, a file called ".exrc" in your home directory
-Xis executed as a series of \fIex\fR commands.
-XA file by the same name may be executed in the current directory, too.
-XOn non-UNIX systems, ".exrc" is usually an invalid file name;
-Xthere, the initialization file is called "elvis.rc" instead.
-X.SH "SEE ALSO"
-Xctags(1), ref(1), virec(1)
-X.PP
-X\fIElvis - A Clone of Vi/Ex\fP, the complete \fIelvis\fP documentation.
-X.SH BUGS
-XThere is no LISP support.
-XCertain other features are missing, too.
-X.PP
-XAuto-indent mode is not quite compatible with the real vi.
-XAmong other things, 0^D and ^^D don't do what you might expect.
-X.PP
-XLong lines are displayed differently.
-XThe real vi wraps long lines onto multiple rows of the screen,
-Xbut \fIelvis\fP scrolls sideways.
-X.SH AUTHOR
-X.nf
-XSteve Kirkendall
-Xkirkenda@cs.pdx.edu
-X.fi
-X.PP
-XMany other people have worked to port \fIelvis\fP to various operating systems.
-XTo see who deserves credit, run the \fI:version\fP command from within \fIelvis\fP,
-Xor look in the system-specific section of the complete documentation.
-/
-echo x - elvprsv.man
-sed '/^X/s///' > elvprsv.man << '/'
-X.TH ELVPRSV 1
-X.SH NAME
-Xelvprsv - Preserve the the modified version of a file after a crash.
-X.SH SYNOPSIS
-X.nf
-X\fB\fBelvprsv\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
-X\fB\fBelvprsv\fP -R /tmp/\fIfilename\fP...
-X.fi
-X.SH DESCRIPTION
-X.PP
-X\fIelvprsv\fP preserves your edited text after \fIelvis\fP dies.
-XThe text can be recovered later, via the \fIelvprsv\fP program.
-X.PP
-XFor UNIX-like systems,
-Xyou should never need to run this program from the command line.
-XIt is run automatically when \fIelvis\fP is about to die,
-Xand it should be run (via /etc/rc) when the computer is booted.
-XTHAT'S ALL!
-X.PP
-XFor non-UNIX systems such as MS-DOS, you can either use \fIelvprsv\fP
-Xthe same way as under UNIX systems (by running it from your AUTOEXEC.BAT file),
-Xor you can run it separately with the "-R" flag to recover the files
-Xin one step.
-X.PP
-XIf you're editing a file when \fIelvis\fP dies
-X(due to a bug, system crash, power failure, etc.)
-Xthen \fIelvprsv\fP will preserve the most recent version of your text.
-XThe preserved text is stored in a special directory; it does NOT overwrite
-Xyour text file automatically.
-X.PP
-X\fIelvprsv\fP will send mail to any user whose work it preserves,
-Xif your operating system normally supports mail.
-X.SH FILES
-X.IP /tmp/elv*
-XThe temporary file that \fIelvis\fP was using when it died.
-X.IP /usr/preserve/p*
-XThe text that is preserved by \fIelvprsv\fP.
-X.IP /usr/preserve/Index
-XA text file which lists the names of all preserved files, and the names
-Xof the /usr/preserve/p* files which contain their preserved text.
-X.SH BUGS
-X.PP
-XDue to the permissions on the /usr/preserve directory, on UNIX systems
-X\fIelvprsv\fP must be run as superuser.
-XThis is accomplished by making the \fIelvprsv\fP executable be owned by "root"
-Xand turning on its "set user id" bit.
-X.PP
-XIf you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvprsv\fP will pretend
-Xthat the file was named "foo".
-X.SH AUTHOR
-X.nf
-XSteve Kirkendall
-Xkirkenda@cs.pdx.edu
-X.fi
-/
-echo x - elvrec.man
-sed '/^X/s///' > elvrec.man << '/'
-X.TH ELVREC 1
-X.SH NAME
-Xelvrec - Recover the modified version of a file after a crash
-X.SH SYNOPSIS
-X.nf
-X\fBelvrec\fP [\fIpreservedfile\fP [\fInewfile\fR]]
-X.fi
-X.SH DESCRIPTION
-X.PP
-XIf you're editing a file when \fIelvis\fP dies, the system crashes, or power fails,
-Xthe most recent version of your text will be preserved.
-XThe preserved text is stored in a special directory; it does NOT overwrite
-Xyour text file automatically.
-X.PP
-XThe \fIelvrec\fP program locates the preserved version of a given file,
-Xand writes it over the top of your text file -- or to a new file, if you prefer.
-XThe recovered file will have nearly all of your changes.
-X.PP
-XTo see a list of all recoverable files, run \fIelvrec\fP with no arguments.
-X.SH FILES
-X.IP /usr/preserve/p*
-XThe text that was preserved when \fIelvis\fP died.
-X.IP /usr/preserve/Index
-XA text file which lists the names of all preserved files, and the names
-Xof the /usr/preserve/p* files which contain their preserved text.
-X.SH BUGS
-X.PP
-X\fIelvrec\fP is very picky about filenames.
-XYou must tell it to recover the file using exactly the same pathname as
-Xwhen you were editing it.
-XThe simplest way to do this is to go into the same directory that you were
-Xediting, and invoke \fIelvrec\fP with the same filename as \fIelvis\fP.
-XIf that doesn't work, then try running \fIelvrec\fP with no arguments,
-Xto see exactly which pathname it is using for the desired file.
-X.PP
-XDue to the permissions on the /usr/preserve directory, on UNIX systems
-X\fIelvrec\fP must be run as superuser.
-XThis is accomplished by making the \fIelvrec\fP executable be owned by "root"
-Xand setting its "set user id" bit.
-X.PP
-XIf you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvrec\fP
-Xwill pretend that the file was named "foo".
-X.SH AUTHOR
-X.nf
-XSteve Kirkendall
-Xkirkenda@cs.pdx.edu
-X.fi
-/
-echo x - fmt.man
-sed '/^X/s///' > fmt.man << '/'
-X.TH FMT 1
-X.SH NAME
-Xfmt - adjust line-length for paragraphs of text
-X.SH SYNOPSIS
-X\fBfmt\fP [\-\fIwidth\fP] [\fIfiles\fP]...
-X.SH DESCRIPTION
-X\fIfmt\fR is a simple text formatter.
-XIt inserts or deletes newlines, as necessary, to make all lines in a
-Xparagraph be approximately the same width.
-XIt preserves indentation and word spacing.
-X.PP
-XThe default line width is 72 characters.
-XYou can override this with the \-\fIwidth\fR flag.
-XIf you don't name any files on the command line,
-Xthen \fIfmt\fR will read from stdin.
-X.PP
-XIt is typically used from within \fIvi\fR to adjust the line breaks
-Xin a single paragraph.
-XTo do this, move the cursor to the top of the paragraph,
-Xtype "!}fmt", and
-Xhit <Return>.
-X.SH AUTHOR
-X.nf
-XSteve Kirkendall
-Xkirkenda@cs.pdx.edu
-X.fi
-/
-echo x - ref.man
-sed '/^X/s///' > ref.man << '/'
-X.TH REF 1
-X.SH NAME
-Xref - Display a C function header
-X.SH SYNOPSIS
-X\fBref\fR [-t] [-c \fIclass\fR]... [-f \fIfile\fR]... \fItag\fR
-X.SH DESCRIPTION
-X\fIref\fP quickly locates and displays the header of a function.
-XTo do this, \fIref\fR
-Xlooks in the "tags" file for the line that describes the function, and then 
-Xscans the source file for the function.
-XWhen it locates the function, it displays an introductory comment
-X(if there is one), the function's declaration, and the declarations of all
-Xarguments.
-X.SH "SEARCH METHOD"
-X.PP
-X\fIref\fR uses a fairly sophisticated tag look-up algorithm.
-XIf you supply a filename via \fB-f\fR \fIfile\fR, then elvis first scans
-Xthe tags file for a static tag from that file.
-XThis search is limited to the tags file in the current directory.
-X.PP
-XIf you supply a classname via \fB-c\fR \fIclass\fR, then elvis searches
-Xfor a tag from that class.
-XThis search is not limited to the current directory;
-XYou can supply a list of directories in the environment variable \fITAGPATH\fR,
-Xand \fIref\fR will search through the "tags" file in each directory until it finds
-Xa tag in the desired class.
-X.PP
-XIf that fails, \fIref\fR will then try to look up an ordinary global tag.
-XThis search checks all of the directories listed in \fITAGPATH\fR, too.
-X.PP
-XIf you've given the \fB-t\fR flag, then \fIref\fR will simply output the tag line that
-Xit found, and then exit.
-XWithout \fB-t\fR, though, \fIref\fR will search for the tag line.
-XIt will try to open the source file, which should be in the same directory
-Xas the tags file where the tag was discovered.
-XIf the source file doesn't exist, or is unreadable, then \fIref\fR will try to open
-Xa file called "\fIrefs\fR" in that directory.
-XEither way, \fIref\fR will try to locate the tag, and display whatever it finds.
-X.SH "INTERACTION WITH ELVIS"
-X.PP
-X\fIref\fP is used by \fIelvis\fR' shift-K command.
-XIf the cursor is located on a word such as "splat", in the file "foo.c",
-Xthen \fIelvis\fR will invoke \fIref\fR with the command "ref -f foo.c splat".
-X.PP
-XIf \fIelvis\fR has been compiled with the -DEXTERNAL_TAGS flag, then \fIelvis\fR will
-Xuse \fIref\fR \fB\fRto scan the tags files.
-XThis is slower than the built-in tag searching, but it allows \fIelvis\fR to access
-Xthe more sophisticated tag lookup provided by \fIref\fR.
-XOther than that, external tags should act exactly like internal tags.
-X.SH OPTIONS
-X.IP \fB-t\fR
-XOutput tag info, instead of the function header.
-X.IP "\fB-f\fR \fIfile\fR"
-XThe tag might be a static function in \fIfile\fR.
-XYou can use several -f flags to have \fIref\fR consider static tags from more than one file.
-X.IP "\fB-c\fR \fIclass\fR"
-XThe tag might be a member of class \fIclass\fR.
-XYou can use several -c flags to have \fIref\fR consider tags from more than one class.
-X.SH FILES
-X.IP \fBtags\fR
-XList of function names and their locations, generated by \fIctags\fR.
-X.IP \fBrefs\fR
-XFunction headers extracted from source files (optional).
-X.SH ENVIRONMENT
-X.IP \fBTAGPATH\fR
-XList of directories to be searched.
-XThe elements in the list are separated by either
-Xsemicolons (for MS-DOS, Atari TOS, and AmigaDos), or
-Xby colons (every other operating system).
-XFor each operating system, \fIref\fR has a built-in default which is probably
-Xadequate.
-X.SH NOTES
-X.PP
-XYou might want to generate a "tags" file the directory that contains the
-Xsource code for standard C library on your system.
-XIf licensing restrictions prevent you from making the library source readable
-Xby everybody, then you can have \fIctags\fR generate a "refs" file,
-Xand make "refs" readable by everybody.
-X.PP
-XIf your system doesn't come with the library source code, then perhaps you
-Xcan produce something workable from the \fIlint\fR libraries.
-X.SH "SEE ALSO"
-Xelvis(1), ctags(1)
-X.SH AUTHOR
-X.nf
-XSteve Kirkendall
-Xkirkenda@cs.pdx.edu
-X.fi
-/
diff --git a/commands/elvis/Readme.txt b/commands/elvis/Readme.txt
deleted file mode 100644 (file)
index dc7656f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Elvis is a clone of vi/ex, the standard UNIX editor.  Elvis supports
-nearly all of the vi/ex commands, in both visual mode and colon mode.
-
-Elvis runs under BSD UNIX, AT&T SysV UNIX, SCO Xenix, Minix, MS-DOS
-(Turbo-C or MSC 5.1), Atari TOS, OS9/68000, Coherent, VMS, and AmigaDos.
-Ports to other operating systems are in progress; contact me before you
-start porting it to some other OS, because somebody else may have
-already done it for you.
-
-Elvis is freely redistributable, in either source form or executable
-form.  There are no restrictions on how you may use it.
-
-The file "elvisman.txt" contains the manual for elvis.  It is a plain
-ASCII file with nothing more exotic than a newline character.  It is
-formatted for 66-line, 80-column pages.  There may also be an archive of
-"*.ms" and "*.man" files, which contain the TROFF source text used to
-generate that manual.
-
-The file named "Makefile.mix" is used to compile elvis for all systems
-except VMS and possibly MS-DOS.  You should copy "Makefile.mix" to
-"Makefile", and then edit "Makefile" to select the appropriate group of
-settings for your system.
-
-
-Author: Steve Kirkendall
-       14407 SW Teal Blvd. #C
-       Beaverton, OR   97005
-
-E-mail:        kirkenda@cs.pdx.edu
-
-Phone: (503) 643-6980
diff --git a/commands/elvis/blk.c b/commands/elvis/blk.c
deleted file mode 100644 (file)
index db41d93..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/* blk.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the functions that get/put blocks from the temp file.
- * It also contains the "do" and "undo" functions.
- */
-
-#include "config.h"
-#include "vi.h"
-
-#ifndef NBUFS
-# define NBUFS 5               /* must be at least 3 -- more is better */
-#endif
-
-
-/*------------------------------------------------------------------------*/
-
-BLK            hdr;            /* buffer for the header block */
-
-static int     b4cnt;          /* used to count context of beforedo/afterdo */
-static struct _blkbuf
-{
-       BLK             buf;            /* contents of a text block */
-       unsigned short  logical;        /* logical block number */
-       int             dirty;          /* must the buffer be rewritten? */
-}
-               blk[NBUFS],     /* buffers for text[?] blocks */
-               *toonew,        /* buffer which shouldn't be recycled yet */
-               *newtoo,        /* another buffer which should be recycled */
-               *recycle = blk; /* next block to be recycled */
-
-
-
-
-
-/* This function wipes out all buffers */
-void blkinit()
-{
-       int     i;
-
-       for (i = 0; i < NBUFS; i++)
-       {
-               blk[i].logical = 0;
-               blk[i].dirty = FALSE;
-       }
-       for (i = 0; i < MAXBLKS; i++)
-       {
-               hdr.n[i] = 0;
-       }
-}
-
-/* This function allocates a buffer and fills it with a given block's text */
-BLK *blkget(logical)
-       int     logical;        /* logical block number to fetch */
-{
-       REG struct _blkbuf      *this;  /* used to step through blk[] */
-       REG int i;
-
-       /* if logical is 0, just return the hdr buffer */
-       if (logical == 0)
-       {
-               return &hdr;
-       }
-
-       /* see if we have that block in mem already */
-       for (this = blk; this < &blk[NBUFS]; this++)
-       {
-               if (this->logical == logical)
-               {
-                       newtoo = toonew;
-                       toonew = this;
-                       return &this->buf;
-               }
-       }
-
-       /* choose a block to be recycled */
-       do
-       {
-               this = recycle++;
-               if (recycle == &blk[NBUFS])
-               {
-                       recycle = blk;
-               }
-       } while (this == toonew || this == newtoo);
-
-       /* if it contains a block, flush that block */
-       blkflush(this);
-
-       /* fill this buffer with the desired block */
-       this->logical = logical;
-       if (hdr.n[logical])
-       {
-               /* it has been used before - fill it from tmp file */
-               lseek(tmpfd, (long)hdr.n[logical] * (long)BLKSIZE, 0);
-               if (read(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
-               {
-                       msg("Error reading back from tmp file!");
-               }
-       }
-       else
-       {
-               /* it is new - zero it */
-               for (i = 0; i < BLKSIZE; i++)
-               {
-                       this->buf.c[i] = 0;
-               }
-       }
-
-       /* This isn't really a change, but it does potentially invalidate
-        * the kinds of shortcuts that the "changes" variable is supposed
-        * to protect us from... so count it as a change.
-        */
-       changes++;
-
-       /* mark it as being "not dirty" */
-       this->dirty = 0;
-
-       /* return it */
-       newtoo = toonew;
-       toonew = this;
-       return &this->buf;
-}
-
-
-
-/* This function writes a block out to the temporary file */
-void blkflush(this)
-       REG struct _blkbuf      *this;  /* the buffer to flush */
-{
-       long            seekpos;        /* seek position of the new block */
-       unsigned short  physical;       /* physical block number */
-
-       /* if its empty (an orphan blkadd() maybe?) then make it dirty */
-       if (this->logical && !*this->buf.c)
-       {
-               blkdirty(&this->buf);
-       }
-
-       /* if it's an empty buffer or a clean version is on disk, quit */
-       if (!this->logical || hdr.n[this->logical] && !this->dirty)
-       {
-               return;
-       }
-
-       /* find a free place in the file */
-#ifndef NO_RECYCLE
-       seekpos = allocate();
-       lseek(tmpfd, seekpos, 0);
-#else
-       seekpos = lseek(tmpfd, 0L, 2);
-#endif
-       physical = seekpos / BLKSIZE;
-
-       /* put the block there */
-       if (write(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
-       {
-               msg("Trouble writing to tmp file");
-       }
-       this->dirty = FALSE;
-
-       /* update the header so it knows we put it there */
-       hdr.n[this->logical] = physical;
-}
-
-
-/* This function sets a block's "dirty" flag or deletes empty blocks */
-void blkdirty(bp)
-       BLK     *bp;    /* buffer returned by blkget() */
-{
-       REG int         i, j;
-       REG char        *scan;
-       REG int         k;
-
-       /* find the buffer */
-       for (i = 0; i < NBUFS && bp != &blk[i].buf; i++)
-       {
-       }
-#ifdef DEBUG
-       if (i >= NBUFS)
-       {
-               msg("blkdirty() called with unknown buffer at 0x%lx", bp);
-               return;
-       }
-       if (blk[i].logical == 0)
-       {
-               msg("blkdirty called with freed buffer");
-               return;
-       }
-#endif
-
-       /* if this block ends with line# INFINITY, then it must have been
-        * allocated unnecessarily during tmpstart().  Forget it.
-        */
-       if (lnum[blk[i].logical] == INFINITY)
-       {
-#ifdef DEBUG
-               if (blk[i].buf.c[0])
-               {
-                       msg("bkldirty called with non-empty extra BLK");
-               }
-#endif
-               blk[i].logical = 0;
-               blk[i].dirty = FALSE;
-               return;
-       }
-
-       /* count lines in this block */
-       for (j = 0, scan = bp->c; *scan && scan < bp->c + BLKSIZE; scan++)
-       {
-               if (*scan == '\n')
-               {
-                       j++;
-               }
-       }
-
-       /* adjust lnum, if necessary */
-       k = blk[i].logical;
-       j += (lnum[k - 1] - lnum[k]);
-       if (j != 0)
-       {
-               nlines += j;
-               while (k < MAXBLKS && lnum[k] != INFINITY)
-               {
-                       lnum[k++] += j;
-               }
-       }
-
-       /* if it still has text, mark it as dirty */
-       if (*bp->c)
-       {
-               blk[i].dirty = TRUE;
-       }
-       else /* empty block, so delete it */
-       {
-               /* adjust the cache */
-               k = blk[i].logical;
-               for (j = 0; j < NBUFS; j++)
-               {
-                       if (blk[j].logical >= k)
-                       {
-                               blk[j].logical--;
-                       }
-               }
-
-               /* delete it from hdr.n[] and lnum[] */
-               blk[i].logical = 0;
-               blk[i].dirty = FALSE;
-               while (k < MAXBLKS - 1)
-               {
-                       hdr.n[k] = hdr.n[k + 1];
-                       lnum[k] = lnum[k + 1];
-                       k++;
-               }
-               hdr.n[MAXBLKS - 1] = 0;
-               lnum[MAXBLKS - 1] = INFINITY;
-       }
-}
-
-
-/* insert a new block into hdr, and adjust the cache */
-BLK *blkadd(logical)
-       int     logical;        /* where to insert the new block */
-{
-       REG int i;
-
-       /* adjust hdr and lnum[] */
-       for (i = MAXBLKS - 1; i > logical; i--)
-       {
-               hdr.n[i] = hdr.n[i - 1];
-               lnum[i] = lnum[i - 1];
-       }
-       hdr.n[logical] = 0;
-       lnum[logical] = lnum[logical - 1];
-
-       /* adjust the cache */
-       for (i = 0; i < NBUFS; i++)
-       {
-               if (blk[i].logical >= logical)
-               {
-                       blk[i].logical++;
-               }
-       }
-
-       /* return the new block, via blkget() */
-       return blkget(logical);
-}
-
-
-/* This function forces all dirty blocks out to disk */
-void blksync()
-{
-       int     i;
-
-       for (i = 0; i < NBUFS; i++)
-       {
-               /* blk[i].dirty = TRUE; */
-               blkflush(&blk[i]);
-       }
-       if (*o_sync)
-       {
-               sync();
-       }
-}
-
-/*------------------------------------------------------------------------*/
-
-static MARK    undocurs;       /* where the cursor should go if undone */
-static long    oldnlines;
-static long    oldlnum[MAXBLKS];
-
-
-/* This function should be called before each command that changes the text.
- * It defines the state that undo() will reset the file to.
- */
-void beforedo(forundo)
-       int             forundo;        /* boolean: is this for an undo? */
-{
-       REG int         i;
-       REG long        l;
-
-       /* if this is a nested call to beforedo, quit! Use larger context */
-       if (b4cnt++ > 0)
-       {
-               return;
-       }
-
-       /* force all block buffers to disk */
-       blksync();
-
-#ifndef NO_RECYCLE
-       /* perform garbage collection on blocks from tmp file */
-       garbage();
-#endif
-
-       /* force the header out to disk */
-       lseek(tmpfd, 0L, 0);
-       if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) != BLKSIZE)
-       {
-               msg("Trouble writing header to tmp file ");
-       }
-
-       /* copy or swap oldnlines <--> nlines, oldlnum <--> lnum */
-       if (forundo)
-       {
-               for (i = 0; i < MAXBLKS; i++)
-               {
-                       l = lnum[i];
-                       lnum[i] = oldlnum[i];
-                       oldlnum[i] = l;
-               }
-               l = nlines;
-               nlines = oldnlines;
-               oldnlines = l;
-       }
-       else
-       {
-               for (i = 0; i < MAXBLKS; i++)
-               {
-                       oldlnum[i] = lnum[i];
-               }
-               oldnlines = nlines;
-       }
-
-       /* save the cursor position */
-       undocurs = cursor;
-
-       /* upon return, the calling function continues and makes changes... */
-}
-
-/* This function marks the end of a (nested?) change to the file */
-void afterdo()
-{
-       if (--b4cnt)
-       {
-               /* after abortdo(), b4cnt may decribe nested beforedo/afterdo
-                * pairs incorrectly.  If it is decremented to often, then
-                * keep b4cnt sane but don't do anything else.
-                */
-               if (b4cnt < 0)
-                       b4cnt = 0;
-
-               return;
-       }
-
-       /* make sure the cursor wasn't left stranded in deleted text */
-       if (markline(cursor) > nlines)
-       {
-               cursor = MARK_LAST;
-       }
-       /* NOTE: it is still possible that markidx(cursor) is after the
-        * end of a line, so the Vi mode will have to take care of that
-        * itself */
-
-       /* if a significant change has been made to this file, then set the
-        * MODIFIED flag.
-        */
-       if (significant)
-       {
-               setflag(file, MODIFIED);
-               setflag(file, UNDOABLE);
-       }       
-}
-
-/* This function cuts short the current set of changes.  It is called after
- * a SIGINT.
- */
-void abortdo()
-{
-       /* finish the operation immediately. */
-       if (b4cnt > 0)
-       {
-               b4cnt = 1;
-               afterdo();
-       }
-
-       /* in visual mode, the screen is probably screwed up */
-       if (mode == MODE_COLON)
-       {
-               mode = MODE_VI;
-       }
-       if (mode == MODE_VI)
-       {
-               redraw(MARK_UNSET, FALSE);
-       }
-}
-
-/* This function discards all changes made since the last call to beforedo() */
-int undo()
-{
-       BLK             oldhdr;
-
-       /* if beforedo() has never been run, fail */
-       if (!tstflag(file, UNDOABLE))
-       {
-               msg("You haven't modified this file yet.");
-               return FALSE;
-       }
-
-       /* read the old header form the tmp file */
-       lseek(tmpfd, 0L, 0);
-       if (read(tmpfd, oldhdr.c, (unsigned)BLKSIZE) != BLKSIZE)
-       {
-               msg("Trouble rereading the old header from tmp file");
-       }
-
-       /* "do" the changed version, so we can undo the "undo" */
-       cursor = undocurs;
-       beforedo(TRUE);
-       afterdo();
-
-       /* wipe out the block buffers - we can't assume they're correct */
-       blkinit();
-
-       /* use the old header -- and therefore the old text blocks */
-       hdr = oldhdr;
-
-       /* This is a change */
-       significant = TRUE;
-       changes++;
-
-       return TRUE;
-}
diff --git a/commands/elvis/cmd1.c b/commands/elvis/cmd1.c
deleted file mode 100644 (file)
index 4930052..0000000
+++ /dev/null
@@ -1,1774 +0,0 @@
-/* cmd1.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains some of the EX commands - mostly ones that deal with
- * files, options, etc. -- anything except text.
- */
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-#include "regexp.h"
-
-#ifdef DEBUG
-/* print the selected lines with info on the blocks */
-/*ARGSUSED*/
-void cmd_debug(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       REG char        *scan;
-       REG long        l;
-       REG int         i;
-       int             len;
-
-       /* scan lnum[] to determine which block its in */
-       l = markline(frommark);
-       for (i = 1; l > lnum[i]; i++)
-       {
-       }
-
-       do
-       {
-               /* fetch text of the block containing that line */
-               scan = blkget(i)->c;
-
-               /* calculate its length */
-               if (scan[BLKSIZE - 1])
-               {
-                       len = BLKSIZE;
-               }
-               else
-               {
-                       len = strlen(scan);
-               }
-
-               /* print block stats */
-               msg("##### hdr[%d]=%d, lnum[%d-1]=%ld, lnum[%d]=%ld (%ld lines)",
-                       i, hdr.n[i], i, lnum[i-1], i, lnum[i], lnum[i] - lnum[i - 1]);
-               msg("##### len=%d, buf=0x%lx, %sdirty",
-                       len, scan, ((int *)scan)[MAXBLKS + 1] ? "" : "not ");
-               if (bang)
-               {
-                       while (--len >= 0)
-                       {
-                               addch(*scan);
-                               scan++;
-                       }
-               }
-               exrefresh();
-
-               /* next block */
-               i++;
-       } while (i < MAXBLKS && lnum[i] && lnum[i - 1] < markline(tomark));
-}
-
-
-/* This function checks a lot of conditions to make sure they aren't screwy */
-/*ARGSUSED*/
-void cmd_validate(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       char    *scan;
-       int     i;
-       int     nlcnt;  /* used to count newlines */
-       int     len;    /* counts non-NUL characters */
-
-       /* check lnum[0] */
-       if (lnum[0] != 0L)
-       {
-               msg("lnum[0] = %ld", lnum[0]);
-       }
-
-       /* check each block */
-       for (i = 1; lnum[i] <= nlines; i++)
-       {
-               scan = blkget(i)->c;
-               if (scan[BLKSIZE - 1])
-               {
-                       msg("block %d has no NUL at the end", i);
-               }
-               else
-               {
-                       for (nlcnt = len = 0; *scan; scan++, len++)
-                       {
-                               if (*scan == '\n')
-                               {
-                                       nlcnt++;
-                               }
-                       }
-                       if (scan[-1] != '\n')
-                       {
-                               msg("block %d doesn't end with '\\n' (length %d)", i, len);
-                       }
-                       if (bang || nlcnt != lnum[i] - lnum[i - 1])
-                       {
-                               msg("block %d (line %ld?) has %d lines, but should have %ld",
-                                       i, lnum[i - 1] + 1L, nlcnt, lnum[i] - lnum[i - 1]);
-                       }
-               }
-               exrefresh();
-       }
-
-       /* check lnum again */
-       if (lnum[i] != INFINITY)
-       {
-               msg("hdr.n[%d] = %d, but lnum[%d] = %ld",
-                       i, hdr.n[i], i, lnum[i]);
-       }
-
-       msg("# = \"%s\", %% = \"%s\"", prevorig, origname);
-       msg("V_from=%ld.%d, cursor=%ld.%d", markline(V_from), markidx(V_from), markline(cursor), markidx(cursor));
-}
-#endif /* DEBUG */
-
-
-/*ARGSUSED*/
-void cmd_mark(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       /* validate the name of the mark */
-       if (*extra == '"')
-       {
-               extra++;
-       }
-       /* valid mark names are lowercase ascii characters */
-       if (!isascii(*extra) || !islower(*extra) || extra[1])
-       {
-               msg("Invalid mark name");
-               return;
-       }
-
-       mark[*extra - 'a'] = tomark;
-}
-
-/*ARGSUSED*/
-void cmd_write(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       int             fd;
-       int             append; /* boolean: write in "append" mode? */
-       REG long        l;
-       REG char        *scan;
-       REG int         i;
-
-       /* if writing to a filter, then let filter() handle it */
-       if (*extra == '!')
-       {
-               filter(frommark, tomark, extra + 1, FALSE);
-               return;
-       }
-
-       /* if all lines are to be written, use tmpsave() */
-       if (frommark == MARK_FIRST && tomark == MARK_LAST && cmd == CMD_WRITE)
-       {
-               tmpsave(extra, bang);
-               return;
-       }
-
-       /* see if we're going to do this in append mode or not */
-       append = FALSE;
-       if (extra[0] == '>' && extra[1] == '>')
-       {
-               extra += 2;
-               append = TRUE;
-       }
-
-       /* either the file must not exist, or we must have a ! or be appending */
-       if (access(extra, 0) == 0 && !bang && !append)
-       {
-               msg("File already exists - Use :w! to overwrite");
-               return;
-       }
-
-       /* else do it line-by-line, like cmd_print() */
-       if (append)
-       {
-#ifdef O_APPEND
-               fd = open(extra, O_WRONLY|O_APPEND);
-#else
-               fd = open(extra, O_WRONLY);
-               if (fd >= 0)
-               {
-                       lseek(fd, 0L, 2);
-               }
-#endif
-       }
-       else
-       {
-               fd = -1; /* so we know the file isn't open yet */
-       }
-
-       if (fd < 0)
-       {
-               fd = creat(extra, FILEPERMS);
-               if (fd < 0)
-               {
-                       msg("Can't write to \"%s\"", extra);
-                       return;
-               }
-       }
-       for (l = markline(frommark); l <= markline(tomark); l++)
-       {
-               /* get the next line */
-               scan = fetchline(l);
-               i = strlen(scan);
-               scan[i++] = '\n';
-
-               /* print the line */
-               if (twrite(fd, scan, i) < i)
-               {
-                       msg("Write failed");
-                       break;
-               }
-       }
-       rptlines = markline(tomark) - markline(frommark) + 1;
-       rptlabel = "written";
-       close(fd);
-}      
-
-
-/*ARGSUSED*/
-void cmd_shell(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       static char     prevextra[80];
-
-       /* special case: ":sh" means ":!sh" */
-       if (cmd == CMD_SHELL)
-       {
-               extra = o_shell;
-               frommark = tomark = 0L;
-       }
-
-       /* if extra is "!", substitute previous command */
-       if (*extra == '!')
-       {
-               if (!*prevextra)
-               {
-                       msg("No previous shell command to substitute for '!'");
-                       return;
-               }
-               extra = prevextra;
-       }
-       else if (cmd == CMD_BANG && strlen(extra) < sizeof(prevextra) - 1)
-       {
-               strcpy(prevextra, extra);
-       }
-
-       /* warn the user if the file hasn't been saved yet */
-       if (*o_warn && tstflag(file, MODIFIED))
-       {
-               if (mode == MODE_VI)
-               {
-                       mode = MODE_COLON;
-               }
-               msg("Warning: \"%s\" has been modified but not yet saved", origname);
-       }
-
-       /* if no lines were specified, just run the command */
-       suspend_curses();
-       if (frommark == 0L)
-       {
-               system(extra);
-       }
-       else /* pipe lines from the file through the command */
-       {
-               filter(frommark, tomark, extra, TRUE);
-       }
-
-       /* resume curses quietly for MODE_EX, but noisily otherwise */
-       resume_curses(mode == MODE_EX);
-}
-
-
-/*ARGSUSED*/
-void cmd_global(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra; /* rest of the command line */
-{
-       char    *cmdptr;        /* the command from the command line */
-       char    cmdln[100];     /* copy of the command from the command line */
-       char    *line;          /* a line from the file */
-       long    l;              /* used as a counter to move through lines */
-       long    lqty;           /* quantity of lines to be scanned */
-       long    nchanged;       /* number of lines changed */
-       regexp  *re;            /* the compiled search expression */
-
-       /* can't nest global commands */
-       if (doingglobal)
-       {
-               msg("Can't nest global commands.");
-               rptlines = -1L;
-               return;
-       }
-
-       /* ":g! ..." is the same as ":v ..." */
-       if (bang)
-       {
-               cmd = CMD_VGLOBAL;
-       }
-
-       /* make sure we got a search pattern */
-       if (*extra != '/' && *extra != '?')
-       {
-               msg("Usage: %c /regular expression/ command", cmd == CMD_GLOBAL ? 'g' : 'v');
-               return;
-       }
-
-       /* parse & compile the search pattern */
-       cmdptr = parseptrn(extra);
-       if (!extra[1])
-       {
-               msg("Can't use empty regular expression with '%c' command", cmd == CMD_GLOBAL ? 'g' : 'v');
-               return;
-       }
-       re = regcomp(extra + 1);
-       if (!re)
-       {
-               /* regcomp found & described an error */
-               return;
-       }
-
-       /* for each line in the range */
-       doingglobal = TRUE;
-       ChangeText
-       {
-               /* NOTE: we have to go through the lines in a forward order,
-                * otherwise "g/re/p" would look funny.  *BUT* for "g/re/d"
-                * to work, simply adding 1 to the line# on each loop won't
-                * work.  The solution: count lines relative to the end of
-                * the file.  Think about it.
-                */
-               for (l = nlines - markline(frommark),
-                       lqty = markline(tomark) - markline(frommark) + 1L,
-                       nchanged = 0L;
-                    lqty > 0 && nlines - l >= 0 && nchanged >= 0L;
-                    l--, lqty--)
-               {
-                       /* fetch the line */
-                       line = fetchline(nlines - l);
-
-                       /* if it contains the search pattern... */
-                       if ((!regexec(re, line, 1)) == (cmd != CMD_GLOBAL))
-                       {
-                               /* move the cursor to that line */
-                               cursor = MARK_AT_LINE(nlines - l);
-
-                               /* do the ex command (without mucking up
-                                * the original copy of the command line)
-                                */
-                               strcpy(cmdln, cmdptr);
-                               rptlines = 0L;
-                               doexcmd(cmdln);
-                               nchanged += rptlines;
-                       }
-               }
-       }
-       doingglobal = FALSE;
-
-       /* free the regexp */
-       free(re);
-
-       /* Reporting...*/
-       rptlines = nchanged;
-}
-
-
-/*ARGSUSED*/
-void cmd_file(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-#ifndef CRUNCH
-       /* if we're given a new filename, use it as this file's name */
-       if (extra && *extra)
-       {
-               strcpy(origname, extra);
-               storename(origname);
-               setflag(file, NOTEDITED);
-       }
-#endif
-       if (cmd == CMD_FILE)
-       {
-#ifndef CRUNCH
-               msg("\"%s\" %s%s%s %ld lines,  line %ld [%ld%%]",
-#else
-               msg("\"%s\" %s%s %ld lines,  line %ld [%ld%%]",
-#endif
-                       *origname ? origname : "[NO FILE]",
-                       tstflag(file, MODIFIED) ? "[MODIFIED]" : "",
-#ifndef CRUNCH
-                       tstflag(file, NOTEDITED) ?"[NOT EDITED]":"",
-#endif
-                       tstflag(file, READONLY) ? "[READONLY]" : "",
-                       nlines,
-                       markline(frommark),
-                       markline(frommark) * 100 / nlines);
-       }
-#ifndef CRUNCH
-       else if (markline(frommark) != markline(tomark))
-       {
-               msg("range \"%ld,%ld\" contains %ld lines",
-                       markline(frommark),
-                       markline(tomark),
-                       markline(tomark) - markline(frommark) + 1L);
-       }
-#endif
-       else
-       {
-               msg("%ld", markline(frommark));
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_edit(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       long    line = 1L;      /* might be set to prevline */
-#ifndef CRUNCH
-       char    *init = (char *)0;
-#endif
-
-
-       /* if ":vi", then switch to visual mode, and if no file is named
-        * then don't switch files.
-        */
-       if (cmd == CMD_VISUAL)
-       {
-               mode = MODE_VI;
-               msg("");
-               if (!*extra)
-               {
-                       return;
-               }
-       }
-
-       /* Editing previous file?  Then start at previous line */
-       if (!strcmp(extra, prevorig))
-       {
-               line = prevline;
-       }
-
-#ifndef CRUNCH
-       /* if we were given an explicit starting line, then start there */
-       if (*extra == '+')
-       {
-               for (init = ++extra; !isspace(*extra); extra++)
-               {
-               }
-               while (isspace(*extra))
-               {
-                       *extra++ = '\0';
-               }
-               if (!*init)
-               {
-                       init = "$";
-               }
-               if (!extra)
-               {
-                       extra = origname;
-               }
-       }
-#endif /* not CRUNCH */
-
-       /* switch files */
-       if (tmpabort(bang))
-       {
-               tmpstart(extra);
-               if (line <= nlines && line >= 1L)
-               {
-                       cursor = MARK_AT_LINE(line);
-               }
-#ifndef CRUNCH
-               if (init)
-               {
-                       doexcmd(init);
-               }
-#endif
-       }
-       else
-       {
-               msg("Use edit! to abort changes, or w to save changes");
-
-               /* so we can say ":e!#" next time... */
-               strcpy(prevorig, extra);
-               prevline = 1L;
-       }
-}
-
-/* This code is also used for rewind -- GB */
-
-/*ARGSUSED*/
-void cmd_next(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       int     i, j;
-       char    *scan;
-
-       /* if extra stuff given, use ":args" to define a new args list */
-       if (cmd == CMD_NEXT && extra && *extra)
-       {
-               cmd_args(frommark, tomark, cmd, bang, extra);
-       }
-
-       /* move to the next arg */
-       if (cmd == CMD_NEXT)
-       {
-               i = argno + 1;
-       }
-       else if (cmd == CMD_PREVIOUS)
-       {
-               i = argno - 1;
-       }
-       else /* cmd == CMD_REWIND */
-       {
-               i = 0;
-       }       
-       if (i < 0 || i >= nargs)
-       {
-               msg("No %sfiles to edit", cmd == CMD_REWIND ? "" : "more ");
-               return;
-       }
-
-       /* find & isolate the name of the file to edit */
-       for (j = i, scan = args; j > 0; j--)
-       {
-               while(*scan++)
-               {
-               }
-       }
-
-       /* switch to the next file */
-       if (tmpabort(bang))
-       {
-               tmpstart(scan);
-               argno = i;
-       }
-       else
-       {
-               msg("Use :%s! to abort changes, or w to save changes",
-                       cmd == CMD_NEXT ? "next" :
-                       cmd == CMD_PREVIOUS ? "previous" :
-                                       "rewind");
-       }
-}
-
-/* also called from :wq -- always writes back in this case */
-
-/*ARGSUSED*/
-void cmd_xit(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       static long     whenwarned;     /* when the user was last warned of extra files */
-       int             oldflag;
-
-       /* if there are more files to edit, then warn user */
-       if (argno >= 0 && argno + 1 < nargs && whenwarned != changes && (!bang || cmd != CMD_QUIT))
-       {
-               msg("More files to edit -- Use \":n\" to go to next file");
-               whenwarned = changes;
-               return;
-       }
-
-       if (cmd == CMD_QUIT)
-       {
-               oldflag = *o_autowrite;
-               *o_autowrite = FALSE;
-               if (tmpabort(bang))
-               {
-                       mode = MODE_QUIT;
-               }
-               else
-               {
-                       msg("Use q! to abort changes, or wq to save changes");
-               }
-               *o_autowrite = oldflag;
-       }
-       else
-       {
-               /* else try to save this file */
-               oldflag = tstflag(file, MODIFIED);
-               if (cmd == CMD_WQUIT)
-                       setflag(file, MODIFIED);
-               if (tmpend(bang))
-               {
-                       mode = MODE_QUIT;
-               }
-               else
-               {
-                       msg("Could not save file -- use quit! to abort changes, or w filename");
-               }
-               if (!oldflag)
-                       clrflag(file, MODIFIED);
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_args(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       char    *scan;
-       int     col;
-       int     arg;
-       int     scrolled = FALSE;
-       int     width;
-
-       /* if no extra names given, or just current name, then report the args
-        * we have now.
-        */
-       if (!extra || !*extra)
-       {
-               /* empty args list? */
-               if (nargs == 1 && !*args)
-               {
-                       return;
-               }
-
-               /* list the arguments */
-               for (scan = args, col = arg = 0;
-                    arg < nargs;
-                    scan += width + 1, col += width, arg++)
-               {
-                       width = strlen(scan);
-                       if (col + width >= COLS - 4)
-                       {
-                               addch('\n');
-                               col = 0;
-                               scrolled = TRUE;
-                       }
-                       else if (col > 0)
-                       {
-                               addch(' ');
-                               col++;
-                       }
-                       if (arg == argno)
-                       {
-                               addch('[');
-                               addstr(scan);
-                               addch(']');
-                               col += 2;
-                       }
-                       else
-                       {
-                               addstr(scan);
-                       }
-               }
-
-               /* write a trailing newline */
-               if ((mode == MODE_EX || mode == MODE_COLON || scrolled) && col)
-               {
-                       addch('\n');
-               }
-               exrefresh();    
-       }
-       else /* new args list given */
-       {
-               for (scan = args, nargs = 1; *extra; )
-               {
-                       if (isspace(*extra))
-                       {
-                               *scan++ = '\0';
-                               while (isspace(*extra))
-                               {
-                                       extra++;
-                               }
-                               if (*extra)
-                               {
-                                       nargs++;
-                               }
-                       }
-                       else
-                       {
-                               *scan++ = *extra++;
-                       }
-               }
-               *scan = '\0';
-
-               /* reset argno to before the first, so :next will go to first */
-               argno = -1;
-
-               if (nargs != 1)
-               {
-                        msg("%d files to edit", nargs);
-               }
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_cd(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       char    *getenv();
-
-#ifndef CRUNCH
-       /* if current file is modified, and no '!' was given, then error */
-       if (tstflag(file, MODIFIED) && !bang)
-       {
-               msg("File modified; use \"cd! %s\" to switch anyway", extra);
-       }
-#endif
-
-       /* default directory name is $HOME */
-       if (!*extra)
-       {
-               extra = getenv("HOME");
-               if (!extra)
-               {
-                       msg("environment variable $HOME not set");
-                       return;
-               }
-       }
-
-       /* go to the directory */
-       if (chdir(extra) < 0)
-       {
-               perror(extra);
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_map(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       char    *mapto;
-       char    *build, *scan;
-#ifndef NO_FKEY
-       static char *fnames[NFKEYS] =
-       {
-               "#10", "#1", "#2", "#3", "#4",
-               "#5", "#6", "#7", "#8", "#9",
-# ifndef NO_SHIFT_FKEY
-               "#10s", "#1s", "#2s", "#3s", "#4s",
-               "#5s", "#6s", "#7s", "#8s", "#9s",
-#  ifndef NO_CTRL_FKEY
-               "#10c", "#1c", "#2c", "#3c", "#4c",
-               "#5c", "#6c", "#7c", "#8c", "#9c",
-#   ifndef NO_ALT_FKEY
-               "#10a", "#1a", "#2a", "#3a", "#4a",
-               "#5a", "#6a", "#7a", "#8a", "#9a",
-#   endif
-#  endif
-# endif
-       };
-       int     key;
-#endif
-
-       /* "map" with no extra will dump the map table contents */
-       if (!*extra)
-       {
-#ifndef NO_ABBR
-               if (cmd == CMD_ABBR)
-               {
-                       dumpkey(bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP, TRUE);
-               }
-               else
-#endif
-               {
-                       dumpkey(bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, FALSE);
-               }
-       }
-       else
-       {
-               /* "extra" is key to map, followed by what it maps to */
-
-               /* handle quoting inside the "raw" string */
-               for (build = mapto = extra;
-                    *mapto && (*mapto != ' ' && *mapto != '\t');
-                    *build++ = *mapto++)
-               {
-                       if (*mapto == ctrl('V') && mapto[1])
-                       {
-                               mapto++;
-                       }
-               }
-
-               /* skip whitespace, and mark the end of the "raw" string */
-               while ((*mapto == ' ' || *mapto == '\t'))
-               {
-                       *mapto++ = '\0';
-               }
-               *build = '\0';
-
-               /* strip ^Vs from the "cooked" string */
-               for (scan = build = mapto; *scan; *build++ = *scan++)
-               {
-                       if (*scan == ctrl('V') && scan[1])
-                       {
-                               scan++;
-                       }
-               }
-               *build = '\0';
-
-#ifndef NO_FKEY
-               /* if the mapped string is '#' and a number, then assume
-                * the user wanted that function key
-                */
-               if (extra[0] == '#' && isdigit(extra[1]))
-               {
-                       key = atoi(extra + 1) % 10;
-# ifndef NO_SHIFT_FKEY
-                       build = extra + strlen(extra) - 1;
-                       if (*build == 's')
-                               key += 10;
-#  ifndef NO_CTRL_FKEY
-                       else if (*build == 'c')
-                               key += 20;
-#   ifndef NO_ALT_FKEY
-                       else if (*build == 'a')
-                               key += 30;
-#   endif
-#  endif
-# endif
-                       if (FKEY[key])
-                               mapkey(FKEY[key], mapto, bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, fnames[key]);
-                       else
-                               msg("This terminal has no %s key", fnames[key]);
-               }
-               else
-#endif
-#ifndef NO_ABBR
-               if (cmd == CMD_ABBR || cmd == CMD_UNABBR)
-               {
-                       mapkey(extra, mapto, bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP, "abbr");
-               }
-               else
-#endif
-               {
-                       mapkey(extra, mapto, bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, (char *)0);
-               }
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_set(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       if (!*extra)
-       {
-               dumpopts(FALSE);/* "FALSE" means "don't dump all" - only set */
-       }
-       else if (!strcmp(extra, "all"))
-       {
-               dumpopts(TRUE); /* "TRUE" means "dump all" - even unset vars */
-       }
-       else
-       {
-               setopts(extra);
-
-               /* That option may have affected the appearence of text */
-               changes++;
-       }
-}
-
-/*ARGSUSED*/
-void cmd_tag(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       int     fd;     /* file descriptor used to read the file */
-       char    *scan;  /* used to scan through the tmpblk.c */
-#ifdef INTERNAL_TAGS
-       char    *cmp;   /* char of tag name we're comparing, or NULL */
-       char    *end;   /* marks the end of chars in tmpblk.c */
-#else
-       int     i;
-#endif
-#ifndef NO_MAGIC
-       char    wasmagic; /* preserves the original state of o_magic */
-#endif
-       static char prevtag[30];
-
-       /* if no tag is given, use the previous tag */
-       if (!extra || !*extra)
-       {
-               if (!*prevtag)
-               {
-                       msg("No previous tag");
-                       return;
-               }
-               extra = prevtag;
-       }
-       else
-       {
-               strncpy(prevtag, extra, sizeof prevtag);
-               prevtag[sizeof prevtag - 1] = '\0';
-       }
-
-#ifndef INTERNAL_TAGS
-       /* use "ref" to look up the tag info for this tag */
-       sprintf(tmpblk.c, "ref -t %s%s %s", (*origname ? "-f" : ""),origname, prevtag);
-       fd = rpipe(tmpblk.c, 0);
-       if (fd < 0)
-       {
-               msg("Can't run \"%s\"", tmpblk.c);
-               return;
-       }
-
-       /* try to read the tag info */
-       for (scan = tmpblk.c;
-            (i = tread(fd, scan, scan - tmpblk.c + BLKSIZE)) > 0;
-            scan += i)
-       {
-       }
-       *scan = '\0';
-
-       /* close the pipe.  abort if error */
-       if (rpclose(fd) != 0 || scan < tmpblk.c + 3)
-       {
-               msg("tag \"%s\" not found", extra);
-               return;
-       }
-
-#else /* use internal code to look up the tag */
-       /* open the tags file */
-       fd = open(TAGS, O_RDONLY);
-       if (fd < 0)
-       {
-               msg("No tags file");
-               return;
-       }
-
-       /* Hmmm... this would have been a lot easier with <stdio.h> */
-
-       /* find the line with our tag in it */
-       for(scan = end = tmpblk.c, cmp = extra; ; scan++)
-       {
-               /* read a block, if necessary */
-               if (scan >= end)
-               {
-                       end = tmpblk.c + tread(fd, tmpblk.c, BLKSIZE);
-                       scan = tmpblk.c;
-                       if (scan >= end)
-                       {
-                               msg("tag \"%s\" not found", extra);
-                               close(fd);
-                               return;
-                       }
-               }
-
-               /* if we're comparing, compare... */
-               if (cmp)
-               {
-                       /* matched??? wow! */
-                       if (!*cmp && *scan == '\t')
-                       {
-                               break;
-                       }
-                       if (*cmp++ != *scan)
-                       {
-                               /* failed! skip to newline */
-                               cmp = (char *)0;
-                       }
-               }
-
-               /* if we're skipping to newline, do it fast! */
-               if (!cmp)
-               {
-                       while (scan < end && *scan != '\n')
-                       {
-                               scan++;
-                       }
-                       if (scan < end)
-                       {
-                               cmp = extra;
-                       }
-               }
-       }
-
-       /* found it! get the rest of the line into memory */
-       for (cmp = tmpblk.c, scan++; scan < end && *scan != '\n'; )
-       {
-               *cmp++ = *scan++;
-       }
-       if (scan == end)
-       {
-               tread(fd, cmp, BLKSIZE - (int)(cmp - tmpblk.c));
-       }
-       else
-               *cmp = *scan;
-
-       /* we can close the tags file now */
-       close(fd);
-#endif /* INTERNAL_TAGS */
-
-       /* extract the filename from the line, and edit the file */
-       for (scan = tmpblk.c; *scan != '\t'; scan++)
-       {
-       }
-       *scan++ = '\0';
-       if (strcmp(origname, tmpblk.c) != 0)
-       {
-               if (!tmpabort(bang))
-               {
-                       msg("Use :tag! to abort changes, or :w to save changes");
-                       return;
-               }
-               tmpstart(tmpblk.c);
-       }
-
-       /* move to the desired line (or to line 1 if that fails) */
-#ifndef NO_MAGIC
-       wasmagic = *o_magic;
-       *o_magic = FALSE;
-#endif
-       cursor = MARK_FIRST;
-       linespec(scan, &cursor);
-       if (cursor == MARK_UNSET)
-       {
-               cursor = MARK_FIRST;
-               msg("Tag's address is out of date");
-       }
-#ifndef NO_MAGIC
-       *o_magic = wasmagic;
-#endif
-}
-
-
-
-
-
-/* describe this version of the program */
-/*ARGSUSED*/
-void cmd_version(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       msg("%s", VERSION);
-#ifdef CREDIT
-       msg("%s", CREDIT);
-#endif
-#ifdef CREDIT2
-       msg("%s", CREDIT2);
-#endif
-#ifdef COMPILED_BY
-       msg("Compiled by %s", COMPILED_BY);
-#endif
-#ifdef COPYING
-       msg("%s", COPYING);
-#endif
-}
-
-
-#ifndef NO_MKEXRC
-/* make a .exrc file which describes the current configuration */
-/*ARGSUSED*/
-void cmd_mkexrc(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       int     fd;
-
-       /* the default name for the .exrc file EXRC */
-       if (!*extra)
-       {
-               extra = EXRC;
-       }
-
-       /* create the .exrc file */
-       fd = creat(extra, FILEPERMS);
-       if (fd < 0)
-       {
-               msg("Couldn't create a new \"%s\" file", extra);
-               return;
-       }
-
-       /* save stuff */
-       saveopts(fd);
-       savemaps(fd, FALSE);
-#ifndef NO_ABBR
-       savemaps(fd, TRUE);
-#endif
-#ifndef NO_DIGRAPH
-       savedigs(fd);
-#endif
-#ifndef NO_COLOR
-       savecolor(fd);
-#endif
-
-       /* close the file */
-       close(fd);
-       msg("Configuration saved");
-}
-#endif
-
-#ifndef NO_DIGRAPH
-/*ARGSUSED*/
-void cmd_digraph(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       do_digraph(bang, extra);
-}
-#endif
-
-
-#ifndef NO_ERRLIST 
-static char    errfile[256];   /* the name of a file containing an error */
-static long    errline;        /* the line number for an error */
-static int     errfd = -2;     /* fd of the errlist file */
-
-/* This static function tries to parse an error message.
- *
- * For most compilers, the first word is taken to be the name of the erroneous
- * file, and the first number after that is taken to be the line number where
- * the error was detected.  The description of the error follows, possibly
- * preceded by an "error ... :" or "warning ... :" label which is skipped.
- *
- * For Coherent, error messages look like "line#: filename: message".
- *
- * For non-error lines, or unparsable error lines, this function returns NULL.
- * Normally, though, it alters errfile and errline, and returns a pointer to
- * the description.
- */
-static char *parse_errmsg(text)
-       REG char        *text;
-{
-       REG char        *cpy;
-       long            atol();
-# if COHERENT || TOS /* any Mark Williams compiler */
-       /* Get the line number.  If no line number, then ignore this line. */
-       errline = atol(text);
-       if (errline == 0L)
-               return (char *)0;
-
-       /* Skip to the start of the filename */
-       while (*text && *text++ != ':')
-       {
-       }
-       if (!*text++)
-               return (char *)0;
-
-       /* copy the filename to errfile */
-       for (cpy = errfile; *text && (*cpy++ = *text++) != ':'; )
-       {
-       }
-       if (!*text++)
-               return (char *)0;
-       cpy[-1] = '\0';
-
-       return text;
-# else /* not a Mark Williams compiler */
-       char            *errmsg;
-
-       /* the error message is the whole line, by default */
-       errmsg = text;
-
-       /* skip leading garbage */
-       while (*text && !isalnum(*text))
-       {
-               text++;
-       }
-
-       /* copy over the filename */
-       cpy = errfile;
-       while(isalnum(*text) || *text == '.')
-       {
-               *cpy++ = *text++;
-       }
-       *cpy = '\0';
-
-       /* ignore the name "Error" and filenames that contain a '/' */
-       if (*text == '/' || !*errfile || !strcmp(errfile + 1, "rror") || access(errfile, 0) < 0)
-       {
-               return (char *)0;
-       }
-
-       /* skip garbage between filename and line number */
-       while (*text && !isdigit(*text))
-       {
-               text++;
-       }
-
-       /* if the number is part of a larger word, then ignore this line */
-       if (*text && isalpha(text[-1]))
-       {
-               return (char *)0;
-       }
-
-       /* get the error line */
-       errline = 0L;
-       while (isdigit(*text))
-       {
-               errline *= 10;
-               errline += (*text - '0');
-               text++;
-       }
-
-       /* any line which lacks a filename or line number should be ignored */
-       if (!errfile[0] || !errline)
-       {
-               return (char *)0;
-       }
-
-       /* locate the beginning of the error description */
-       while (*text && !isspace(*text))
-       {
-               text++;
-       }
-       while (*text)
-       {
-#  ifndef CRUNCH
-               /* skip "error #:" and "warning #:" clauses */
-               if (!strncmp(text + 1, "rror ", 5)
-                || !strncmp(text + 1, "arning ", 7)
-                || !strncmp(text + 1, "atal error", 10))
-               {
-                       do
-                       {
-                               text++;
-                       } while (*text && *text != ':');
-                       continue;
-               }
-#  endif
-
-               /* anything other than whitespace or a colon is important */
-               if (!isspace(*text) && *text != ':')
-               {
-                       errmsg = text;
-                       break;
-               }
-
-               /* else keep looking... */
-               text++;
-       }
-
-       return errmsg;
-# endif /* not COHERENT */
-}
-
-/*ARGSUSED*/
-void cmd_errlist(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       static long     endline;/* original number of lines in this file */
-       static long     offset; /* offset of the next line in the errlist file */
-       int             i;
-       char            *errmsg;
-
-       /* if a new errlist file is named, open it */
-       if (extra && extra[0])
-       {
-               /* close the old one */
-               if (errfd >= 0)
-               {
-                       close(errfd);
-               }
-
-               /* open the new one */
-               errfd = open(extra, O_RDONLY);
-               offset = 0L;
-               endline = nlines;
-       }
-       else if (errfd < 0)
-       {
-               /* open the default file */
-               errfd = open(ERRLIST, O_RDONLY);
-               offset = 0L;
-               endline = nlines;
-       }
-
-       /* do we have an errlist file now? */
-       if (errfd < 0)
-       {
-               msg("There is no errlist file");
-               beep();
-               return;
-       }
-
-       /* find the next error message in the file */
-       do
-       {
-               /* read the next line from the errlist */
-               lseek(errfd, offset, 0);
-               if (tread(errfd, tmpblk.c, (unsigned)BLKSIZE) <= 0)
-               {
-                       msg("No more errors");
-                       beep();
-                       close(errfd);
-                       errfd = -2;
-                       return;
-               }
-               for (i = 0; tmpblk.c[i] != '\n'; i++)
-               {
-               }
-               tmpblk.c[i++] = 0;
-
-               /* look for an error message in the line */
-               errmsg = parse_errmsg(tmpblk.c);
-               if (!errmsg)
-               {
-                       offset += i;
-               }
-
-       } while (!errmsg);
-
-       /* switch to the file containing the error, if this isn't it */
-       if (strcmp(origname, errfile))
-       {
-               if (!tmpabort(bang))
-               {
-                       msg("Use :er! to abort changes, or :w to save changes");
-                       beep();
-                       return;
-               }
-               tmpstart(errfile);
-               endline = nlines;
-       }
-       else if (endline == 0L)
-       {
-               endline = nlines;
-       }
-
-       /* go to the line where the error was detected */
-       cursor = MARK_AT_LINE(errline + (nlines - endline));
-       if (cursor > MARK_LAST)
-       {
-               cursor = MARK_LAST;
-       }
-       if (mode == MODE_VI)
-       {
-               redraw(cursor, FALSE);
-       }
-
-       /* display the error message */
-#ifdef CRUNCH
-       msg("%.70s", errmsg);
-#else
-       if (nlines > endline)
-       {
-               msg("line %ld(+%ld): %.60s", errline, nlines - endline, errmsg);
-       }
-       else if (nlines < endline)
-       {
-               msg("line %ld(-%ld): %.60s", errline, endline - nlines, errmsg);
-       }
-       else
-       {
-               msg("line %ld: %.65s", errline, errmsg);
-       }
-#endif
-
-       /* remember where the NEXT error line will start */
-       offset += i;
-}
-
-
-/*ARGSUSED*/
-void cmd_make(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       BLK     buf;
-
-       /* if the file hasn't been saved, then complain unless ! */
-       if (tstflag(file, MODIFIED) && !bang)
-       {
-               msg("\"%s\" not saved yet", origname);
-               return;
-       }
-
-       /* build the command */
-       sprintf(buf.c, "%s %s %s%s", (cmd == CMD_CC ? o_cc : o_make), extra, REDIRECT, ERRLIST);
-       qaddstr(buf.c);
-       addch('\n');
-
-       /* close the old errlist file, if any */
-       if (errfd >= 0)
-       {
-               close(errfd);
-               errfd = -3;
-       }
-
-       /* run the command, with curses temporarily disabled */
-       suspend_curses();
-       system(buf.c);
-       resume_curses(mode == MODE_EX);
-       if (mode == MODE_COLON)
-               mode = MODE_VI;
-
-       /* run the "errlist" command */
-       cmd_errlist(MARK_UNSET, MARK_UNSET, cmd, bang, ERRLIST);
-}
-#endif
-
-
-
-#ifndef NO_COLOR
-
-/* figure out the number of text colors we use with this configuration */
-# ifndef NO_POPUP
-#  ifndef NO_VISIBLE
-#   define NCOLORS 7
-#  else
-#   define NCOLORS 6
-#  endif
-# else
-#  ifndef NO_VISIBLE
-#   define NCOLORS 6
-#  else
-#   define NCOLORS 5
-#  endif
-# endif
-
-/* the attribute bytes used in each of "when"s */
-static char bytes[NCOLORS];
-
-static struct
-{
-       char    *word;  /* a legal word */
-       int     type;   /* what type of word this is */
-       int     val;    /* some other value */
-}
-       words[] =
-{
-       {"normal",      1,      A_NORMAL},      /* all "when" names must come */
-       {"standout",    1,      A_STANDOUT},    /* at the top of the list.    */
-       {"bold",        1,      A_BOLD},        /* The first 3 must be normal,*/
-       {"underlined",  1,      A_UNDERLINE},   /* standout, and bold; the    */
-       {"italics",     1,      A_ALTCHARSET},  /* remaining names follow.    */
-#ifndef NO_POPUP
-       {"popup",       1,      A_POPUP},
-#endif
-#ifndef NO_VISIBLE
-       {"visible",     1,      A_VISIBLE},
-#endif
-
-       {"black",       3,      0x00},          /* The color names start right*/
-       {"blue",        3,      0x01},          /* after the "when" names.    */
-       {"green",       3,      0x02},
-       {"cyan",        3,      0x03},
-       {"red",         3,      0x04},
-       {"magenta",     3,      0x05},
-       {"brown",       3,      0x06},
-       {"white",       3,      0x07},
-       {"yellow",      3,      0x0E}, /* bright brown */
-       {"gray",        3,      0x08}, /* bright black?  of course! */
-       {"grey",        3,      0x08},
-
-       {"bright",      2,      0x08},
-       {"light",       2,      0x08},
-       {"blinking",    2,      0x80},
-       {"on",          0,      0},
-       {"n",           1,      A_NORMAL},
-       {"s",           1,      A_STANDOUT},
-       {"b",           1,      A_BOLD},
-       {"u",           1,      A_UNDERLINE},
-       {"i",           1,      A_ALTCHARSET},
-#ifndef NO_POPUP
-       {"p",           1,      A_POPUP},
-       {"menu",        1,      A_POPUP},
-#endif
-#ifndef NO_VISIBLE
-       {"v",           1,      A_VISIBLE},
-#endif
-       {(char *)0,     0,      0}
-};
-
-/*ARGSUSED*/
-void cmd_color(frommark, tomark, cmd, bang, extra)
-       MARK    frommark, tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       int     attrbyte;
-       int     cmode;
-       int     nowbg;  /* BOOLEAN: is the next color background? */
-
-       REG char *scan;
-       REG     i;
-
-
-#ifndef CRUNCH
-       /* if no args are given, then report the current colors */
-       if (!*extra)
-       {
-               /* if no colors are set, then say so */
-               if (!bytes[0])
-               {
-                       msg("no colors have been set");
-                       return;
-               }
-
-               /* report all five color combinations */
-               for (i = 0; i < NCOLORS; i++)
-               {
-                       qaddstr("color ");
-                       qaddstr(words[i].word);
-                       qaddch(' ');
-                       if (bytes[i] & 0x80)
-                               qaddstr("blinking ");
-                       switch (bytes[i] & 0xf)
-                       {
-                         case 0x08:    qaddstr("gray");        break;
-                         case 0x0e:    qaddstr("yellow");      break;
-                         case 0x0f:    qaddstr("bright white");break;
-                         default:
-                               if (bytes[i] & 0x08)
-                                       qaddstr("light ");
-                               qaddstr(words[(bytes[i] & 0x07) + NCOLORS].word);
-                       }
-                       qaddstr(" on ");
-                       qaddstr(words[((bytes[i] >> 4) & 0x07) + NCOLORS].word);
-                       addch('\n');
-                       exrefresh();
-               }
-               return;
-       }
-#endif
-
-       /* The default background color is the same as "normal" chars.
-        * There is no default foreground color.
-        */
-       cmode = A_NORMAL;
-       attrbyte = bytes[0] & 0x70;
-       nowbg = FALSE;
-
-       /* parse each word in the "extra" text */
-       for (scan = extra; *extra; extra = scan)
-       {
-               /* locate the end of the word */
-               while (*scan && *scan != ' ')
-               {
-                       scan++;
-               }
-
-               /* skip whitespace at the end of the word */
-               while(*scan == ' ')
-               {
-                       *scan++ = '\0';
-               }
-
-               /* lookup the word */
-               for (i = 0; words[i].word && strcmp(words[i].word, extra); i++)
-               {
-               }
-
-               /* if not a word, then complain */
-               if (!words[i].word)
-               {
-                       msg("Invalid color name: %s", extra);
-                       return;
-               }
-
-               /* process the word */
-               switch (words[i].type)
-               {
-                 case 1:
-                       cmode = words[i].val;
-                       break;
-
-                 case 2:
-                       attrbyte |= words[i].val;
-                       break;
-
-                 case 3:
-                       if (nowbg)
-                               attrbyte = ((attrbyte & ~0x70) | ((words[i].val & 0x07) << 4));
-                       else
-                               attrbyte |= words[i].val;
-                       nowbg = TRUE;
-                       break;
-               }
-       }
-
-       /* if nowbg isn't set now, then we were never given a foreground color */
-       if (!nowbg)
-       {
-               msg("usage: color [when] [\"bright\"] [\"blinking\"] foreground [background]");
-               return;
-       }
-
-       /* the first ":color" command MUST define the "normal" colors */
-       if (!bytes[0])
-               cmode = A_NORMAL;
-
-       /* we should now have a cmode and an attribute byte... */
-
-       /* set the color */
-       setcolor(cmode, attrbyte);
-
-       /* remember what we just did */
-       bytes[cmode] = attrbyte;
-
-       /* if the other colors haven't been set yet, then set them to defaults */
-       if (!bytes[1])
-       {
-               /* standout is the opposite of normal */
-               bytes[1] = ((attrbyte << 4) & 0x70 | (attrbyte >> 4) & 0x07);
-               setcolor(A_STANDOUT, bytes[1]);
-
-               /* if "normal" isn't bright, then bold defaults to normal+bright
-                * else bold defaults to bright white.
-                */
-               bytes[2] = attrbyte | ((attrbyte & 0x08) ? 0x0f : 0x08);
-               setcolor(A_BOLD, bytes[2]);
-
-               /* all others default to the "standout" colors, without blinking */
-               for (i = 3; i < NCOLORS; i++)
-               {
-                       bytes[i] = (bytes[1] & 0x7f);
-                       setcolor(words[i].val, bytes[i]);
-               }
-       }
-
-       /* force a redraw, so we see the new colors */
-       redraw(MARK_UNSET, FALSE);
-}
-
-
-
-void savecolor(fd)
-       int     fd;     /* file descriptor to write colors to */
-{
-       int     i;
-       char    buf[80];
-
-       /* if no colors are set, then return */
-       if (!bytes[0])
-       {
-               return;
-       }
-
-       /* save all five color combinations */
-       for (i = 0; i < NCOLORS; i++)
-       {
-               strcpy(buf, "color ");
-               strcat(buf, words[i].word);
-               strcat(buf, " ");
-               if (bytes[i] & 0x80)
-                       strcat(buf, "blinking ");
-               switch (bytes[i] & 0xf)
-               {
-                 case 0x08:    strcat(buf, "gray");    break;
-                 case 0x0e:    strcat(buf, "yellow");  break;
-                 case 0x0f:    strcat(buf, "bright white");break;
-                 default:
-                       if (bytes[i] & 0x08)
-                               strcat(buf, "light ");
-                       strcat(buf, words[(bytes[i] & 0x07) + NCOLORS].word);
-               }
-               strcat(buf, " on ");
-               strcat(buf, words[((bytes[i] >> 4) & 0x07) + NCOLORS].word);
-               strcat(buf, "\n");
-               twrite(fd, buf, (unsigned)strlen(buf));
-       }
-}
-#endif
-
-#ifdef SIGTSTP
-/* temporarily suspend elvis */
-/*ARGSUSED*/
-void cmd_suspend(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       void    (*func)();      /* stores the previous setting of SIGTSTP */
-
-#if ANY_UNIX
-       /* the Bourne shell can't handle ^Z */
-       if (!strcmp(o_shell, "/bin/sh"))
-       {
-               msg("The /bin/sh shell doesn't support ^Z");
-               return;
-       }
-#endif
-
-       move(LINES - 1, 0);
-       if (tstflag(file, MODIFIED))
-       {
-               addstr("Warning: \"");
-               addstr(origname);
-               addstr("\" modified but not yet saved");
-               clrtoeol();
-       }
-       refresh();
-       suspend_curses();
-       func = signal(SIGTSTP, SIG_DFL);
-       kill (0, SIGTSTP);
-
-       /* the process stops and resumes here */
-
-       signal(SIGTSTP, func);
-       resume_curses(TRUE);
-       if (mode == MODE_VI || mode == MODE_COLON)
-               redraw(MARK_UNSET, FALSE);
-       else
-               refresh ();
-}
-#endif
diff --git a/commands/elvis/cmd2.c b/commands/elvis/cmd2.c
deleted file mode 100644 (file)
index 5d88acc..0000000
+++ /dev/null
@@ -1,942 +0,0 @@
-/* cmd2.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains some of the commands - mostly ones that change text */
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-#include "regexp.h"
-#if TOS
-# include <stat.h>
-#else
-# if OSK
-#  include "osk.h"
-# else
-#  if AMIGA
-#   include "amistat.h"
-#  else
-#   include <sys/stat.h>
-#  endif
-# endif
-#endif
-
-
-/*ARGSUSED*/
-void cmd_substitute(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra; /* rest of the command line */
-{
-       char    *line;  /* a line from the file */
-       regexp  *re;    /* the compiled search expression */
-       char    *subst; /* the substitution string */
-       char    *opt;   /* substitution options */
-       long    l;      /* a line number */
-       char    *s, *d; /* used during subtitutions */
-       char    *conf;  /* used during confirmation */
-       long    chline; /* # of lines changed */
-       long    chsub;  /* # of substitutions made */
-       static  optp;   /* boolean option: print when done? */
-       static  optg;   /* boolean option: substitute globally in line? */
-       static  optc;   /* boolean option: confirm before subst? */
-#ifndef CRUNCH
-       long    oldnlines;
-#endif
-
-
-       /* for now, assume this will fail */
-       rptlines = -1L;
-
-       if (cmd == CMD_SUBAGAIN)
-       {
-#ifndef NO_MAGIC
-               if (*o_magic)
-                       subst = "~";
-               else
-#endif
-               subst = "\\~";
-               re = regcomp("");
-
-               /* if visual "&", then turn off the "p" and "c" options */
-               if (bang)
-               {
-                       optp = optc = FALSE;
-               }
-       }
-       else /* CMD_SUBSTITUTE */
-       {
-               /* make sure we got a search pattern */
-               if (*extra != '/' && *extra != '?')
-               {
-                       msg("Usage: s/regular expression/new text/");
-                       return;
-               }
-
-               /* parse & compile the search pattern */
-               subst = parseptrn(extra);
-               re = regcomp(extra + 1);
-       }
-
-       /* abort if RE error -- error message already given by regcomp() */
-       if (!re)
-       {
-               return;
-       }
-
-       if (cmd == CMD_SUBSTITUTE)
-       {
-               /* parse the substitution string & find the option string */
-               for (opt = subst; *opt && *opt != *extra; opt++)
-               {
-                       if (*opt == '\\' && opt[1])
-                       {
-                               opt++;
-                       }
-               }
-               if (*opt)
-               {
-                       *opt++ = '\0';
-               }
-
-               /* analyse the option string */
-               if (!*o_edcompatible)
-               {
-                       optp = optg = optc = FALSE;
-               }
-               while (*opt)
-               {
-                       switch (*opt++)
-                       {
-                         case 'p':     optp = !optp;   break;
-                         case 'g':     optg = !optg;   break;
-                         case 'c':     optc = !optc;   break;
-                         case ' ':
-                         case '\t':                    break;
-                         default:
-                               msg("Subst options are p, c, and g -- not %c", opt[-1]);
-                               return;
-                       }
-               }
-       }
-
-       /* if "c" or "p" flag was given, and we're in visual mode, then NEWLINE */
-       if ((optc || optp) && mode == MODE_VI)
-       {
-               addch('\n');
-               exrefresh();
-       }
-
-       ChangeText
-       {
-               /* reset the change counters */
-               chline = chsub = 0L;
-
-               /* for each selected line */
-               for (l = markline(frommark); l <= markline(tomark); l++)
-               {
-                       /* fetch the line */
-                       line = fetchline(l);
-
-                       /* if it contains the search pattern... */
-                       if (regexec(re, line, TRUE))
-                       {
-                               /* increment the line change counter */
-                               chline++;
-
-                               /* initialize the pointers */
-                               s = line;
-                               d = tmpblk.c;
-
-                               /* do once or globally ... */
-                               do
-                               {
-#ifndef CRUNCH
-                                       /* confirm, if necessary */
-                                       if (optc)
-                                       {
-                                               for (conf = line; conf < re->startp[0]; conf++)
-                                                       addch(*conf);
-                                               standout();
-                                               for ( ; conf < re->endp[0]; conf++)
-                                                       addch(*conf);
-                                               standend();
-                                               for (; *conf; conf++)
-                                                       addch(*conf);
-                                               addch('\n');
-                                               exrefresh();
-                                               if (getkey(0) != 'y')
-                                               {
-                                                       /* copy accross the original chars */
-                                                       while (s < re->endp[0])
-                                                               *d++ = *s++;
-
-                                                       /* skip to next match on this line, if any */
-                                                       goto Continue;
-                                               }
-                                       }
-#endif /* not CRUNCH */
-
-                                       /* increment the substitution change counter */
-                                       chsub++;
-
-                                       /* copy stuff from before the match */
-                                       while (s < re->startp[0])
-                                       {
-                                               *d++ = *s++;
-                                       }
-
-                                       /* substitute for the matched part */
-                                       regsub(re, subst, d);
-                                       s = re->endp[0];
-                                       d += strlen(d);
-
-Continue:
-                                       /* if this regexp could conceivably match
-                                        * a zero-length string, then require at
-                                        * least 1 unmatched character between
-                                        * matches.
-                                        */
-                                       if (re->minlen == 0)
-                                       {
-                                               if (!*s)
-                                                       break;
-                                               *d++ = *s++;
-                                       }
-
-                               } while (optg && regexec(re, s, FALSE));
-
-                               /* copy stuff from after the match */
-                               while (*d++ = *s++)     /* yes, ASSIGNMENT! */
-                               {
-                               }
-
-#ifndef CRUNCH
-                               /* NOTE: since the substitution text is allowed to have ^Ms which are
-                                * translated into newlines, it is possible that the number of lines
-                                * in the file will increase after each line has been substituted.
-                                * we need to adjust for this.
-                                */
-                               oldnlines = nlines;
-#endif
-
-                               /* replace the old version of the line with the new */
-                               d[-1] = '\n';
-                               d[0] = '\0';
-                               change(MARK_AT_LINE(l), MARK_AT_LINE(l + 1), tmpblk.c);
-
-#ifndef CRUNCH
-                               l += nlines - oldnlines;
-                               tomark += MARK_AT_LINE(nlines - oldnlines);
-#endif
-
-                               /* if supposed to print it, do so */
-                               if (optp)
-                               {
-                                       addstr(tmpblk.c);
-                                       exrefresh();
-                               }
-
-                               /* move the cursor to that line */
-                               cursor = MARK_AT_LINE(l);
-                       }
-               }
-       }
-
-       /* free the regexp */
-       free(re);
-
-       /* if done from within a ":g" command, then finish silently */
-       if (doingglobal)
-       {
-               rptlines = chline;
-               rptlabel = "changed";
-               return;
-       }
-
-       /* Reporting */
-       if (chsub == 0)
-       {
-               msg("Substitution failed");
-       }
-       else if (chline >= *o_report)
-       {
-               msg("%ld substitutions on %ld lines", chsub, chline);
-       }
-       rptlines = 0L;
-}
-
-
-
-
-/*ARGSUSED*/
-void cmd_delete(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       MARK    curs2;  /* an altered form of the cursor */
-
-       /* choose your cut buffer */
-       if (*extra == '"')
-       {
-               extra++;
-       }
-       if (*extra)
-       {
-               cutname(*extra);
-       }
-
-       /* make sure we're talking about whole lines here */
-       frommark = frommark & ~(BLKSIZE - 1);
-       tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
-
-       /* yank the lines */
-       cut(frommark, tomark);
-
-       /* if CMD_DELETE then delete the lines */
-       if (cmd != CMD_YANK)
-       {
-               curs2 = cursor;
-               ChangeText
-               {
-                       /* delete the lines */
-                       delete(frommark, tomark);
-               }
-               if (curs2 > tomark)
-               {
-                       cursor = curs2 - tomark + frommark;
-               }
-               else if (curs2 > frommark)
-               {
-                       cursor = frommark;
-               }
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_append(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       long    l;      /* line counter */
-
-#ifndef CRUNCH
-       /* if '!' then toggle auto-indent */
-       if (bang)
-       {
-               *o_autoindent = !*o_autoindent;
-       }
-#endif
-
-       ChangeText
-       {
-               /* if we're doing a change, delete the old version */
-               if (cmd == CMD_CHANGE)
-               {
-                       /* delete 'em */
-                       cmd_delete(frommark, tomark, cmd, bang, extra);
-               }
-
-               /* new lines start at the frommark line, or after it */
-               l = markline(frommark);
-               if (cmd == CMD_APPEND)
-               {
-                       l++;
-               }
-
-               /* get lines until no more lines, or "." line, and insert them */
-               while (vgets('\0', tmpblk.c, BLKSIZE) >= 0)
-               {
-                       addch('\n');
-                       if (!strcmp(tmpblk.c, "."))
-                       {
-                               break;
-                       }
-
-                       strcat(tmpblk.c, "\n");
-                       add(MARK_AT_LINE(l), tmpblk.c);
-                       l++;
-               }
-       }
-
-       /* on the odd chance that we're calling this from vi mode ... */
-       redraw(MARK_UNSET, FALSE);
-}
-
-
-/*ARGSUSED*/
-void cmd_put(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       /* choose your cut buffer */
-       if (*extra == '"')
-       {
-               extra++;
-       }
-       if (*extra)
-       {
-               cutname(*extra);
-       }
-
-       /* paste it */
-       ChangeText
-       {
-               cursor = paste(frommark, TRUE, FALSE);
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_join(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       long    l;
-       char    *scan;
-       int     len;    /* length of the new line */
-
-       /* if only one line is specified, assume the following one joins too */
-       if (markline(frommark) == nlines)
-       {
-               msg("Nothing to join with this line");
-               return;
-       }
-       if (markline(frommark) == markline(tomark))
-       {
-               tomark += BLKSIZE;
-       }
-
-       /* get the first line */
-       l = markline(frommark);
-       strcpy(tmpblk.c, fetchline(l));
-       len = strlen(tmpblk.c);
-
-       /* build the longer line */
-       while (++l <= markline(tomark))
-       {
-               /* get the next line */
-               scan = fetchline(l);
-
-               /* remove any leading whitespace */
-               while (*scan == '\t' || *scan == ' ')
-               {
-                       scan++;
-               }
-
-               /* see if the line will fit */
-               if (strlen(scan) + len + 3 > BLKSIZE)
-               {
-                       msg("Can't join -- the resulting line would be too long");
-                       return;
-               }
-
-               /* catenate it, with a space (or two) in between */
-               if (!bang)
-               {
-                       if (len >= 1)
-                       {
-                               if (tmpblk.c[len - 1] == '.'
-                                || tmpblk.c[len - 1] == '?'
-                                || tmpblk.c[len - 1] == '!')
-                               {
-                                        tmpblk.c[len++] = ' ';
-                               }
-                               tmpblk.c[len++] = ' ';
-                       }
-               }
-               strcpy(tmpblk.c + len, scan);
-               len += strlen(scan);
-       }
-       tmpblk.c[len++] = '\n';
-       tmpblk.c[len] = '\0';
-
-       /* make the change */
-       ChangeText
-       {
-               frommark &= ~(BLKSIZE - 1);
-               tomark &= ~(BLKSIZE - 1);
-               tomark += BLKSIZE;
-               change(frommark, tomark, tmpblk.c);
-       }
-
-       /* Reporting... */
-       rptlines = markline(tomark) - markline(frommark) - 1L;
-       rptlabel = "joined";
-}
-
-
-
-/*ARGSUSED*/
-void cmd_shift(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       long    l;      /* line number counter */
-       int     oldidx; /* number of chars previously used for indent */
-       int     newidx; /* number of chars in the new indent string */
-       int     oldcol; /* previous indent amount */
-       int     newcol; /* new indent amount */
-       char    *text;  /* pointer to the old line's text */
-
-       ChangeText
-       {
-               /* for each line to shift... */
-               for (l = markline(frommark); l <= markline(tomark); l++)
-               {
-                       /* get the line - ignore empty lines unless ! mode */
-                       text = fetchline(l);
-                       if (!*text && !bang)
-                               continue;
-
-                       /* calc oldidx and oldcol */
-                       for (oldidx = 0, oldcol = 0;
-                            text[oldidx] == ' ' || text[oldidx] == '\t';
-                            oldidx++)
-                       {
-                               if (text[oldidx] == ' ')
-                               {
-                                       oldcol += 1;
-                               }
-                               else
-                               {
-                                       oldcol += *o_tabstop - (oldcol % *o_tabstop);
-                               }
-                       }
-
-                       /* calc newcol */
-                       if (cmd == CMD_SHIFTR)
-                       {
-                               newcol = oldcol + (*o_shiftwidth & 0xff);
-                       }
-                       else
-                       {
-                               newcol = oldcol - (*o_shiftwidth & 0xff);
-                               if (newcol < 0)
-                                       newcol = 0;
-                       }
-
-                       /* if no change, then skip to next line */
-                       if (oldcol == newcol)
-                               continue;
-
-                       /* build a new indent string */
-                       newidx = 0;
-                       if (*o_autotab)
-                       {
-                               while (newcol >= *o_tabstop)
-                               {
-                                       tmpblk.c[newidx++] = '\t';
-                                       newcol -= *o_tabstop;
-                               }
-                       }
-                       while (newcol > 0)
-                       {
-                               tmpblk.c[newidx++] = ' ';
-                               newcol--;
-                       }
-                       tmpblk.c[newidx] = '\0';
-
-                       /* change the old indent string into the new */
-                       change(MARK_AT_LINE(l), MARK_AT_LINE(l) + oldidx, tmpblk.c);
-               }
-       }
-
-       /* Reporting... */
-       rptlines = markline(tomark) - markline(frommark) + 1L;
-       if (cmd == CMD_SHIFTR)
-       {
-               rptlabel = ">ed";
-       }
-       else
-       {
-               rptlabel = "<ed";
-       }
-}
-
-
-/*ARGSUSED*/
-void cmd_read(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       int     fd, rc; /* used while reading from the file */
-       char    *scan;  /* used for finding NUL characters */
-       int     hadnul; /* boolean: any NULs found? */
-       int     addnl;  /* boolean: forced to add newlines? */
-       int     len;    /* number of chars in current line */
-       long    lines;  /* number of lines in current block */
-       struct stat statb;
-
-       /* special case: if ":r !cmd" then let the filter() function do it */
-       if (extra[0] == '!')
-       {
-               filter(frommark, MARK_UNSET, extra + 1, TRUE);
-               return;
-       }
-
-       /* open the file */
-       fd = open(extra, O_RDONLY);
-       if (fd < 0)
-       {
-               msg("Can't open \"%s\"", extra);
-               return;
-       }
-
-#ifndef CRUNCH
-       if (stat(extra, &statb) < 0)
-       {
-               msg("Can't stat \"%s\"", extra);
-       }
-# if TOS
-       if (statb.st_mode & S_IJDIR)
-# else
-#  if OSK
-       if (statb.st_mode & S_IFDIR)
-#  else
-       if ((statb.st_mode & S_IFMT) != S_IFREG)
-#  endif
-# endif
-       {
-               msg("\"%s\" is not a regular file", extra);
-               return;
-       }
-#endif /* not CRUNCH */
-
-       /* get blocks from the file, and add them */
-       ChangeText
-       {
-               /* insertion starts at the line following frommark */
-               tomark = frommark = (frommark | (BLKSIZE - 1L)) + 1L;
-               len = 0;
-               hadnul = addnl = FALSE;
-
-               /* add an extra newline, so partial lines at the end of
-                * the file don't trip us up
-                */
-               add(tomark, "\n");
-
-               /* for each chunk of text... */
-               while ((rc = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
-               {
-                       /* count newlines, convert NULs, etc. ... */
-                       for (lines = 0, scan = tmpblk.c; rc > 0; rc--, scan++)
-                       {
-                               /* break up long lines */
-                               if (*scan != '\n' && len + 2 > BLKSIZE)
-                               {
-                                       *scan = '\n';
-                                       addnl = TRUE;
-                               }
-
-                               /* protect against NUL chars in file */
-                               if (!*scan)
-                               {
-                                       *scan = 0x80;
-                                       hadnul = TRUE;
-                               }
-
-                               /* starting a new line? */
-                               if (*scan == '\n')
-                               {
-                                       /* reset length at newline */
-                                       len = 0;
-                                       lines++;
-                               }
-                               else
-                               {
-                                       len++;
-                               }
-                       }
-
-                       /* add the text */
-                       *scan = '\0';
-                       add(tomark, tmpblk.c);
-                       tomark += MARK_AT_LINE(lines) + len - markidx(tomark);
-               }
-
-               /* if partial last line, then retain that first newline */
-               if (len > 0)
-               {
-                       msg("Last line had no newline");
-                       tomark += BLKSIZE; /* <- for the rptlines calc */
-               }
-               else /* delete that first newline */
-               {
-                       delete(tomark, (tomark | (BLKSIZE - 1L)) + 1L);
-               }
-       }
-
-       /* close the file */
-       close(fd);
-
-       /* Reporting... */
-       rptlines = markline(tomark) - markline(frommark);
-       rptlabel = "read";
-       if (mode == MODE_EX)
-       {
-               cursor = (tomark & ~BLKSIZE) - BLKSIZE;
-       }
-       else
-       {
-               cursor = frommark;
-       }
-
-       if (addnl)
-               msg("Newlines were added to break up long lines");
-       if (hadnul)
-               msg("NULs were converted to 0x80");
-}
-
-
-
-/*ARGSUSED*/
-void cmd_undo(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       undo();
-}
-
-
-/* print the selected lines */
-/*ARGSUSED*/
-void cmd_print(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       REG char        *scan;
-       REG long        l;
-       REG int         col;
-
-       for (l = markline(frommark); l <= markline(tomark); l++)
-       {
-               /* display a line number, if CMD_NUMBER */
-               if (cmd == CMD_NUMBER)
-               {
-                       sprintf(tmpblk.c, "%6ld  ", l);
-                       qaddstr(tmpblk.c);
-                       col = 8;
-               }
-               else
-               {
-                       col = 0;
-               }
-
-               /* get the next line & display it */
-               for (scan = fetchline(l); *scan; scan++)
-               {
-                       /* expand tabs to the proper width */
-                       if (*scan == '\t' && cmd != CMD_LIST)
-                       {
-                               do
-                               {
-                                       qaddch(' ');
-                                       col++;
-                               } while (col % *o_tabstop != 0);
-                       }
-                       else if (*scan > 0 && *scan < ' ' || *scan == '\177')
-                       {
-                               qaddch('^');
-                               qaddch(*scan ^ 0x40);
-                               col += 2;
-                       }
-                       else if ((*scan & 0x80) && cmd == CMD_LIST)
-                       {
-                               sprintf(tmpblk.c, "\\%03o", UCHAR(*scan));
-                               qaddstr(tmpblk.c);
-                               col += 4;
-                       }
-                       else
-                       {
-                               qaddch(*scan);
-                               col++;
-                       }
-
-                       /* wrap at the edge of the screen */
-                       if (!has_AM && col >= COLS)
-                       {
-                               addch('\n');
-                               col -= COLS;
-                       }
-               }
-               if (cmd == CMD_LIST)
-               {
-                       qaddch('$');
-               }
-               addch('\n');
-               exrefresh();
-       }
-}
-
-
-/* move or copy selected lines */
-/*ARGSUSED*/
-void cmd_move(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       MARK    destmark;
-
-       /* parse the destination linespec.  No defaults.  Line 0 is okay */
-       destmark = cursor;
-       if (!strcmp(extra, "0"))
-       {
-               destmark = 0L;
-       }
-       else if (linespec(extra, &destmark) == extra || !destmark)
-       {
-               msg("invalid destination address");
-               return;
-       }
-
-       /* flesh the marks out to encompass whole lines */
-       frommark &= ~(BLKSIZE - 1);
-       tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
-       destmark = (destmark & ~(BLKSIZE - 1)) + BLKSIZE;
-
-       /* make sure the destination is valid */
-       if (cmd == CMD_MOVE && destmark >= frommark && destmark < tomark)
-       {
-               msg("invalid destination address");
-       }
-
-       /* Do it */
-       ChangeText
-       {
-               /* save the text to a cut buffer */
-               cutname('\0');
-               cut(frommark, tomark);
-
-               /* if we're not copying, delete the old text & adjust destmark */
-               if (cmd != CMD_COPY)
-               {
-                       delete(frommark, tomark);
-                       if (destmark >= frommark)
-                       {
-                               destmark -= (tomark - frommark);
-                       }
-               }
-
-               /* add the new text */
-               paste(destmark, FALSE, FALSE);
-       }
-
-       /* move the cursor to the last line of the moved text */
-       cursor = destmark + (tomark - frommark) - BLKSIZE;
-       if (cursor < MARK_FIRST || cursor >= MARK_LAST + BLKSIZE)
-       {
-               cursor = MARK_LAST;
-       }
-
-       /* Reporting... */
-       rptlabel = ( (cmd == CMD_COPY) ? "copied" : "moved" );
-}
-
-
-
-/* execute EX commands from a file */
-/*ARGSUSED*/
-void cmd_source(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       /* must have a filename */
-       if (!*extra)
-       {
-               msg("\"source\" requires a filename");
-               return;
-       }
-
-       doexrc(extra);
-}
-
-
-#ifndef NO_AT
-/*ARGSUSED*/
-void cmd_at(frommark, tomark, cmd, bang, extra)
-       MARK    frommark;
-       MARK    tomark;
-       CMD     cmd;
-       int     bang;
-       char    *extra;
-{
-       static  nest = FALSE;
-       int     result;
-       char    buf[MAXRCLEN];
-
-       /* don't allow nested macros */
-       if (nest)
-       {
-               msg("@ macros can't be nested");
-               return;
-       }
-       nest = TRUE;
-
-       /* require a buffer name */
-       if (*extra == '"')
-               extra++;
-       if (!*extra || !isascii(*extra) ||!islower(*extra))
-       {
-               msg("@ requires a cut buffer name (a-z)");
-       }
-
-       /* get the contents of the buffer */
-       result = cb2str(*extra, buf, (unsigned)(sizeof buf));
-       if (result <= 0)
-       {
-               msg("buffer \"%c is empty", *extra);
-       }
-       else if (result >= sizeof buf)
-       {
-               msg("buffer \"%c is too large to execute", *extra);
-       }
-       else
-       {
-               /* execute the contents of the buffer as ex commands */
-               exstring(buf, result, '\\');
-       }
-
-       nest = FALSE;
-}
-#endif
diff --git a/commands/elvis/config.h b/commands/elvis/config.h
deleted file mode 100644 (file)
index 38af7e8..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * vi configuration file
- * We try to automatically configure to various compilers and operating
- * systems. Extend the autoconf section as needed.
- */
-
-#ifndef _CONFIG_H
-# define _CONFIG_H
-
-/*************************** autoconf section ************************/
-
-/* Commodore-Amiga */
-#ifdef amiga
-# define AMIGA         1
-# define COMPILED_BY   "Manx Aztec C 5.2b"
-#endif
-
-/* standard unix V (?) */
-#ifdef M_SYSV
-# define UNIXV         1
-#endif
-
-/* xelos system, University of Ulm */
-#ifdef xelos
-# define UNIXV         1
-#endif
-
-/* BSD UNIX? */
-#ifdef bsd
-# define BSD           1
-#else
-# ifdef sun
-#  define BSD          1
-# endif
-#endif
-
-/* Microsoft C: sorry, Watcom does the same thing */
-#ifdef M_I86
-# ifndef M_SYSV
-#  define MSDOS                1
-#  ifdef IBMC2
-#   define COMPILED_BY "IBM C/2 1.00"
-#  else
-#   define MICROSOFT   1
-#   define COMPILED_BY "Microsoft C 5.10"
-#  endif
-# endif
-#endif
-
-/* Borland's Turbo C */
-#ifdef __TURBOC__
-# define MSDOS         1
-# define TURBOC                1
-# ifdef __BORLANDC__
-# define COMPILED_BY   "Borland C 2.00"
-# else
-# define COMPILED_BY   (__TURBOC__ >= 661 ? "Turbo C++ 1.00" : "Turbo C 2.00")
-# endif
-#endif
-
-/* Tos Mark-Williams */
-#ifdef M68000
-# define TOS 1
-# define COMPILED_BY   "Mark Williams C"
-#endif
-
-/* Tos GNU-C */
-#if defined(__atarist__) && defined(__gem__)
-# define TOS 1
-# define COMPILED_BY   "GNU-C " __VERSION__
-#endif
-
-/* OS9/68000 */
-#ifdef OSK
-# define COMPILED_BY   "Microware C V2.3 Edition 40"
-#endif
-
-/* DEC Rainbow, running MS-DOS (handled by earlier MS-DOS tests) */
-/* (would need -DRAINBOW in CFLAGS to compile a Rainbow-compatible .EXE) */
-
-#ifdef VMS
-# define COMPILED_BY    "VAX/VMS VAXC compiler"
-# undef VMS
-# define VMS 1
-#endif
-
-/*************************** end of autoconf section ************************/
-
-/* All undefined symbols are defined to zero here, to allow for older    */
-/* compilers which dont understand #if defined() or #if UNDEFINED_SYMBOL */
-
-/*************************** operating systems *****************************/
-#ifndef        BSD
-# define BSD   0               /* UNIX - Berkeley 4.x */
-#endif
-
-#ifndef        UNIXV
-# define UNIXV 0               /* UNIX - AT&T SYSV */
-#endif
-
-#ifndef        UNIX7
-# define UNIX7 0               /* UNIX - version 7 */
-#endif
-
-#ifndef        MSDOS
-# define MSDOS 0               /* PC           */
-#endif
-
-#ifndef        TOS
-# define TOS   0               /* Atari ST     */
-#endif
-
-#ifndef        AMIGA
-# define AMIGA 0               /* Commodore Amiga */
-#endif
-
-#ifndef OSK
-# define OSK   0               /* OS-9 / 68k */
-#endif
-
-#ifndef COHERENT
-# define COHERENT 0            /* Coherent */
-#endif
-
-#ifndef RAINBOW                        /* DEC Rainbow support, under MS-DOS */
-# define RAINBOW 0
-#endif
-
-#ifndef VMS
-# define VMS 0                  /* VAX/VMS */
-#endif
-                               /* Minix has no predefines */
-#if !BSD && !UNIXV && !UNIX7 && !MSDOS && !TOS && !AMIGA && !OSK && !COHERENT && !VMS
-# define MINIX 1
-#else
-# define MINIX 0
-#endif
-
-                               /* generic combination of Unices */
-#if UNIXV || UNIX7 || BSD || MINIX || COHERENT
-# define ANY_UNIX 1
-#else
-# define ANY_UNIX 0
-#endif
-
-/*************************** compilers **************************************/
-#ifndef        AZTEC_C
-# define AZTEC_C       0
-#endif
-
-#ifndef        MICROSOFT
-# define MICROSOFT     0
-#endif
-
-#ifndef        TURBOC
-# define TURBOC                0
-#endif
-
-/******************************* Credit ************************************/
-
-#if MSDOS
-# define CREDIT "Ported to MS-DOS by Guntram Blohm & Martin Patzel"
-# if RAINBOW
-#  define CREDIT2 "Rainbow support added by Willett Kempton"
-# endif
-#endif
-
-#if AMIGA
-# define CREDIT "Ported to AmigaDOS 2.04 by Mike Rieser & Dale Rahn"
-#endif
-
-#if TOS
-# define CREDIT "Ported to Atari/TOS by Guntram Blohm & Martin Patzel"
-#endif
-
-#if OSK
-# define CREDIT        "Ported to Microware OS9/68k by Peter Reinig"
-#endif
-
-#if COHERENT
-# define CREDIT        "Ported to Coherent by Esa Ahola"
-#endif
-
-#if VMS
-# define CREDIT "Ported to VAX/VMS by John Campbell"
-#endif
-/*************************** functions depending on OS *********************/
-
-/* There are two terminal-related functions that we need: ttyread() and
- * ttywrite().  The ttyread() function implements read-with-timeout and is
- * a true function on all systems.  The ttywrite() function is almost always
- * just a macro...
- */
-#if !TOS && !AMIGA
-# define ttywrite(buf, len)    write(1, buf, (unsigned)(len))  /* raw write */
-#endif
-
-/* The strchr() function is an official standard now, so everybody has it
- * except Unix version 7 (which is old) and BSD Unix (which is academic).
- * Those guys use something called index() to do the same thing.
- */
-#if BSD || UNIX7 || OSK
-# define strchr        index
-#endif
-extern char *strchr();
-
-/* BSD uses bcopy() instead of memcpy() */
-#if BSD
-# define memcpy(dest, src, siz)        bcopy(src, dest, siz)
-#endif
-
-/* BSD uses getwd() instead of getcwd().  The arguments are a little different,
- * but we'll ignore that and hope for the best; adding arguments to the macro
- * would mess up an "extern" declaration of the function.
- */
-#if BSD || COHERENT
-# define getcwd        getwd
-#endif
-extern char *getcwd();
-
-/* text versa binary mode for read/write */
-#if !TOS
-#define        tread(fd,buf,n)         read(fd,buf,(unsigned)(n))
-#define twrite(fd,buf,n)       write(fd,buf,(unsigned)(n))
-#endif
-
-/**************************** Compiler quirks *********************************/
-
-/* the UNIX version 7 and (some) TOS compilers, don't allow "void" */
-#if UNIX7 || TOS
-# define void int
-#endif
-
-/* as far as I know, all compilers except version 7 support unsigned char */
-/* NEWFLASH: the Minix-ST compiler has subtle problems with unsigned char */
-#if UNIX7 || MINIX
-# define UCHAR(c)      ((c) & 0xff)
-# define uchar         char
-#else
-# define UCHAR(c)      ((unsigned char)(c))
-# define uchar         unsigned char
-#endif
-
-/* Some compilers prefer to have malloc declared as returning a (void *) */
-#if BSD || AMIGA
-extern void *malloc();
-#else
-extern char *malloc();
-#endif
-
-/* everybody but Amiga wants lseek declared here */
-/* LSC: MINIX Does not want it either! */
-#if !AMIGA && !defined(__minix)
-extern long lseek();
-#endif
-
-/******************* Names of files and environment vars **********************/
-
-#if ANY_UNIX
-# ifndef TMPDIR
-#  if MINIX
-#   define TMPDIR      "/tmp"
-#  endif
-# endif
-# ifndef PRSVDIR
-#  define PRSVDIR      "/usr/preserve" /* directory where preserved file live */
-# endif
-# ifndef PRSVINDEX
-#  define PRSVINDEX    "/usr/preserve/Index" /* index of files in PRSVDIR */
-# endif
-# ifndef EXRC
-#  define EXRC         ".exrc"         /* init file in current directory */
-# endif
-# define SCRATCHOUT    "%s/soXXXXXX"   /* temp file used as input to filter */
-# ifndef SHELL
-#  define SHELL                "/bin/sh"       /* default shell */
-# endif
-# if COHERENT
-#  ifndef REDIRECT
-#   define REDIRECT    ">"             /* Coherent CC writes errors to stdout */
-#  endif
-# endif
-#endif
-
-#if AMIGA              /* Specify AMIGA environment */
-# ifndef CC_COMMAND
-#  define CC_COMMAND   "cc"            /* generic C compiler */
-# endif
-# ifndef COLON
-#  define COLON                ':'             /* Amiga files can also end in `:' */
-# endif
-# ifndef SYSEXRC
-#  define SYSEXRC      "S:" EXRC       /* name of ".exrc" file in system dir */
-# endif
-# ifndef MAXRCLEN
-#  define MAXRCLEN     2048            /* max size of a .exrc file */
-# endif
-# ifndef NBUFS
-#  define NBUFS                10              /* must be at least 3 -- more is better */
-# endif
-# ifndef NEEDSYNC
-#  define NEEDSYNC     TRUE            /* assume ":se sync" by default */
-# endif
-# ifndef PRSVDIR
-#  define PRSVDIR      "Elvis:"        /* directory where preserved file live */
-# endif
-# ifndef PRSVINDEX
-#  define PRSVINDEX    "Elvis:Index"   /* index of files in PRSVDIR */
-# endif
-# ifndef REDIRECT
-#  define REDIRECT     ">"             /* Amiga writes errors to stdout */
-# endif
-# ifndef SCRATCHIN
-#  define SCRATCHIN    "%sSIXXXXXX"
-# endif
-# ifndef SCRATCHOUT
-#  define SCRATCHOUT   "%sSOXXXXXX"
-# endif
-# ifndef SHELL
-#  define SHELL                "newshell"      /* default shell */
-# endif
-# ifndef TERMTYPE
-#  define TERMTYPE     "amiga"         /* default termtype */
-# endif
-# ifndef TMPDIR                                /* for AMIGA should end in `:' or `/' */
-#  define TMPDIR       "T:"            /* directory where temp files live */
-# endif
-# ifndef TMPNAME
-#  define TMPNAME      "%selv_%x.%x"   /* format of names for temp files */
-# endif
-#endif
-
-#if MSDOS || TOS
-/* do not change TMPNAME and SCRATCH*: they MUST begin with '%s\\'! */
-# ifndef TMPDIR
-#  define TMPDIR       "C:\\tmp"       /* directory where temp files live */
-# endif
-# ifndef PRSVDIR
-#  define PRSVDIR      "C:\\preserve"  /* directory where preserved file live */
-# endif
-# ifndef PRSVINDEX
-#  define PRSVINDEX    "C:\\preserve\\Index" /* index of files in PRSVDIR */
-# endif
-# define TMPNAME       "%s\\elv_%x.%x" /* temp file */
-# if MSDOS
-#  if MICROSOFT
-#   define CC_COMMAND  "cl -c"         /* C compiler */
-#  else
-#   if __BORLANDC__  /* Borland C */
-#    define CC_COMMAND "bcc"           /* C compiler */
-#   else
-#   if TURBOC        /* Turbo C */
-#    define CC_COMMAND "tcc"           /* C compiler */
-#   endif      /* TURBOC */
-#   endif      /* BORLANDC */
-#  endif               /* MICROSOFT */
-# endif                /* MSDOS */
-# define SCRATCHIN     "%s\\siXXXXXX"  /* DOS ONLY - output of filter program */
-# define SCRATCHOUT    "%s\\soXXXXXX"  /* temp file used as input to filter */
-# define SLASH         '\\'
-# ifndef SHELL
-#  if TOS
-#   define SHELL       "shell.ttp"     /* default shell */
-#  else
-#   define SHELL       "command.com"   /* default shell */
-#  endif
-# endif
-# define NEEDSYNC      TRUE            /* assume ":se sync" by default */
-# if TOS && __GNUC__                   /* probably on other systems, too */
-#  define REDIRECT     "2>"            /* GNUC reports on 2, others on 1 */
-#  define CC_COMMAND   "gcc -c"
-# else
-#  define REDIRECT     ">"             /* shell's redirection of stderr */
-# endif
-#endif
-
-#if VMS
-/* do not change TMPNAME, and SCRATCH*: they MUST begin with '%s\\'! */
-# ifndef TMPDIR
-#  define TMPDIR        "sys$scratch:"  /* directory where temp files live */
-# endif
-# define TMPNAME        "%selv_%x.%x;1" /* temp file */
-# define SCRATCHIN      "%ssiXXXXXX"    /* DOS ONLY - output of filter program */
-# define SCRATCHOUT     "%ssoXXXXXX"    /* temp file used as input to filter */
-# define SLASH          '\:'  /* Worry point... jdc */
-# ifndef SHELL
-#   define SHELL        ""      /* default shell */
-# endif
-# define REDIRECT       ">"             /* shell's redirection of stderr */
-# define tread(fd,buf,n)  vms_read(fd,buf,(unsigned)(n))
-# define close vms_close
-# define lseek vms_lseek
-# define unlink vms_delete
-# define delete __delete   /* local routine conflicts w/VMS rtl routine. */
-# define rpipe vms_rpipe
-# define rpclose vms_rpclose
-# define ttyread vms_ttyread
-/* There is no sync() on vms */
-# define sync()
-/* jdc -- seems VMS external symbols are case insensitive */
-# define m_fWord m_fw_ord
-# define m_bWord m_bw_ord
-# define m_eWord m_ew_ord
-# define m_Nsrch m_n_srch
-# define m_Fch   m_f_ch
-# define m_Tch   m_t_ch
-# define v_Xchar v_x_char
-/* jdc -- also, braindead vms curses always found by linker. */
-# define LINES elvis_LINES
-# define COLS  elvis_COLS
-# define curscr elvis_curscr
-# define stdscr elvis_stdscr
-# define initscr elvis_initscr
-# define endwin  elvis_endwin
-# define wrefresh elvis_wrefresh
-#endif
-
-#if OSK
-# ifndef TMPDIR
-#  define TMPDIR       "/dd/tmp"          /* directory where temp files live */
-# endif
-# ifndef PRSVDIR
-#  define PRSVDIR      "/dd/usr/preserve" /* directory where preserved file live */
-# endif
-# ifndef PRSVINDEX
-#  define PRSVINDEX    "/dd/usr/preserve/Index" /* index of files in PRSVDIR */
-# endif
-# ifndef CC_COMMAND
-#  define CC_COMMAND   "cc -r"            /* name of the compiler */
-# endif
-# ifndef EXRC
-#  define EXRC         ".exrc"            /* init file in current directory */
-# endif
-# define SCRATCHOUT    "%s/soXXXXXX"      /* temp file used as input to filter */
-# ifndef SHELL
-#  define SHELL                "shell"            /* default shell */
-# endif
-# define FILEPERMS     (S_IREAD|S_IWRITE) /* file permissions used for creat() */
-# define REDIRECT      ">>-"              /* shell's redirection of stderr */
-# define sync()                                   /* OS9 doesn't need a sync() */
-#endif
-
-#ifndef        TAGS
-# define TAGS          "tags"          /* name of the tags file */
-#endif
-
-#ifndef TMPNAME
-# define TMPNAME       "%s/elv_%x.%x"  /* format of names for temp files */
-#endif
-
-#ifndef EXINIT
-# define EXINIT                "EXINIT"        /* name of EXINIT environment variable */
-#endif
-
-#ifndef        EXRC
-# define EXRC          "elvis.rc"      /* name of ".exrc" file in current dir */
-#endif
-
-#ifndef HMEXRC
-# define HMEXRC                EXRC            /* name of ".exrc" file in home dir */
-#endif
-
-#ifndef        KEYWORDPRG
-# define KEYWORDPRG    "ref"
-#endif
-
-#ifndef        SCRATCHOUT
-# define SCRATCHIN     "%s/SIXXXXXX"
-# define SCRATCHOUT    "%s/SOXXXXXX"
-#endif
-
-#ifndef ERRLIST
-# define ERRLIST       "errlist"
-#endif
-
-#ifndef        SLASH
-# define SLASH         '/'
-#endif
-
-#ifndef SHELL
-# define SHELL         "shell"
-#endif
-
-#ifndef REG
-# define REG           register
-#endif
-
-#ifndef NEEDSYNC
-# define NEEDSYNC      FALSE
-#endif
-
-#ifndef FILEPERMS
-# define FILEPERMS     0666
-#endif
-
-#ifndef PRESERVE
-# define PRESERVE      "elvprsv"       /* name of the "preserve" program */
-#endif
-
-#ifndef CC_COMMAND
-# define CC_COMMAND    "cc -c"
-#endif
-
-#ifndef MAKE_COMMAND
-# define MAKE_COMMAND  "make"
-#endif
-
-#ifndef REDIRECT
-# define REDIRECT      "2>"
-#endif
-
-#ifndef BLKSIZE
-# ifdef CRUNCH
-#  define BLKSIZE      1024
-# else
-#  define BLKSIZE      2048
-# endif
-#endif
-
-#ifndef KEYBUFSIZE
-# define KEYBUFSIZE    1000
-#endif
-
-#endif  /* ndef _CONFIG_H */
diff --git a/commands/elvis/ctags.c b/commands/elvis/ctags.c
deleted file mode 100644 (file)
index 700138a..0000000
+++ /dev/null
@@ -1,819 +0,0 @@
-/* ctags.c */
-
-/* This is a reimplementation of the ctags(1) program.  It supports ANSI C,
- * and has heaps o' flags.  It is meant to be distributed with elvis.
- */
-
-#include <stdio.h>
-#include "config.h"
-#ifndef FALSE
-# define FALSE 0
-# define TRUE  1
-#endif
-#ifndef TAGS
-# define TAGS  "tags"
-#endif
-#ifndef REFS
-# define REFS  "refs"
-#endif
-#ifndef BLKSIZE
-# define BLKSIZE 1024
-#endif
-
-#include "ctype.c" /* yes, that really is the .c file, not the .h one. */
-
-/* -------------------------------------------------------------------------- */
-/* Some global variables */
-
-/* The following boolean variables are set according to command line flags */
-int    incl_static;    /* -s  include static tags */
-int    incl_types;     /* -t  include typedefs and structs */
-int    incl_vars;      /* -v  include variables */
-int    make_refs;      /* -r  generate a "refs" file */
-int    append_files;   /* -a  append to "tags" [and "refs"] files */
-
-/* The following are used for outputting to the "tags" and "refs" files */
-FILE   *tags;          /* used for writing to the "tags" file */
-FILE   *refs;          /* used for writing to the "refs" file */
-
-/* -------------------------------------------------------------------------- */
-/* These are used for reading a source file.  It keeps track of line numbers */
-char   *file_name;     /* name of the current file */
-FILE   *file_fp;       /* stream used for reading the file */
-long   file_lnum;      /* line number in the current file */
-long   file_seek;      /* fseek() offset to the start of current line */
-int    file_afternl;   /* boolean: was previous character a newline? */
-int    file_prevch;    /* a single character that was ungotten */
-int    file_header;    /* boolean: is the current file a header file? */
-
-/* This function opens a file, and resets the line counter.  If it fails, it
- * it will display an error message and leave the file_fp set to NULL.
- */
-void file_open(name)
-       char    *name;  /* name of file to be opened */
-{
-       /* if another file was already open, then close it */
-       if (file_fp)
-       {
-               fclose(file_fp);
-       }
-
-       /* try to open the file for reading.  The file must be opened in
-        * "binary" mode because otherwise fseek() would misbehave under DOS.
-        */
-#if MSDOS || TOS
-       file_fp = fopen(name, "rb");
-#else
-       file_fp = fopen(name, "r");
-#endif
-       if (!file_fp)
-       {
-               perror(name);
-       }
-
-       /* reset the name & line number */
-       file_name = name;
-       file_lnum = 0L;
-       file_seek = 0L;
-       file_afternl = TRUE;
-
-       /* determine whether this is a header file */
-       file_header = FALSE;
-       name += strlen(name) - 2;
-       if (name >= file_name && name[0] == '.' && (name[1] == 'h' || name[1] == 'H'))
-       {
-               file_header = TRUE;
-       }
-}
-
-/* This function reads a single character from the stream.  If the *previous*
- * character was a newline, then it also increments file_lnum and sets
- * file_offset.
- */
-int file_getc()
-{
-       int     ch;
-
-       /* if there is an ungotten character, then return it.  Don't do any
-        * other processing on it, though, because we already did that the
-        * first time it was read.
-        */
-       if (file_prevch)
-       {
-               ch = file_prevch;
-               file_prevch = 0;
-               return ch;
-       }
-
-       /* if previous character was a newline, then we're starting a line */
-       if (file_afternl)
-       {
-               file_afternl = FALSE;
-               file_seek = ftell(file_fp);
-               file_lnum++;
-       }
-
-       /* Get a character.  If no file is open, then return EOF */
-       ch = (file_fp ? getc(file_fp) : EOF);
-
-       /* if it is a newline, then remember that fact */
-       if (ch == '\n')
-       {
-               file_afternl = TRUE;
-       }
-
-       /* return the character */
-       return ch;
-}
-
-/* This function ungets a character from the current source file */
-void file_ungetc(ch)
-       int     ch;     /* character to be ungotten */
-{
-       file_prevch = ch;
-}
-
-/* This function copies the current line out some other fp.  It has no effect
- * on the file_getc() function.  During copying, any '\' characters are doubled
- * and a leading '^' or trailing '$' is also quoted.  The newline character is
- * not copied.
- *
- * This is meant to be used when generating a tag line.
- */
-void file_copyline(seek, fp)
-       long    seek;   /* where the lines starts in the source file */
-       FILE    *fp;    /* the output stream to copy it to */
-{
-       long    oldseek;/* where the file's pointer was before we messed it up */
-       char    ch;     /* a single character from the file */
-       char    next;   /* the next character from this file */
-
-       /* go to the start of the line */
-       oldseek = ftell(file_fp);
-       fseek(file_fp, seek, 0);
-
-       /* if first character is '^', then emit \^ */
-       ch = getc(file_fp);
-       if (ch == '^')
-       {
-               putc('\\', fp);
-               putc('^', fp);
-               ch = getc(file_fp);
-       }
-
-       /* write everything up to, but not including, the newline */
-       while (ch != '\n')
-       {
-               /* preread the next character from this file */
-               next = getc(file_fp);
-
-               /* if character is '\', or a terminal '$', then quote it */
-               if (ch == '\\' || (ch == '$' && next == '\n'))
-               {
-                       putc('\\', fp);
-               }
-               putc(ch, fp);
-
-               /* next character... */
-               ch = next;
-       }
-
-       /* seek back to the old position */
-       fseek(file_fp, oldseek, 0);
-}
-
-/* -------------------------------------------------------------------------- */
-/* This section handles preprocessor directives.  It strips out all of the
- * directives, and may emit a tag for #define directives.
- */
-
-int    cpp_afternl;    /* boolean: look for '#' character? */
-int    cpp_prevch;     /* an ungotten character, if any */
-int    cpp_refsok;     /* boolean: can we echo characters out to "refs"? */
-
-/* This function opens the file & resets variables */
-void cpp_open(name)
-       char    *name;  /* name of source file to be opened */
-{
-       /* use the lower-level file_open function to open the file */
-       file_open(name);
-
-       /* reset variables */
-       cpp_afternl = TRUE;
-       cpp_refsok = TRUE;
-}
-
-/* This function copies a character from the source file to the "refs" file */
-void cpp_echo(ch)
-       int     ch; /* the character to copy */
-{
-       static  wasnl;
-
-       /* echo non-EOF chars, unless not making "ref", or echo turned off */
-       if (ch != EOF && make_refs && cpp_refsok && !file_header)
-       {
-               /* try to avoid blank lines */
-               if (ch == '\n')
-               {
-                       if (wasnl)
-                       {
-                               return;
-                       }
-                       wasnl = TRUE;
-               }
-               else
-               {
-                       wasnl = FALSE;
-               }
-
-               /* add the character */
-               putc(ch, refs);
-       }
-}
-
-/* This function returns the next character which isn't part of a directive */
-int cpp_getc()
-{
-       static
-       int     ch;     /* the next input character */
-       char    *scan;
-
-       /* if we have an ungotten character, then return it */
-       if (cpp_prevch)
-       {
-               ch = cpp_prevch;
-               cpp_prevch = 0;
-               return ch;
-       }
-
-       /* Get a character from the file.  Return it if not special '#' */
-       ch = file_getc();
-       if (ch == '\n')
-       {
-               cpp_afternl = TRUE;
-               cpp_echo(ch);
-               return ch;
-       }
-       else if (ch != '#' || !cpp_afternl)
-       {
-               /* normal character.  Any non-whitespace should turn off afternl */
-               if (ch != ' ' && ch != '\t')
-               {
-                       cpp_afternl = FALSE;
-               }
-               cpp_echo(ch);
-               return ch;
-       }
-
-       /* Yikes!  We found a directive */
-
-       /* see whether this is a #define line */
-       scan = " define ";
-       while (*scan)
-       {
-               if (*scan == ' ')
-               {
-                       /* space character matches any whitespace */
-                       do
-                       {
-                               ch = file_getc();
-                       } while (ch == ' ' || ch == '\t');
-                       file_ungetc(ch);
-               }
-               else
-               {
-                       /* other characters should match exactly */
-                       ch = file_getc();
-                       if (ch != *scan)
-                       {
-                               file_ungetc(ch);
-                               break;
-                       }
-               }
-               scan++;
-       }
-
-       /* is this a #define line?  and should we generate a tag for it? */
-       if (!*scan && (file_header || incl_static))
-       {
-               /* if not a header, then this will be a static tag */
-               if (!file_header)
-               {
-                       fputs(file_name, tags);
-                       putc(':', tags);
-               }
-
-               /* output the tag name */
-               for (ch = file_getc(); isalnum(ch) || ch == '_'; ch = file_getc())
-               {
-                       putc(ch, tags);
-               }
-
-               /* output a tab, the filename, another tab, and the line number */
-               fprintf(tags, "\t%s\t%ld\n", file_name, file_lnum);
-       }
-
-       /* skip to the end of the directive -- a newline that isn't preceded
-        * by a '\' character.
-        */
-       while (ch != EOF && ch != '\n')
-       {
-               if (ch == '\\')
-               {
-                       ch = file_getc();
-               }
-               ch = file_getc();
-       }
-
-       /* return the newline that we found at the end of the directive */
-       cpp_echo(ch);
-       return ch;
-}
-
-/* This puts a character back into the input queue for the source file */
-cpp_ungetc(ch)
-       int     ch;     /* a character to be ungotten */
-{
-       cpp_prevch = ch;
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* This is the lexical analyser.  It gets characters from the preprocessor,
- * and gives tokens to the parser.  Some special codes are...
- *   (deleted)  / *...* /      (comments)
- *   (deleted) //...\n (comments)
- *   (deleted) (*      (parens used in complex declaration)
- *   (deleted) [...]   (array subscript, when ... contains no ])
- *   (deleted) struct  (intro to structure declaration)
- *   BODY      {...}   ('{' can occur anywhere, '}' only at BOW if ... has '{')
- *   ARGS      (...{   (args of function, not extern or forward)
- *   ARGS      (...);  (args of an extern/forward function declaration)
- *   COMMA     ,       (separate declarations that have same scope)
- *   SEMICOLON ;       (separate declarations that have different scope)
- *   SEMICOLON  =...;  (initializer)
- *   TYPEDEF   typedef (the "typedef" keyword)
- *   STATIC    static  (the "static" keyword)
- *   STATIC    private (the "static" keyword)
- *   STATIC    PRIVATE (the "static" keyword)
- *   NAME      [a-z]+  (really any valid name that isn't reserved word)
- */
-
-/* #define EOF -1 */
-#define DELETED          0
-#define BODY     1
-#define ARGS     2
-#define COMMA    3
-#define SEMICOLON 4
-#define TYPEDEF   5
-#define STATIC   6
-#define EXTERN   7
-#define NAME     8
-
-char   lex_name[BLKSIZE];      /* the name of a "NAME" token */
-long   lex_seek;               /* start of line that contains lex_name */
-
-lex_gettoken()
-{
-       int     ch;             /* a character from the preprocessor */
-       int     next;           /* the next character */
-       int     token;          /* the token that we'll return */
-       int     i;
-
-       /* loop until we get a token that isn't "DELETED" */
-       do
-       {
-               /* get the next character */
-               ch = cpp_getc();
-
-               /* process the character */
-               switch (ch)
-               {
-                 case ',':
-                       token = COMMA;
-                       break;
-
-                 case ';':
-                       token = SEMICOLON;
-                       break;
-
-                 case '/':
-                       /* get the next character */
-                       ch = cpp_getc();
-                       switch (ch)
-                       {
-                         case '*':     /* start of C comment */
-                               ch = cpp_getc();
-                               next = cpp_getc();
-                               while (next != EOF && (ch != '*' || next != '/'))
-                               {
-                                       ch = next;
-                                       next = cpp_getc();
-                               }
-                               break;
-
-                         case '/':     /* start of a C++ comment */
-                               do
-                               {
-                                       ch = cpp_getc();
-                               } while (ch != '\n' && ch != EOF);
-                               break;
-
-                         default:      /* some other slash */
-                               cpp_ungetc(ch);
-                       }
-                       token = DELETED;
-                       break;
-
-                 case '(':
-                       ch = cpp_getc();
-                       if (ch == '*')
-                       {
-                               token = DELETED;
-                       }
-                       else
-                       {
-                               next = cpp_getc();
-                               while (ch != '{' && ch != EOF && (ch != ')' || next != ';'))/*}*/
-                               {
-                                       ch = next;
-                                       next = cpp_getc();
-                               }
-                               if (ch == '{')/*}*/
-                               {
-                                       cpp_ungetc(ch);
-                               }
-                               else if (next == ';')
-                               {
-                                       cpp_ungetc(next);
-                               }
-                               token = ARGS;
-                       }
-                       break;
-
-                 case '{':/*}*/
-                       /* don't send the next characters to "refs" */
-                       cpp_refsok = FALSE;
-
-                       /* skip ahead to closing '}', or to embedded '{' */
-                       do
-                       {
-                               ch = cpp_getc();
-                       } while (ch != '{' && ch != '}' && ch != EOF);
-
-                       /* if has embedded '{', then skip to '}' in column 1 */
-                       if (ch == '{') /*}*/
-                       {
-                               ch = cpp_getc();
-                               next = cpp_getc();
-                               while (ch != EOF && (ch != '\n' || next != '}'))/*{*/
-                               {
-                                       ch = next;
-                                       next = cpp_getc();
-                               }
-                       }
-
-                       /* resume "refs" processing */
-                       cpp_refsok = TRUE;
-                       cpp_echo('}');
-
-                       token = BODY;
-                       break;
-
-                 case '[':
-                       /* skip to matching ']' */
-                       do
-                       {
-                               ch = cpp_getc();
-                       } while (ch != ']' && ch != EOF);
-                       token = DELETED;
-                       break;
-
-                 case '=':
-                       /* skip to next ';' */
-                       do
-                       {
-                               ch = cpp_getc();
-
-                               /* leave array initializers out of "refs" */
-                               if (ch == '{')
-                               {
-                                       cpp_refsok = FALSE;
-                               }
-                       } while (ch != ';' && ch != EOF);
-
-                       /* resume echoing to "refs" */
-                       if (!cpp_refsok)
-                       {
-                               cpp_refsok = TRUE;
-                               cpp_echo('}');
-                               cpp_echo(';');
-                       }
-                       token = SEMICOLON;
-                       break;
-
-                 case EOF:
-                       token = EOF;
-                       break;
-
-                 default:
-                       /* is this the start of a name/keyword? */
-                       if (isalpha(ch) || ch == '_')
-                       {
-                               /* collect the whole word */
-                               lex_name[0] = ch;
-                               for (i = 1, ch = cpp_getc();
-                                    i < BLKSIZE - 1 && (isalnum(ch) || ch == '_');
-                                    i++, ch = cpp_getc())
-                               {
-                                       lex_name[i] = ch;
-                               }
-                               lex_name[i] = '\0';
-                               cpp_ungetc(ch);
-
-                               /* is it a reserved word? */
-                               if (!strcmp(lex_name, "typedef"))
-                               {
-                                       token = TYPEDEF;
-                                       lex_seek = -1L;
-                               }
-                               else if (!strcmp(lex_name, "static")
-                                     || !strcmp(lex_name, "private")
-                                     || !strcmp(lex_name, "PRIVATE"))
-                               {
-                                       token = STATIC;
-                                       lex_seek = -1L;
-                               }
-                               else if (!strcmp(lex_name, "extern")
-                                     || !strcmp(lex_name, "EXTERN")
-                                     || !strcmp(lex_name, "FORWARD"))
-                               {
-                                       token = EXTERN;
-                                       lex_seek = -1L;
-                               }
-                               else
-                               {
-                                       token = NAME;
-                                       lex_seek = file_seek;
-                               }
-                       }
-                       else /* not part of a name/keyword */
-                       {
-                               token = DELETED;
-                       }
-
-               } /* end switch(ch) */
-
-       } while (token == DELETED);
-
-       return token;
-}
-
-/* -------------------------------------------------------------------------- */
-/* This is the parser.  It locates tag candidates, and then decides whether to
- * generate a tag for them.
- */
-
-/* This function generates a tag for the object in lex_name, whose tag line is
- * located at a given seek offset.
- */
-void maketag(scope, seek)
-       int     scope;  /* 0 if global, or STATIC if static */
-       long    seek;   /* the seek offset of the line */
-{
-       /* output the tagname and filename fields */
-       if (scope == EXTERN)
-       {
-               /* whoa!  we should *never* output a tag for "extern" decl */
-               return;
-       }
-       else if (scope == STATIC)
-       {
-               fprintf(tags, "%s:%s\t%s\t", file_name, lex_name, file_name);
-       }
-       else
-       {
-               fprintf(tags, "%s\t%s\t", lex_name, file_name);
-       }
-
-       /* output the target line */
-       putc('/', tags);
-       putc('^', tags);
-       file_copyline(seek, tags);
-       putc('$', tags);
-       putc('/', tags);
-       putc('\n', tags);
-}
-
-
-/* This function parses a source file, adding any tags that it finds */
-void ctags(name)
-       char    *name;  /* the name of a source file to be checked */
-{
-       int     prev;   /* the previous token from the source file */
-       int     token;  /* the current token from the source file */
-       int     scope;  /* normally 0, but could be a TYPEDEF or STATIC token */
-       int     gotname;/* boolean: does lex_name contain a tag candidate? */
-       long    tagseek;/* start of line that contains lex_name */
-
-       /* open the file */
-       cpp_open(name);
-
-       /* reset */
-       scope = 0;
-       gotname = FALSE;
-       token = SEMICOLON;
-
-       /* parse until the end of the file */
-       while (prev = token, (token = lex_gettoken()) != EOF)
-       {
-               /* scope keyword? */
-               if (token == TYPEDEF || token == STATIC || token == EXTERN)
-               {
-                       scope = token;
-                       gotname = FALSE;
-                       continue;
-               }
-
-               /* name of a possible tag candidate? */
-               if (token == NAME)
-               {
-                       tagseek = file_seek;
-                       gotname = TRUE;
-                       continue;
-               }
-
-               /* if NAME BODY, without ARGS, then NAME is a struct tag */
-               if (gotname && token == BODY && prev != ARGS)
-               {
-                       gotname = FALSE;
-                       
-                       /* ignore if in typedef -- better name is coming soon */
-                       if (scope == TYPEDEF)
-                       {
-                               continue;
-                       }
-
-                       /* generate a tag, if -t and maybe -s */
-                       if (incl_types && (file_header || incl_static))
-                       {
-                               maketag(file_header ? 0 : STATIC, tagseek);
-                       }
-               }
-
-               /* If NAME ARGS BODY, then NAME is a function */
-               if (gotname && prev == ARGS && token == BODY)
-               {
-                       gotname = FALSE;
-                       
-                       /* generate a tag, maybe checking -s */
-                       if (scope != STATIC || incl_static)
-                       {
-                               maketag(scope, tagseek);
-                       }
-               }
-
-               /* If NAME SEMICOLON or NAME COMMA, then NAME is var/typedef */
-               if (gotname && (token == SEMICOLON || token == COMMA))
-               {
-                       gotname = FALSE;
-
-                       /* generate a tag, if -v/-t and maybe -s */
-                       if (scope == TYPEDEF && incl_types && (file_header || incl_static)
-                        || scope == STATIC && incl_vars && incl_static
-                        || incl_vars)
-                       {
-                               /* a TYPEDEF outside of a header is STATIC */
-                               if (scope == TYPEDEF && !file_header)
-                               {
-                                       maketag(STATIC, tagseek);
-                               }
-                               else /* use whatever scope was declared */
-                               {
-                                       maketag(scope, tagseek);
-                               }
-                       }
-               }
-
-               /* reset after a semicolon or ARGS BODY pair */
-               if (token == SEMICOLON || (prev == ARGS && token == BODY))
-               {
-                       scope = 0;
-                       gotname = FALSE;
-               }
-       }
-
-       /* The source file will be automatically closed */
-}
-
-/* -------------------------------------------------------------------------- */
-
-void usage()
-{
-       fprintf(stderr, "usage: ctags [flags] filenames...\n");
-       fprintf(stderr, "\t-s  include static functions\n");
-       fprintf(stderr, "\t-t  include typedefs\n");
-       fprintf(stderr, "\t-v  include variable declarations\n");
-       fprintf(stderr, "\t-r  generate a \"refs\" file, too\n");
-       fprintf(stderr, "\t-a  append to \"tags\", instead of overwriting\n");
-       exit(2);
-}
-
-
-
-#if AMIGA
-# include "amiwild.c"
-#endif
-
-#if VMS
-# include "vmswild.c"
-#endif
-
-main(argc, argv)
-       int     argc;
-       char    **argv;
-{
-       int     i, j;
-
-#if MSDOS || TOS
-       char    **wildexpand();
-       argv = wildexpand(&argc, argv);
-#endif
-
-       /* build the tables used by the ctype macros */
-       _ct_init("");
-
-       /* parse the option flags */
-       for (i = 1; i < argc && argv[i][0] == '-'; i++)
-       {
-               for (j = 1; argv[i][j]; j++)
-               {
-                       switch (argv[i][j])
-                       {
-                         case 's':     incl_static = TRUE;     break;
-                         case 't':     incl_types = TRUE;      break;
-                         case 'v':     incl_vars = TRUE;       break;
-                         case 'r':     make_refs = TRUE;       break;
-                         case 'a':     append_files = TRUE;    break;
-                         default:      usage();
-                       }
-               }
-       }
-
-       /* There should always be at least one source file named in args */
-       if (i == argc)
-       {
-               usage();
-       }
-
-       /* open the "tags" and maybe "refs" files */
-       tags = fopen(TAGS, append_files ? "a" : "w");
-       if (!tags)
-       {
-               perror(TAGS);
-               exit(3);
-       }
-       if (make_refs)
-       {
-               refs = fopen(REFS, append_files ? "a" : "w");
-               if (!refs)
-               {
-                       perror(REFS);
-                       exit(4);
-               }
-       }
-
-       /* parse each source file */
-       for (; i < argc; i++)
-       {
-               ctags(argv[i]);
-       }
-
-       /* close "tags" and maybe "refs" */
-       fclose(tags);
-       if (make_refs)
-       {
-               fclose(refs);
-       }
-
-#ifdef SORT
-               /* This is a hack which will sort the tags list.   It should
-                * on UNIX and OS-9.  You may have trouble with csh.   Note
-                * that the tags list only has to be sorted if you intend to
-                * use it with the real vi;  elvis permits unsorted tags.
-                */
-# if OSK
-               system("qsort tags >-_tags; -nx; del tags; rename _tags tags");
-# else 
-               system("sort tags >_tags$$; mv _tags$$ tags");
-# endif
-#endif
-
-       exit(0);
-       /*NOTREACHED*/
-}
-
-#if MSDOS || TOS
-# define WILDCARD_NO_MAIN
-# include "wildcard.c"
-#endif
diff --git a/commands/elvis/ctype.c b/commands/elvis/ctype.c
deleted file mode 100644 (file)
index ac61183..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ctype.c */
-
-/* This file contains the tables and initialization function for elvis'
- * version of <ctype.h>.  It should be portable.
- */
-
-#include "config.h"
-#include "ctype.h"
-
-uchar  _ct_toupper[256];
-uchar  _ct_tolower[256];
-uchar  _ct_ctypes[256];
-
-/* This function initializes the tables used by the ctype macros.  It should
- * be called at the start of the program.  It can be called again anytime you
- * wish to change the non-standard "flipcase" list.  The "flipcase" list is
- * a string of characters which are taken to be lowercase/uppercase pairs.
- * If you don't want to use any special flipcase characters, then pass an
- * empty string.
- */
-void _ct_init(flipcase)
-       uchar   *flipcase;      /* list of non-standard lower/upper letter pairs */
-{
-       int     i;
-       uchar   *scan;
-
-       /* reset all of the tables */
-       for (i = 0; i < 256; i++)
-       {
-               _ct_toupper[i] = _ct_tolower[i] = i;
-               _ct_ctypes[i] = 0;
-       }
-
-       /* add the digits */
-       for (scan = (uchar *)"0123456789"; *scan; scan++)
-       {
-               _ct_ctypes[*scan] |= _CT_DIGIT | _CT_ALNUM;
-       }
-
-       /* add the whitespace */
-       for (scan = (uchar *)" \t\n\r\f"; *scan; scan++)
-       {
-               _ct_ctypes[*scan] |= _CT_SPACE;
-       }
-
-       /* add the standard ASCII letters */
-       for (scan = (uchar *)"aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; *scan; scan += 2)
-       {
-               _ct_ctypes[scan[0]] |= _CT_LOWER | _CT_ALNUM;
-               _ct_ctypes[scan[1]] |= _CT_UPPER | _CT_ALNUM;
-               _ct_toupper[scan[0]] = scan[1];
-               _ct_tolower[scan[1]] = scan[0];
-       }
-
-       /* add the flipcase letters */
-       for (scan = flipcase; scan[0] && scan[1]; scan += 2)
-       {
-               _ct_ctypes[scan[0]] |= _CT_LOWER | _CT_ALNUM;
-               _ct_ctypes[scan[1]] |= _CT_UPPER | _CT_ALNUM;
-               _ct_toupper[scan[0]] = scan[1];
-               _ct_tolower[scan[1]] = scan[0];
-       }
-
-       /* include '_' in the isalnum() list */
-       _ct_ctypes[UCHAR('_')] |= _CT_ALNUM;
-
-       /* !!! find the control characters in an ASCII-dependent way */
-       for (i = 0; i < ' '; i++)
-       {
-               _ct_ctypes[i] |= _CT_CNTRL;
-       }
-       _ct_ctypes[127] |= _CT_CNTRL;
-       _ct_ctypes[255] |= _CT_CNTRL;
-}
diff --git a/commands/elvis/ctype.h b/commands/elvis/ctype.h
deleted file mode 100644 (file)
index 1a46fd3..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* ctype.h */
-
-/* This file contains macros definitions and extern declarations for a
- * version of <ctype.h> which is aware of the o_flipcase letters used in
- * elvis.
- *
- * This file uses the "uchar" data type and "UCHAR" conversion macro which
- * are defined in "config.h".  Consequently, any file that includes this
- * header must include config.h first.
- */
-
-#ifndef _CT_UPPER
-
-#define _CT_UPPER      0x01
-#define _CT_LOWER      0x02
-#define _CT_SPACE      0x04
-#define _CT_DIGIT      0x08
-#define _CT_ALNUM      0x10
-#define _CT_CNTRL      0x20
-
-#define isalnum(c)     (_ct_ctypes[UCHAR(c)] & _CT_ALNUM)
-#define isalpha(c)     (_ct_ctypes[UCHAR(c)] & (_CT_LOWER|_CT_UPPER))
-#define isdigit(c)     (_ct_ctypes[UCHAR(c)] & _CT_DIGIT)
-#define islower(c)     (_ct_ctypes[UCHAR(c)] & _CT_LOWER)
-#define isspace(c)     (_ct_ctypes[UCHAR(c)] & _CT_SPACE)
-#define isupper(c)     (_ct_ctypes[UCHAR(c)] & _CT_UPPER)
-#define iscntrl(c)     (_ct_ctypes[UCHAR(c)] & _CT_CNTRL)
-#define ispunct(c)     (!_ct_ctypes[UCHAR(c)]) /* punct = "none of the above" */
-
-#define isascii(c)     (!((c) & 0x80))
-
-#define toupper(c)     _ct_toupper[UCHAR(c)]
-#define tolower(c)     _ct_tolower[UCHAR(c)]
-
-extern uchar   _ct_toupper[];
-extern uchar   _ct_tolower[];
-extern uchar   _ct_ctypes[];
-extern void    _ct_init(/* char *flipcase */);
-
-#endif /* ndef _CT_UPPER */
diff --git a/commands/elvis/curses.c b/commands/elvis/curses.c
deleted file mode 100644 (file)
index f8cc767..0000000
+++ /dev/null
@@ -1,925 +0,0 @@
-/* curses.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the functions & variables needed for a tiny subset of
- * curses.  The principle advantage of this version of curses is its
- * extreme speed.  Disadvantages are potentially larger code, few supported
- * functions, limited compatibility with full curses, and only stdscr.
- */
-
-#include "config.h"
-#include "vi.h"
-
-#if ANY_UNIX
-/* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
- * (KJB)
- */
-# include      <termios.h>
-# if MINIX
-#  include     <sys/ioctl.h>
-# endif
-#endif
-
-#if TOS
-# include      <osbind.h>
-#endif
-
-#if OSK
-# include      <sgstat.h>
-#endif
-
-#if VMS
-extern int VMS_read_raw;  /* Set in initscr() */
-#endif
-
-
-extern char    *getenv();
-static void     starttcap();
-
-/* variables, publicly available & used in the macros */
-char   *termtype;      /* name of terminal entry */
-short  ospeed;         /* speed of the tty, eg B2400 */
-#if OSK
-char   PC_;    /* Pad char */
-char   *BC;    /* backspace character string */
-#else
-char   PC;             /* Pad char */
-#endif
-WINDOW *stdscr;        /* pointer into kbuf[] */
-WINDOW kbuf[KBSIZ];    /* a very large output buffer */
-int    LINES;          /* :li#: number of rows */
-int    COLS;           /* :co#: number of columns */
-int    AM;             /* :am:  boolean: auto margins? */
-int    PT;             /* :pt:  boolean: physical tabs? */
-char   *VB;            /* :vb=: visible bell */
-char   *UP;            /* :up=: move cursor up */
-char   *SO = "";       /* :so=: standout start */
-char   *SE = "";       /* :se=: standout end */
-char   *US = "";       /* :us=: underline start */
-char   *UE = "";       /* :ue=: underline end */
-char   *MD = "";       /* :md=: bold start */
-char   *ME = "";       /* :me=: bold end */
-char   *AS = "";       /* :as=: alternate (italic) start */
-char   *AE = "";       /* :ae=: alternate (italic) end */
-#ifndef NO_VISIBLE
-char   *MV;            /* :mv=: "visible" selection start */
-#endif
-char   *CM;            /* :cm=: cursor movement */
-char   *CE;            /* :ce=: clear to end of line */
-char   *CD;            /* :cd=: clear to end of screen */
-char   *AL;            /* :al=: add a line */
-char   *DL;            /* :dl=: delete a line */
-#if OSK
-char   *SR_;           /* :sr=: scroll reverse */
-#else
-char   *SR;            /* :sr=: scroll reverse */
-#endif
-char   *KS = "";       /* :ks=: init string for cursor */
-char   *KE = "";       /* :ke=: restore string for cursor */
-char   *KU;            /* :ku=: key sequence sent by up arrow */
-char   *KD;            /* :kd=: key sequence sent by down arrow */
-char   *KL;            /* :kl=: key sequence sent by left arrow */
-char   *KR;            /* :kr=: key sequence sent by right arrow */
-char   *HM;            /* :HM=: key sequence sent by the <Home> key */
-char   *EN;            /* :EN=: key sequence sent by the <End> key */
-char   *PU;            /* :PU=: key sequence sent by the <PgUp> key */
-char   *PD;            /* :PD=: key sequence sent by the <PgDn> key */
-char   *KI;            /* :kI=: key sequence sent by the <Insert> key */
-#ifndef NO_FKEY
-char   *FKEY[NFKEYS];  /* :k0=: ... :k9=: sequences sent by function keys */
-#endif
-char   *IM = "";       /* :im=: insert mode start */
-char   *IC = "";       /* :ic=: insert the following character */
-char   *EI = "";       /* :ei=: insert mode end */
-char   *DC;            /* :dc=: delete a character */
-char   *TI = "";       /* :ti=: terminal init */       /* GB */
-char   *TE = "";       /* :te=: terminal exit */       /* GB */
-#ifndef NO_CURSORSHAPE
-#if 1
-char   *CQ = (char *)0;/* :cQ=: normal cursor */
-char   *CX = (char *)1;/* :cX=: cursor used for EX command/entry */
-char   *CV = (char *)2;/* :cV=: cursor used for VI command mode */
-char   *CI = (char *)3;/* :cI=: cursor used for VI input mode */
-char   *CR = (char *)4;/* :cR=: cursor used for VI replace mode */
-#else
-char   *CQ = "";       /* :cQ=: normal cursor */
-char   *CX = "";       /* :cX=: cursor used for EX command/entry */
-char   *CV = "";       /* :cV=: cursor used for VI command mode */
-char   *CI = "";       /* :cI=: cursor used for VI input mode */
-char   *CR = "";       /* :cR=: cursor used for VI replace mode */
-#endif
-#endif
-char   *aend = "";     /* end an attribute -- either UE or ME */
-char   ERASEKEY;       /* backspace key taken from ioctl structure */
-#ifndef NO_COLOR
-char   normalcolor[16];
-char   SOcolor[16];
-char   SEcolor[16];
-char   UScolor[16];
-char   UEcolor[16];
-char   MDcolor[16];
-char   MEcolor[16];
-char   AScolor[16];
-char   AEcolor[16];
-# ifndef NO_POPUP
-char   POPUPcolor[16];
-# endif
-# ifndef NO_VISIBLE
-char   VISIBLEcolor[16];
-# endif
-#endif
-
-#if ANY_UNIX
-static struct termios  oldtermio;      /* original tty mode */
-static struct termios  newtermio;      /* cbreak/noecho tty mode */
-#endif
-
-#if OSK
-static struct sgbuf    oldsgttyb;      /* orginal tty mode */
-static struct sgbuf    newsgttyb;      /* noecho tty mode */
-#endif
-
-static char    *capbuf;        /* capability string buffer */
-
-
-/* Initialize the Curses package. */
-void initscr()
-{
-       /* make sure TERM variable is set */
-       termtype = getenv("TERM");
-
-#if VMS
-       /* VMS getenv() handles TERM as a environment setting.  Foreign 
-        * terminal support can be implemented by setting the ELVIS_TERM
-        * logical or symbol to match a tinytcap entry.
-        */
-       if (!strcmp(termtype,"unknown"))
-               termtype = getenv("ELVIS_TERM");
-#endif
-#if MSDOS
-       /* For MS-DOS, if TERM is unset we can default to "pcbios", or
-        * maybe "rainbow".
-        */
-       if (!termtype)
-       {
-#ifdef RAINBOW
-               if (*(unsigned char far*)(0xffff000eL) == 6   /* Rainbow 100a */
-                || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
-               {
-                       termtype = "rainbow";
-               }
-               else
-#endif
-                       termtype = "pcbios";
-       }
-       if (!strcmp(termtype, "pcbios"))
-#else
-       if (!termtype)
-#endif
-       {
-#if ANY_UNIX
-               write(2, "Environment variable TERM must be set\n", (unsigned)38);
-               exit(1);
-#endif
-#if OSK
-               writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
-               exit(1);
-#endif
-#if AMIGA
-               termtype = TERMTYPE;
-               starttcap(termtype);
-#endif
-#if MSDOS
-               starttcap("pcbios");
-#endif
-#if TOS
-               termtype = "vt52";
-               starttcap(termtype);
-#endif
-#if VMS
-               write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
-               exit(1);
-#endif
-       }
-       else
-       {
-#if MSDOS
-               *o_pcbios = 0;
-#endif
-               /* start termcap stuff */
-               starttcap(termtype);
-       }
-
-       /* create stdscr and curscr */
-       stdscr = kbuf;
-
-       /* change the terminal mode to cbreak/noecho */
-#if ANY_UNIX
-       tcgetattr(2, &oldtermio);
-#endif
-
-#if OSK
-       _gs_opt(0, &oldsgttyb);
-#endif
-
-#if VMS
-       VMS_read_raw = 1;   /* cbreak/noecho */
-       vms_open_tty();
-#endif
-       resume_curses(TRUE);
-}
-
-/* Shut down the Curses package. */
-void endwin()
-{
-       /* change the terminal mode back the way it was */
-       suspend_curses();
-#if AMIGA
-       amiclosewin();
-#endif
-}
-
-
-static int curses_active = FALSE;
-
-/* Send any required termination strings.  Turn off "raw" mode. */
-void suspend_curses()
-{
-#ifndef NO_CURSORSHAPE
-       if (has_CQ)
-       {
-               do_CQ();
-       }
-#endif
-       if (has_TE)                                     /* GB */
-       {
-               do_TE();
-       }
-       if (has_KE)
-       {
-               do_KE();
-       }
-#ifndef NO_COLOR
-       quitcolor();
-#endif
-       refresh();
-
-       /* change the terminal mode back the way it was */
-#if ANY_UNIX
-       tcsetattr(2, TCSADRAIN, &oldtermio);
-#endif
-#if OSK
-       _ss_opt(0, &oldsgttyb);
-#endif
-#if AMIGA
-       ttyshutdown();
-#endif
-#if MSDOS
-       raw_set_stdio(FALSE);
-#endif
-
-#if VMS
-       VMS_read_raw = 0;
-#endif
-       curses_active = FALSE;
-}
-
-
-/* put the terminal in RAW mode.  If "quietly" is FALSE, then ask the user
- * to hit a key, and wait for keystroke before returning.
- */
-void resume_curses(quietly)
-       int     quietly;
-{
-       if (!curses_active)
-       {
-               /* change the terminal mode to cbreak/noecho */
-#if ANY_UNIX
-               ospeed = cfgetospeed(&oldtermio);
-               ERASEKEY = oldtermio.c_cc[VERASE];
-               newtermio = oldtermio;
-               newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
-               newtermio.c_oflag &= ~OPOST;
-               newtermio.c_lflag &= ISIG;
-               newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
-               newtermio.c_cc[VMIN] = 1;
-               newtermio.c_cc[VTIME] = 0;
-               newtermio.c_cc[VSUSP] = 0;
-               tcsetattr(2, TCSADRAIN, &newtermio);
-#endif
-#if OSK
-               newsgttyb = oldsgttyb;
-               newsgttyb.sg_echo = 0;
-               newsgttyb.sg_eofch = 0;
-               newsgttyb.sg_kbach = 0;
-               newsgttyb.sg_kbich = ctrl('C');
-               _ss_opt(0, &newsgttyb);
-               ospeed = oldsgttyb.sg_baud;
-               ERASEKEY = oldsgttyb.sg_bspch;
-#endif
-#if AMIGA
-               /* turn on window resize and RAW */
-               ttysetup();
-#endif
-#if MSDOS
-               raw_set_stdio(TRUE);
-#endif
-
-#if VMS
-               VMS_read_raw = 1;
-               { int c;
-                       read(0,&c,0);   /* Flush the tty buffer. */
-               }
-               ERASEKEY = '\177';  /* Accept <DEL> as <^H> for VMS */
-#endif
-
-               if (has_TI)                                     /* GB */
-               {
-                       do_TI();
-               }
-               if (has_KS)
-               {
-                       do_KS();
-               }
-
-               curses_active = TRUE;
-       }
-
-       /* If we're supposed to quit quietly, then we're done */
-       if (quietly)
-       {
-               return;
-       }
-
-       signal(SIGINT, SIG_IGN);
-
-       move(LINES - 1, 0);
-       do_SO();
-#if VMS
-       qaddstr("\n[Press <RETURN> to continue]");
-#else
-       qaddstr("[Press <RETURN> to continue]");
-#endif
-       do_SE();
-       refresh();
-       ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
-       if (kbuf[0] == ':')
-       {
-               mode = MODE_COLON;
-               addch('\n');
-               refresh();
-       }
-       else
-       {
-               mode = MODE_VI;
-               redraw(MARK_UNSET, FALSE);
-       }       
-       exwrote = FALSE;
-
-       signal(SIGINT, (void(*)()) trapint);
-}
-
-/* This function fetches an optional string from termcap */
-static void mayhave(T, s)
-       char    **T;    /* where to store the returned pointer */
-       char    *s;     /* name of the capability */
-{
-       char    *val;
-
-       val = tgetstr(s, &capbuf);
-       if (val)
-       {
-               *T = val;
-       }
-}
-
-
-/* This function fetches a required string from termcap */
-static void musthave(T, s)
-       char    **T;    /* where to store the returned pointer */
-       char    *s;     /* name of the capability */
-{
-       mayhave(T, s);
-       if (!*T)
-       {
-               write(2, "This termcap entry lacks the :", (unsigned)30);
-               write(2, s, (unsigned)2);
-               write(2, "=: capability\n", (unsigned)14);
-#if OSK
-               write(2, "\l", 1);
-#endif
-               exit(1);
-       }
-}
-
-
-/* This function fetches a pair of strings from termcap.  If one of them is
- * missing, then the other one is ignored.
- */
-static void pair(T, U, sT, sU)
-       char    **T;    /* where to store the first pointer */
-       char    **U;    /* where to store the second pointer */
-       char    *sT;    /* name of the first capability */
-       char    *sU;    /* name of the second capability */
-{
-       mayhave(T, sT);
-       mayhave(U, sU);
-       if (!**T || !**U)
-       {
-               *T = *U = "";
-       }
-}
-
-
-void getsize(int signo);
-
-/* Read everything from termcap */
-static void starttcap(term)
-       char    *term;
-{
-       static char     cbmem[800];
-
-       /* allocate memory for capbuf */
-       capbuf = cbmem;
-
-       /* get the termcap entry */
-       switch (tgetent(kbuf, term))
-       {
-         case -1:
-               write(2, "Can't read /etc/termcap\n", (unsigned)24);
-#if OSK
-               write(2, "\l", 1);
-#endif
-               exit(2);
-
-         case 0:
-               write(2, "Unrecognized TERM type\n", (unsigned)23);
-#if OSK
-               write(2, "\l", 1);
-#endif
-               exit(3);
-       }
-
-       /* get strings */
-       musthave(&UP, "up");
-       mayhave(&VB, "vb");
-       musthave(&CM, "cm");
-       pair(&SO, &SE, "so", "se");
-       mayhave(&TI, "ti");
-       mayhave(&TE, "te");
-       if (tgetnum("ug") <= 0)
-       {
-               pair(&US, &UE, "us", "ue");
-               pair(&MD, &ME, "md", "me");
-
-               /* get italics, or have it default to underline */
-               pair(&AS, &AE, "as", "ae");
-               if (!*AS)
-               {
-                       AS = US;
-                       AE = UE;
-               }
-       }
-#ifndef NO_VISIBLE
-       MV = SO; /* by default */
-       mayhave(&MV, "mv");
-#endif
-       mayhave(&AL, "al");
-       mayhave(&DL, "dl");
-       musthave(&CE, "ce");
-       mayhave(&CD, "cd");
-#if OSK
-       mayhave(&SR_, "sr");
-#else  
-       mayhave(&SR, "sr");
-#endif
-       pair(&IM, &EI, "im", "ei");
-       mayhave(&IC, "ic");
-       mayhave(&DC, "dc");
-
-       /* other termcap stuff */
-       AM = (tgetflag("am") && !tgetflag("xn"));
-       PT = tgetflag("pt");
-#if AMIGA
-       amiopenwin(termtype);   /* Must run this before ttysetup(); */
-       ttysetup();     /* Must run this before getsize(0); */
-#endif
-       getsize(0);
-
-       /* Key sequences */
-       pair(&KS, &KE, "ks", "ke");
-       mayhave(&KU, "ku");             /* up */
-       mayhave(&KD, "kd");             /* down */
-       mayhave(&KL, "kl");             /* left */
-       mayhave(&KR, "kr");             /* right */
-       mayhave(&PU, "kP");             /* PgUp */
-       mayhave(&PD, "kN");             /* PgDn */
-       mayhave(&HM, "kh");             /* Home */
-       mayhave(&EN, "kH");             /* End */
-       mayhave(&KI, "kI");             /* Insert */
-#ifndef CRUNCH
-       if (!PU) mayhave(&PU, "K2");    /* "3x3 pad" names for PgUp, etc. */
-       if (!PD) mayhave(&PD, "K5");
-       if (!HM) mayhave(&HM, "K1");
-       if (!EN) mayhave(&EN, "K4");
-
-       mayhave(&PU, "PU");             /* old XENIX names for PgUp, etc. */
-       mayhave(&PD, "PD");             /* (overrides others, if used.) */
-       mayhave(&HM, "HM");
-       mayhave(&EN, "EN");
-#endif
-#ifndef NO_FKEY
-       mayhave(&FKEY[0], "k0");                /* function key codes */
-       mayhave(&FKEY[1], "k1");
-       mayhave(&FKEY[2], "k2");
-       mayhave(&FKEY[3], "k3");
-       mayhave(&FKEY[4], "k4");
-       mayhave(&FKEY[5], "k5");
-       mayhave(&FKEY[6], "k6");
-       mayhave(&FKEY[7], "k7");
-       mayhave(&FKEY[8], "k8");
-       mayhave(&FKEY[9], "k9");
-# ifndef NO_SHIFT_FKEY
-       mayhave(&FKEY[10], "s0");               /* shift function key codes */
-       mayhave(&FKEY[11], "s1");
-       mayhave(&FKEY[12], "s2");
-       mayhave(&FKEY[13], "s3");
-       mayhave(&FKEY[14], "s4");
-       mayhave(&FKEY[15], "s5");
-       mayhave(&FKEY[16], "s6");
-       mayhave(&FKEY[17], "s7");
-       mayhave(&FKEY[18], "s8");
-       mayhave(&FKEY[19], "s9");
-#  ifndef NO_CTRL_FKEY
-       mayhave(&FKEY[20], "c0");               /* control function key codes */
-       mayhave(&FKEY[21], "c1");
-       mayhave(&FKEY[22], "c2");
-       mayhave(&FKEY[23], "c3");
-       mayhave(&FKEY[24], "c4");
-       mayhave(&FKEY[25], "c5");
-       mayhave(&FKEY[26], "c6");
-       mayhave(&FKEY[27], "c7");
-       mayhave(&FKEY[28], "c8");
-       mayhave(&FKEY[29], "c9");
-#   ifndef NO_ALT_FKEY
-       mayhave(&FKEY[30], "a0");               /* alt function key codes */
-       mayhave(&FKEY[31], "a1");
-       mayhave(&FKEY[32], "a2");
-       mayhave(&FKEY[33], "a3");
-       mayhave(&FKEY[34], "a4");
-       mayhave(&FKEY[35], "a5");
-       mayhave(&FKEY[36], "a6");
-       mayhave(&FKEY[37], "a7");
-       mayhave(&FKEY[38], "a8");
-       mayhave(&FKEY[39], "a9");
-#   endif
-#  endif
-# endif
-#endif
-
-#ifndef NO_CURSORSHAPE
-       /* cursor shapes */
-       CQ = tgetstr("cQ", &capbuf);
-       if (has_CQ)
-       {
-               CX = tgetstr("cX", &capbuf);
-               if (!CX) CX = CQ;
-               CV = tgetstr("cV", &capbuf);
-               if (!CV) CV = CQ;
-               CI = tgetstr("cI", &capbuf);
-               if (!CI) CI = CQ;
-               CR = tgetstr("cR", &capbuf);
-               if (!CR) CR = CQ;
-       }
-# ifndef CRUNCH
-       else
-       {
-               CQ = CV = "";
-               pair(&CQ, &CV, "ve", "vs");
-               CX = CI = CR = CQ;
-       }
-# endif /* !CRUNCH */
-#endif /* !NO_CURSORSHAPE */
-
-#ifndef NO_COLOR
-       strcpy(SOcolor, SO);
-       strcpy(SEcolor, SE);
-       strcpy(AScolor, AS);
-       strcpy(AEcolor, AE);
-       strcpy(MDcolor, MD);
-       strcpy(MEcolor, ME);
-       strcpy(UScolor, US);
-       strcpy(UEcolor, UE);
-# ifndef NO_POPUP
-       strcpy(POPUPcolor, SO);
-# endif
-# ifndef NO_VISIBLE
-       strcpy(VISIBLEcolor, MV);
-# endif
-#endif
-
-}
-
-
-/* This function gets the window size.  It uses the TIOCGWINSZ ioctl call if
- * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
- * This function is called once during initialization, and thereafter it is
- * called whenever the SIGWINCH signal is sent to this process.
- */
-void getsize(signo)
-       int     signo;
-{
-       int     lines;
-       int     cols;
-#ifdef TIOCGWINSZ
-       struct winsize size;
-#endif
-
-#ifdef SIGWINCH
-       /* reset the signal vector */
-       signal(SIGWINCH, getsize);
-#endif
-
-       /* get the window size, one way or another. */
-       lines = cols = 0;
-#ifdef TIOCGWINSZ
-       if (ioctl(2, TIOCGWINSZ, &size) >= 0)
-       {
-               lines = size.ws_row;
-               cols = size.ws_col;
-       }
-#endif
-#if AMIGA
-       /* Amiga gets window size by asking the console.device */
-       if (!strcmp(TERMTYPE, termtype))
-       {
-           auto long len;
-           auto char buf[30];
-           
-           Write(Output(), "\2330 q", 4); /* Ask the console.device */
-           len = Read(Input(), buf, 29);
-           buf[len] = '\000';
-           sscanf(&buf[5], "%d;%d", &lines, &cols);
-       }
-#endif
-       if ((lines == 0 || cols == 0) && signo == 0)
-       {
-               LINES = tgetnum("li");
-               COLS = tgetnum("co");
-       }
-#if MSDOS
-# ifdef RAINBOW
-       if (!strcmp(termtype, "rainbow"))
-       {
-               /* Determine whether Rainbow is in 80-column or 132-column mode */
-               cols = *(unsigned char far *)0xee000f57L;
-       }
-       else
-# endif
-       {
-               lines = v_rows();
-               cols = v_cols();
-       }
-#endif
-       if (lines >= 2)
-       {
-               LINES = lines;
-       }
-
-       if (cols >= 30)
-       {
-               COLS = cols;
-       }
-
-       /* Make sure we got values that we can live with */
-       if (LINES < 2 || COLS < 30)
-       {
-               write(2, "Screen too small\n", (unsigned)17);
-#if OSK
-               write(2, "\l", 1);
-#endif
-               endwin();
-               exit(2);
-       }
-
-#if AMIGA
-       if (*o_lines != LINES || *o_columns != COLS)
-       {
-               *o_lines = LINES;
-               *o_columns = COLS;
-       }
-#endif
-}
-
-
-/* This is a function version of addch() -- it is used by tputs() */
-int faddch(ch)
-       int     ch;
-{
-       addch(ch);
-
-       return 0;
-}
-
-/* This function quickly adds a string to the output queue.  It does *NOT*
- * convert \n into <CR><LF>.
- */
-void qaddstr(str)
-       char    *str;
-{
-       REG char *s_, *d_;
-
-#if MSDOS
-       if (o_pcbios[0])
-       {
-               while (*str)
-                       qaddch(*str++);
-               return;
-       }
-#endif
-       for (s_=(str), d_=stdscr; *d_++ = *s_++; )
-       {
-       }
-       stdscr = d_ - 1;
-}
-
-/* Output the ESC sequence needed to go into any video mode, if supported */
-void attrset(a)
-       int     a;
-{
-       do_aend();
-       if (a == A_BOLD)
-       {
-               do_MD();
-               aend = ME;
-       }
-       else if (a == A_UNDERLINE)
-       {
-               do_US();
-               aend = UE;
-       }
-       else if (a == A_ALTCHARSET)
-       {
-               do_AS();
-               aend = AE;
-       }
-       else
-       {
-               aend = "";
-       }
-}
-
-
-/* Insert a single character into the display */
-void insch(ch)
-       int     ch;
-{
-       if (has_IM)
-               do_IM();
-       do_IC();
-       qaddch(ch);
-       if (has_EI)
-               do_EI();
-}
-
-void wrefresh()
-{
-       if (stdscr != kbuf)
-       {
-               VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
-               stdscr = kbuf;
-       }
-}
-
-void wqrefresh()
-{
-       if (stdscr - kbuf > 2000)
-       {
-               VOIDBIOS(stdscr = kbuf,
-               {
-                       ttywrite(kbuf, (unsigned)(stdscr - kbuf)); 
-                       stdscr = kbuf;
-               });
-       }
-}
-
-#ifndef NO_COLOR
-/* This function is called during termination.  It resets color modes */
-int ansiquit()
-{
-       /* if ANSI color terminal, then reset the colors */
-       if (!strcmp(UP, "\033[A"))
-       {
-               tputs("\033[37;40m\033[m", 1, faddch);
-               clrtoeol();
-               return 1;
-       }
-       return 0;
-}
-
-/* This sets the color strings that work for ANSI terminals.  If the TERMCAP
- * doesn't look like an ANSI terminal, then it returns FALSE.  If the colors
- * aren't understood, it also returns FALSE.  If all goes well, it returns TRUE
- */
-int ansicolor(cmode, attrbyte)
-       int     cmode;          /* mode to set, e.g. A_NORMAL */
-       int     attrbyte;       /* IBM PC attribute byte */
-{
-       char    temp[16];       /* hold the new mode string */
-
-       /* if not ANSI-ish, then fail */
-       if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
-       {
-               msg("Don't know how to set colors for this terminal");
-               return 0;
-       }
-
-       /* construct the color string */
-       sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
-               "04261537"[attrbyte & 0x07],
-               "04261537"[(attrbyte >> 4) & 0x07],
-               (attrbyte & 0x08) ? ";1" : "",
-               (attrbyte & 0x80) ? ";5" : "");
-
-       /* stick it in the right place */
-       switch (cmode)
-       {
-         case A_NORMAL:
-               if (!strcmp(MEcolor, normalcolor))
-                       strcpy(MEcolor, temp);
-               if (!strcmp(UEcolor, normalcolor))
-                       strcpy(UEcolor, temp);
-               if (!strcmp(AEcolor, normalcolor))
-                       strcpy(AEcolor, temp);
-               if (!strcmp(SEcolor, normalcolor))
-                       strcpy(SEcolor, temp);
-
-               strcpy(normalcolor, temp);
-               tputs(normalcolor, 1, faddch);
-               break;
-
-         case A_BOLD:
-               strcpy(MDcolor, temp);
-               strcpy(MEcolor, normalcolor);
-               break;
-
-         case A_UNDERLINE:
-               strcpy(UScolor, temp);
-               strcpy(UEcolor, normalcolor);
-               break;
-
-         case A_ALTCHARSET:
-               strcpy(AScolor, temp);
-               strcpy(AEcolor, normalcolor);
-               break;
-
-         case A_STANDOUT:
-               strcpy(SOcolor, temp);
-               strcpy(SEcolor, normalcolor);
-               break;
-
-#ifndef NO_POPUP
-         case A_POPUP:
-               strcpy(POPUPcolor, temp);
-               break;
-#endif
-
-#ifndef NO_VISIBLE
-         case A_VISIBLE:
-               strcpy(VISIBLEcolor, temp);
-               break;
-#endif
-       }
-
-       return 1;
-}
-
-
-/* This function outputs the ESC sequence needed to switch the screen back
- * to "normal" mode.  On color terminals which haven't had their color set
- * yet, this is one of the termcap strings; for color terminals that really
- * have had colors defined, we just the "normal color" escape sequence.
- */
-endcolor()
-{
-       if (aend == ME)
-               tputs(MEcolor, 1, faddch);
-       else if (aend == UE)
-               tputs(UEcolor, 1, faddch);
-       else if (aend == AE)
-               tputs(AEcolor, 1, faddch);
-       else if (aend == SE)
-               tputs(SEcolor, 1, faddch);
-       aend = "";
-       return 0;
-}
-
-
-#endif /* !NO_COLOR */
diff --git a/commands/elvis/curses.h b/commands/elvis/curses.h
deleted file mode 100644 (file)
index 84c897c..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/* curses.h */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This is the header file for a small, fast, fake curses package */
-
-/* termcap stuff */
-extern char    *tgoto();
-extern char    *tgetstr();
-extern void    tputs();
-
-#if MSDOS
-/* BIOS interface used instead of termcap for MS-DOS */
-extern int     vmode;
-extern void    v_up();
-extern void    v_cb();
-extern void    v_cs();
-extern void    v_ce();
-extern void    v_cl();
-extern void    v_cd();
-extern void    v_al();
-extern void    v_dl();
-extern void    v_sr();
-extern void    v_move();
-#endif
-
-/* faddch() is a function.  a pointer to it is passed to tputs() */
-extern int     faddch();
-
-/* data types */
-#define WINDOW char
-
-/* CONSTANTS & SYMBOLS */
-#define TRUE           1
-#define FALSE          0
-#define A_NORMAL       0
-#define A_STANDOUT     1
-#define A_BOLD         2
-#define A_UNDERLINE    3
-#define A_ALTCHARSET   4
-#define A_POPUP                5
-#define A_VISIBLE      6
-#define KBSIZ          4096
-
-/* figure out how many function keys we need to allow. */
-#ifndef NO_FKEY
-# ifdef NO_SHIFT_FKEY
-#  define      NFKEYS  10
-# else
-#  ifdef NO_CTRL_FKEY
-#   define     NFKEYS  20
-#  else
-#   ifdef NO_ALT_FKEY
-#    define    NFKEYS  30
-#   else
-#    define    NFKEYS  40
-#   endif
-#  endif
-# endif
-extern char    *FKEY[NFKEYS];  /* :k0=:...:k9=: codes sent by function keys */
-#endif
-
-/* extern variables, defined in curses.c */
-extern char    *termtype;      /* name of terminal entry */
-extern short   ospeed;         /* tty speed, eg B2400 */
-#if OSK
-extern char PC_;       /* Pad char */
-extern char    *BC;    /* Backspace char string */
-#else
-extern char    PC;             /* Pad char */
-#endif
-extern WINDOW  *stdscr;        /* pointer into kbuf[] */
-extern WINDOW  kbuf[KBSIZ];    /* a very large output buffer */
-extern int     LINES;          /* :li#: number of rows */
-extern int     COLS;           /* :co#: number of columns */
-extern int     AM;             /* :am:  boolean: auto margins? */
-extern int     PT;             /* :pt:  boolean: physical tabs? */
-extern char    *VB;            /* :vb=: visible bell */
-extern char    *UP;            /* :up=: move cursor up */
-extern char    *SO;            /* :so=: standout start */
-extern char    *SE;            /* :se=: standout end */
-extern char    *US;            /* :us=: underline start */
-extern char    *UE;            /* :ue=: underline end */
-extern char    *MD;            /* :md=: bold start */
-extern char    *ME;            /* :me=: bold end */
-extern char    *AS;            /* :as=: alternate (italic) start */
-extern char    *AE;            /* :ae=: alternate (italic) end */
-#ifndef NO_VISIBLE
-extern char    *MV;            /* :mv=: "visible" selection start */
-#endif
-extern char    *CM;            /* :cm=: cursor movement */
-extern char    *CE;            /* :ce=: clear to end of line */
-extern char    *CD;            /* :cd=: clear to end of screen */
-extern char    *AL;            /* :al=: add a line */
-extern char    *DL;            /* :dl=: delete a line */
-#if OSK
-extern char    *SR_;           /* :sr=: scroll reverse */
-#else
-extern char    *SR;            /* :sr=: scroll reverse */
-#endif
-extern char    *KS;            /* :ks=: init string for cursor */
-extern char    *KE;            /* :ke=: restore string for cursor */
-extern char    *KU;            /* :ku=: sequence sent by up key */
-extern char    *KD;            /* :kd=: sequence sent by down key */
-extern char    *KL;            /* :kl=: sequence sent by left key */
-extern char    *KR;            /* :kr=: sequence sent by right key */
-extern char    *PU;            /* :PU=: key sequence sent by PgUp key */
-extern char    *PD;            /* :PD=: key sequence sent by PgDn key */
-extern char    *HM;            /* :HM=: key sequence sent by Home key */
-extern char    *EN;            /* :EN=: key sequence sent by End key */
-extern char    *KI;            /* :kI=: key sequence sent by Insert key */
-extern char    *IM;            /* :im=: insert mode start */
-extern char    *IC;            /* :ic=: insert following char */
-extern char    *EI;            /* :ei=: insert mode end */
-extern char    *DC;            /* :dc=: delete a character */
-extern char    *TI;            /* :ti=: terminal init */       /* GB */
-extern char    *TE;            /* :te=: terminal exit */       /* GB */
-#ifndef NO_CURSORSHAPE
-extern char    *CQ;            /* :cQ=: normal cursor */
-extern char    *CX;            /* :cX=: cursor used for EX command/entry */
-extern char    *CV;            /* :cV=: cursor used for VI command mode */
-extern char    *CI;            /* :cI=: cursor used for VI input mode */
-extern char    *CR;            /* :cR=: cursor used for VI replace mode */
-#endif
-extern char    *aend;          /* end an attribute -- either UE or ME */
-extern char    ERASEKEY;       /* taken from the ioctl structure */
-#ifndef NO_COLOR
-extern char    SOcolor[];
-extern char    SEcolor[];
-extern char    UScolor[];
-extern char    UEcolor[];
-extern char    MDcolor[];
-extern char    MEcolor[];
-extern char    AScolor[];
-extern char    AEcolor[];
-# ifndef NO_POPUP
-extern char    POPUPcolor[];
-# endif
-# ifndef NO_VISIBLE
-extern char    VISIBLEcolor[];
-# endif
-extern char    normalcolor[];
-#endif /* undef NO_COLOR */
-
-/* Msdos-versions may use bios; others always termcap.
- * Will emit some 'code has no effect' warnings in unix.
- */
-#if MSDOS
-extern char o_pcbios[1];               /* BAH! */
-#define        CHECKBIOS(x,y)  (*o_pcbios ? (x) : (y))
-#define VOIDBIOS(x,y)  {if (*o_pcbios) {x;} else {y;}}
-#else
-#define        CHECKBIOS(x,y)  (y)
-#define VOIDBIOS(x,y)  {y;}
-#endif
-
-#ifndef NO_COLOR
-# define setcolor(m,a) CHECKBIOS(bioscolor(m,a), ansicolor(m,a))
-# define fixcolor()    VOIDBIOS(;, tputs(normalcolor, 1, faddch))
-# define quitcolor()   CHECKBIOS(biosquit(), ansiquit())
-# define do_SO()       VOIDBIOS((vmode=A_STANDOUT), tputs(SOcolor, 1, faddch))
-# define do_SE()       VOIDBIOS((vmode=A_NORMAL), tputs(SEcolor, 1, faddch))
-# define do_US()       VOIDBIOS((vmode=A_UNDERLINE), tputs(UScolor, 1, faddch))
-# define do_UE()       VOIDBIOS((vmode=A_NORMAL), tputs(UEcolor, 1, faddch))
-# define do_MD()       VOIDBIOS((vmode=A_BOLD), tputs(MDcolor, 1, faddch))
-# define do_ME()       VOIDBIOS((vmode=A_NORMAL), tputs(MEcolor, 1, faddch))
-# define do_AS()       VOIDBIOS((vmode=A_ALTCHARSET), tputs(AScolor, 1, faddch))
-# define do_AE()       VOIDBIOS((vmode=A_NORMAL), tputs(AEcolor, 1, faddch))
-# define do_POPUP()    VOIDBIOS((vmode=A_POPUP), tputs(POPUPcolor, 1, faddch))
-# define do_VISIBLE()  VOIDBIOS((vmode=A_VISIBLE), tputs(VISIBLEcolor, 1, faddch))
-#else
-# define do_SO()       VOIDBIOS((vmode=A_STANDOUT), tputs(SO, 1, faddch))
-# define do_SE()       VOIDBIOS((vmode=A_NORMAL), tputs(SE, 1, faddch))
-# define do_US()       VOIDBIOS((vmode=A_UNDERLINE), tputs(US, 1, faddch))
-# define do_UE()       VOIDBIOS((vmode=A_NORMAL), tputs(UE, 1, faddch))
-# define do_MD()       VOIDBIOS((vmode=A_BOLD), tputs(MD, 1, faddch))
-# define do_ME()       VOIDBIOS((vmode=A_NORMAL), tputs(ME, 1, faddch))
-# define do_AS()       VOIDBIOS((vmode=A_ALTCHARSET), tputs(AS, 1, faddch))
-# define do_AE()       VOIDBIOS((vmode=A_NORMAL), tputs(AE, 1, faddch))
-# define do_POPUP()    VOIDBIOS((vmode=A_POPUP), tputs(SO, 1, faddch))
-# define do_VISIBLE()  VOIDBIOS((vmode=A_VISIBLE), tputs(MV, 1, faddch))
-#endif
-
-#define        do_VB()         VOIDBIOS(;, tputs(VB, 1, faddch))
-#define        do_UP()         VOIDBIOS(v_up(), tputs(UP, 1, faddch))
-#undef do_CM           /* move */
-#define        do_CE()         VOIDBIOS(v_ce(), tputs(CE, 1, faddch))
-#define        do_CD()         VOIDBIOS(v_cd(), tputs(CD, 1, faddch))
-#define        do_AL()         VOIDBIOS(v_al(), tputs(AL, LINES, faddch))
-#define        do_DL()         VOIDBIOS(v_dl(), tputs(DL, LINES, faddch))
-#if OSK
-#define        do_SR()         VOIDBIOS(v_sr(), tputs(SR_, 1, faddch))
-#else
-#define        do_SR()         VOIDBIOS(v_sr(), tputs(SR, 1, faddch))
-#endif
-#define do_KS()                VOIDBIOS(1, tputs(KS, 1, faddch))
-#define do_KE()                VOIDBIOS(1, tputs(KE, 1, faddch))
-#define        do_IM()         VOIDBIOS(;, tputs(IM, 1, faddch))
-#define        do_IC()         VOIDBIOS(;, tputs(IC, 1, faddch))
-#define        do_EI()         VOIDBIOS(;, tputs(EI, 1, faddch))
-#define        do_DC()         VOIDBIOS(;, tputs(DC, COLS, faddch))
-#define        do_TI()         VOIDBIOS(;, (void)ttywrite(TI, (unsigned)strlen(TI)))
-#define        do_TE()         VOIDBIOS(;, (void)ttywrite(TE, (unsigned)strlen(TE)))
-#ifndef NO_CURSORSHAPE
-# define do_CQ()       VOIDBIOS(v_cs(), tputs(CQ, 1, faddch))
-# define do_CX()       VOIDBIOS(v_cs(), tputs(CX, 1, faddch))
-# define do_CV()       VOIDBIOS(v_cs(), tputs(CV, 1, faddch))
-# define do_CI()       VOIDBIOS(v_cb(), tputs(CI, 1, faddch))
-# define do_CR()       VOIDBIOS(v_cb(), tputs(CR, 1, faddch))
-#endif
-#ifndef NO_COLOR
-# define do_aend()     VOIDBIOS((vmode=A_NORMAL), endcolor())
-#else
-# define do_aend()     VOIDBIOS((vmode=A_NORMAL), tputs(aend, 1, faddch))
-#endif
-
-#define        has_AM          CHECKBIOS(1, AM)
-#define        has_PT          CHECKBIOS(0, PT)
-#define        has_VB          CHECKBIOS((char *)0, VB)
-#define        has_UP          CHECKBIOS((char *)1, UP)
-#define        has_SO          CHECKBIOS((char)1, (*SO))
-#define        has_SE          CHECKBIOS((char)1, (*SE))
-#define        has_US          CHECKBIOS((char)1, (*US))
-#define        has_UE          CHECKBIOS((char)1, (*UE))
-#define        has_MD          CHECKBIOS((char)1, (*MD))
-#define        has_ME          CHECKBIOS((char)1, (*ME))
-#define        has_AS          CHECKBIOS((char)1, (*AS))
-#define        has_AE          CHECKBIOS((char)1, (*AE))
-#undef has_CM          /* cursor move: don't need */
-#define        has_CB          CHECKBIOS(1, 0)
-#define        has_CS          CHECKBIOS(1, 0)
-#define        has_CE          CHECKBIOS((char *)1, CE)
-#define        has_CD          CHECKBIOS((char *)1, CD)
-#define        has_AL          CHECKBIOS((char *)1, AL)
-#define        has_DL          CHECKBIOS((char *)1, DL)
-#if OSK
-#define        has_SR          CHECKBIOS((char *)1, SR_)
-#else
-#define        has_SR          CHECKBIOS((char *)1, SR)
-#endif
-#define has_KS         CHECKBIOS((char)1, (*KS))
-#define has_KE         CHECKBIOS((char)1, (*KE))
-#define        has_KU          KU
-#define        has_KD          KD
-#define        has_KL          KL
-#define        has_KR          KR
-#define has_HM         HM
-#define has_EN         EN
-#define has_PU         PU
-#define has_PD         PD
-#define has_KI         KI
-#define        has_IM          CHECKBIOS((char)0, (*IM))
-#define        has_IC          CHECKBIOS((char)0, (*IC))
-#define        has_EI          CHECKBIOS((char)0, (*EI))
-#define        has_DC          CHECKBIOS((char *)0, DC)
-#define        has_TI          CHECKBIOS((char)0, (*TI))
-#define        has_TE          CHECKBIOS((char)0, (*TE))
-#ifndef NO_CURSORSHAPE
-#define has_CQ         CHECKBIOS((char *)1, CQ)
-#endif
-
-/* (pseudo)-Curses-functions */
-
-#ifdef lint
-# define _addCR                VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\r') : (stdscr[-1] = '\n')))
-#else
-# if OSK
-#  define _addCR       VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\l') : (stdscr[-1] = stdscr[-1])))
-# else
-#  define _addCR       VOIDBIOS(;, (stdscr[-1] == '\n' ? qaddch('\r') : 0))
-# endif
-#endif
-
-#ifdef AZTEC_C
-# define qaddch(ch)    CHECKBIOS(v_put(ch), (*stdscr = (ch), *stdscr++))
-#else
-#define qaddch(ch)     CHECKBIOS(v_put(ch), (*stdscr++ = (ch)))
-#endif
-
-#if OSK
-#define addch(ch)      if (qaddch(ch) == '\n') qaddch('\l'); else
-#else
-#define addch(ch)      if (qaddch(ch) == '\n') qaddch('\r'); else
-#endif
-
-extern void initscr();
-extern void endwin();
-extern void suspend_curses();
-extern void resume_curses();
-extern void attrset();
-extern void insch();
-extern void qaddstr();
-extern void wrefresh();
-extern void wqrefresh();
-#define addstr(str)    {qaddstr(str); _addCR;}
-#define move(y,x)      VOIDBIOS(v_move(x,y), tputs(tgoto(CM, x, y), 1, faddch))
-#define mvaddch(y,x,ch)        {move(y,x); addch(ch);}
-#define refresh()      VOIDBIOS(;, wrefresh())
-#define standout()     do_SO()
-#define standend()     do_SE()
-#define clrtoeol()     do_CE()
-#define clrtobot()     do_CD()
-#define insertln()     do_AL()
-#define deleteln()     do_DL()
-#define delch()                do_DC()
-#define scrollok(w,b)
-#define raw()
-#define echo()
-#define cbreak()
-#define noraw()
-#define noecho()
-#define nocbreak()
diff --git a/commands/elvis/cut.c b/commands/elvis/cut.c
deleted file mode 100644 (file)
index 0e0bb39..0000000
+++ /dev/null
@@ -1,700 +0,0 @@
-/* cut.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains function which manipulate the cut buffers. */
-
-#include "config.h"
-#include "vi.h"
-#if TURBOC
-#include <process.h>           /* needed for getpid */
-#endif
-#if TOS
-#include <osbind.h>
-#define        rename(a,b)     Frename(0,a,b)
-#endif
-
-# define NANONS        9       /* number of anonymous buffers */
-
-static struct cutbuf
-{
-       short   *phys;  /* pointer to an array of #s of BLKs containing text */
-       int     nblks;  /* number of blocks in phys[] array */
-       int     start;  /* offset into first block of start of cut */
-       int     end;    /* offset into last block of end of cut */
-       int     tmpnum; /* ID number of the temp file */
-       char    lnmode; /* boolean: line-mode cut? (as opposed to char-mode) */
-}
-       named[27],      /* cut buffers "a through "z and ". */
-       anon[NANONS];   /* anonymous cut buffers */
-
-static char    cbname; /* name chosen for next cut/paste operation */
-static char    dotcb;  /* cut buffer to use if "doingdot" is set */
-
-
-#ifndef NO_RECYCLE
-/* This function builds a list of all blocks needed in the current tmp file
- * for the contents of cut buffers.
- * !!! WARNING: if you have more than ~450000 bytes of text in all of the
- * cut buffers, then this will fail disastrously, because buffer overflow
- * is *not* allowed for.
- */
-int cutneeds(need)
-       BLK             *need;  /* this is where we deposit the list */
-{
-       struct cutbuf   *cb;    /* used to count through cut buffers */
-       int             i;      /* used to count through blocks of a cut buffer */
-       int             n;      /* total number of blocks in list */
-
-       n = 0;
-
-       /* first the named buffers... */
-       for (cb = named; cb < &named[27]; cb++)
-       {
-               if (cb->tmpnum != tmpnum)
-                       continue;
-
-               for (i = cb->nblks; i-- > 0; )
-               {
-                       need->n[n++] = cb->phys[i];
-               }
-       }
-
-       /* then the anonymous buffers */
-       for (cb = anon; cb < &anon[NANONS]; cb++)
-       {
-               if (cb->tmpnum != tmpnum)
-                       continue;
-
-               for (i = cb->nblks; i-- > 0; )
-               {
-                       need->n[n++] = cb->phys[i];
-               }
-       }
-
-       /* return the length of the list */
-       return n;
-}
-#endif
-
-static void maybezap(num)
-       int     num;    /* the tmpnum of the temporary file to [maybe] delete */
-{
-       char    cutfname[80];
-       int     i;
-
-       /* if this is the current tmp file, then we'd better keep it! */
-       if (tmpfd >= 0 && num == tmpnum)
-       {
-               return;
-       }
-
-       /* see if anybody else needs this tmp file */
-       for (i = 27; --i >= 0; )
-       {
-               if (named[i].nblks > 0 && named[i].tmpnum == num)
-               {
-                       break;
-               }
-       }
-       if (i < 0)
-       {
-               for (i = NANONS; --i >= 0 ; )
-               {
-                       if (anon[i].nblks > 0 && anon[i].tmpnum == num)
-                       {
-                               break;
-                       }
-               }
-       }
-
-       /* if nobody else needs it, then discard the tmp file */
-       if (i < 0)
-       {
-#if MSDOS || TOS
-               strcpy(cutfname, o_directory);
-               if ((i = strlen(cutfname)) && !strchr(":/\\", cutfname[i - 1]))
-                       cutfname[i++] = SLASH;
-               sprintf(cutfname + i, TMPNAME + 3, getpid(), num);
-#else
-               sprintf(cutfname, TMPNAME, o_directory, getpid(), num);
-#endif
-               unlink(cutfname);
-       }
-}
-
-/* This function frees a cut buffer.  If it was the last cut buffer that
- * refered to an old temp file, then it will delete the temp file. */
-static void cutfree(buf)
-       struct cutbuf   *buf;
-{
-       int     num;
-
-       /* return immediately if the buffer is already empty */
-       if (buf->nblks <= 0)
-       {
-               return;
-       }
-
-       /* else free up stuff */
-       num = buf->tmpnum;
-       buf->nblks = 0;
-#ifdef DEBUG
-       if (!buf->phys)
-               msg("cutfree() tried to free a NULL buf->phys pointer.");
-       else
-#endif
-       free((char *)buf->phys);
-
-       /* maybe delete the temp file */
-       maybezap(num);
-}
-
-/* This function is called when we are about to abort a tmp file.
- *
- * To minimize the number of extra files lying around, only named cut buffers
- * are preserved in a file switch; the anonymous buffers just go away.
- */
-void cutswitch()
-{
-       int     i;
-
-       /* mark the current temp file as being "obsolete", and close it.  */
-       storename((char *)0);
-       close(tmpfd);
-       tmpfd = -1;
-
-       /* discard all anonymous cut buffers */
-       for (i = 0; i < NANONS; i++)
-       {
-               cutfree(&anon[i]);
-       }
-
-       /* delete the temp file, if we don't really need it */
-       maybezap(tmpnum);
-}
-
-/* This function should be called just before termination of vi */
-void cutend()
-{
-       int     i;
-
-       /* free the anonymous buffers, if they aren't already free */
-       cutswitch();
-
-       /* free all named cut buffers, since they might be forcing an older
-        * tmp file to be retained.
-        */
-       for (i = 0; i < 27; i++)
-       {
-               cutfree(&named[i]);
-       }
-
-       /* delete the temp file */
-       maybezap(tmpnum);
-}
-
-
-/* This function is used to select the cut buffer to be used next */
-void cutname(name)
-       int     name;   /* a single character */
-{
-       cbname = name;
-}
-
-
-
-
-/* This function copies a selected segment of text to a cut buffer */
-void cut(from, to)
-       MARK    from;           /* start of text to cut */
-       MARK    to;             /* end of text to cut */
-{
-       int             first;  /* logical number of first block in cut */
-       int             last;   /* logical number of last block used in cut */
-       long            line;   /* a line number */
-       int             lnmode; /* boolean: will this be a line-mode cut? */
-       MARK            delthru;/* end of text temporarily inserted for apnd */
-       REG struct cutbuf *cb;
-       REG long        l;
-       REG int         i;
-       REG char        *scan;
-       char            *blkc;
-
-       /* detect whether this must be a line-mode cut or char-mode cut */
-       if (markidx(from) == 0 && markidx(to) == 0)
-               lnmode = TRUE;
-       else
-               lnmode = FALSE;
-
-       /* by default, we don't "delthru" anything */
-       delthru = MARK_UNSET;
-
-       /* handle the "doingdot" quirks */
-       if (doingdot)
-       {
-               if (!cbname)
-               {
-                       cbname = dotcb;
-               }
-       }
-       else if (cbname != '.')
-       {
-               dotcb = cbname;
-       }
-
-       /* decide which cut buffer to use */
-       if (!cbname)
-       {
-               /* free up the last anonymous cut buffer */
-               cutfree(&anon[NANONS - 1]);
-
-               /* shift the anonymous cut buffers */
-               for (i = NANONS - 1; i > 0; i--)
-               {
-                       anon[i] = anon[i - 1];
-               }
-
-               /* use the first anonymous cut buffer */
-               cb = anon;
-               cb->nblks = 0;
-       }
-       else if (cbname >= 'a' && cbname <= 'z')
-       {
-               cb = &named[cbname - 'a'];
-               cutfree(cb);
-       }
-#ifndef CRUNCH
-       else if (cbname >= 'A' && cbname <= 'Z')
-       {
-               cb = &named[cbname - 'A'];
-               if (cb->nblks > 0)
-               {
-                       /* resolve linemode/charmode differences */
-                       if (!lnmode && cb->lnmode)
-                       {
-                               from &= ~(BLKSIZE - 1);
-                               if (markidx(to) != 0 || to == from)
-                               {
-                                       to = to + BLKSIZE - markidx(to);
-                               }
-                               lnmode = TRUE;
-                       }
-
-                       /* insert the old cut-buffer before the new text */
-                       mark[28] = to;
-                       delthru = paste(from, FALSE, TRUE);
-                       if (delthru == MARK_UNSET)
-                       {
-                               return;
-                       }
-                       delthru++;
-                       to = mark[28];
-               }
-               cutfree(cb);
-       }
-#endif /* not CRUNCH */
-       else if (cbname == '.')
-       {
-               cb = &named[26];
-               cutfree(cb);
-       }
-       else
-       {
-               msg("Invalid cut buffer name: \"%c", cbname);
-               dotcb = cbname = '\0';
-               return;
-       }
-       cbname = '\0';
-       cb->tmpnum = tmpnum;
-
-       /* detect whether we're doing a line mode cut */
-       cb->lnmode = lnmode;
-
-       /* ---------- */
-
-       /* Reporting... */      
-       if (markidx(from) == 0 && markidx(to) == 0)
-       {
-               rptlines = markline(to) - markline(from);
-               rptlabel = "yanked";
-       }
-
-       /* ---------- */
-
-       /* make sure each block has a physical disk address */
-       blksync();
-
-       /* find the first block in the cut */
-       line = markline(from);
-       for (first = 1; line > lnum[first]; first++)
-       {
-       }
-
-       /* fetch text of the block containing that line */
-       blkc = scan = blkget(first)->c;
-
-       /* find the mark in the block */
-       for (l = lnum[first - 1]; ++l < line; )
-       {
-               while (*scan++ != '\n')
-               {
-               }
-       }
-       scan += markidx(from);
-
-       /* remember the offset of the start */
-       cb->start = scan - blkc;
-
-       /* ---------- */
-
-       /* find the last block in the cut */
-       line = markline(to);
-       for (last = first; line > lnum[last]; last++)
-       {
-       }
-
-       /* fetch text of the block containing that line */
-       if (last != first)
-       {
-               blkc = scan = blkget(last)->c;
-       }
-       else
-       {
-               scan = blkc;
-       }
-
-       /* find the mark in the block */
-       for (l = lnum[last - 1]; ++l < line; )
-       {
-               while (*scan++ != '\n')
-               {
-               }
-       }
-       if (markline(to) <= nlines)
-       {
-               scan += markidx(to);
-       }
-
-       /* remember the offset of the end */
-       cb->end = scan - blkc;
-
-       /* ------- */
-
-       /* remember the physical block numbers of all included blocks */
-       cb->nblks = last - first;
-       if (cb->end > 0)
-       {
-               cb->nblks++;
-       }
-#ifdef lint
-       cb->phys = (short *)0;
-#else
-       cb->phys = (short *)malloc((unsigned)(cb->nblks * sizeof(short)));
-#endif
-       for (i = 0; i < cb->nblks; i++)
-       {
-               cb->phys[i] = hdr.n[first++];
-       }
-
-#ifndef CRUNCH
-       /* if we temporarily inserted text for appending, then delete that
-        * text now -- before the user sees it.
-        */
-       if (delthru)
-       {
-               line = rptlines;
-               delete(from, delthru);
-               rptlines = line;
-               rptlabel = "yanked";
-       }
-#endif /* not CRUNCH */
-}
-
-
-static void readcutblk(cb, blkno)
-       struct cutbuf   *cb;
-       int             blkno;
-{
-       char            cutfname[50];/* name of an old temp file */
-       int             fd;     /* either tmpfd or the result of open() */
-#if MSDOS || TOS
-       int             i;
-#endif
-
-       /* decide which fd to use */
-       if (cb->tmpnum == tmpnum)
-       {
-               fd = tmpfd;
-       }
-       else
-       {
-#if MSDOS || TOS
-               strcpy(cutfname, o_directory);
-               if ((i = strlen(cutfname)) && !strchr(":/\\", cutfname[i-1]))
-                       cutfname[i++]=SLASH;
-               sprintf(cutfname+i, TMPNAME+3, getpid(), cb->tmpnum);
-#else
-               sprintf(cutfname, TMPNAME, o_directory, getpid(), cb->tmpnum);
-#endif
-               fd = open(cutfname, O_RDONLY);
-       }
-
-       /* get the block */
-       lseek(fd, (long)cb->phys[blkno] * (long)BLKSIZE, 0);
-       if (read(fd, tmpblk.c, (unsigned)BLKSIZE) != BLKSIZE)
-       {
-               msg("Error reading back from tmp file for pasting!");
-       }
-
-       /* close the fd, if it isn't tmpfd */
-       if (fd != tmpfd)
-       {
-               close(fd);
-       }
-}
-
-
-/* This function inserts text from a cut buffer, and returns the MARK where
- * insertion ended.  Return MARK_UNSET on errors.
- */
-MARK paste(at, after, retend)
-       MARK    at;     /* where to insert the text */
-       int     after;  /* boolean: insert after mark? (rather than before) */
-       int     retend; /* boolean: return end of text? (rather than start) */
-{
-       REG struct cutbuf       *cb;
-       REG int                 i;
-
-       /* handle the "doingdot" quirks */
-       if (doingdot)
-       {
-               if (!cbname)
-               {
-                       if (dotcb >= '1' && dotcb < '1' + NANONS - 1)
-                       {
-                               dotcb++;
-                       }
-                       cbname = dotcb;
-               }
-       }
-       else if (cbname != '.')
-       {
-               dotcb = cbname;
-       }
-
-       /* decide which cut buffer to use */
-       if (cbname >= 'A' && cbname <= 'Z')
-       {
-               cb = &named[cbname - 'A'];
-       }
-       else if (cbname >= 'a' && cbname <= 'z')
-       {
-               cb = &named[cbname - 'a'];
-       }
-       else if (cbname >= '1' && cbname <= '9')
-       {
-               cb = &anon[cbname - '1'];
-       }
-       else if (cbname == '.')
-       {
-               cb = &named[26];
-       }
-       else if (!cbname)
-       {
-               cb = anon;
-       }
-       else
-       {
-               msg("Invalid cut buffer name: \"%c", cbname);
-               cbname = '\0';
-               return MARK_UNSET;
-       }
-
-       /* make sure it isn't empty */
-       if (cb->nblks == 0)
-       {
-               if (cbname)
-                       msg("Cut buffer \"%c is empty", cbname);
-               else
-                       msg("Cut buffer is empty");
-               cbname = '\0';
-               return MARK_UNSET;
-       }
-       cbname = '\0';
-
-       /* adjust the insertion MARK for "after" and line-mode cuts */
-       if (cb->lnmode)
-       {
-               at &= ~(BLKSIZE - 1);
-               if (after)
-               {
-                       at += BLKSIZE;
-               }
-       }
-       else if (after)
-       {
-               /* careful! if markidx(at) == 0 we might be pasting into an
-                * empty line -- so we can't blindly increment "at".
-                */
-               if (markidx(at) == 0)
-               {
-                       pfetch(markline(at));
-                       if (plen != 0)
-                       {
-                               at++;
-                       }
-               }
-               else
-               {
-                       at++;
-               }
-       }
-
-       /* put a copy of the "at" mark in the mark[] array, so it stays in
-        * sync with changes made via add().
-        */
-       mark[27] = at;
-
-       /* simple one-block paste? */
-       if (cb->nblks == 1)
-       {
-               /* get the block */
-               readcutblk(cb, 0);
-
-               /* isolate the text we need within it */
-               if (cb->end)
-               {
-                       tmpblk.c[cb->end] = '\0';
-               }
-
-               /* insert it */
-               ChangeText
-               {
-                       add(at, &tmpblk.c[cb->start]);
-               }
-       }
-       else
-       {
-               /* multi-block paste */
-
-               ChangeText
-               {
-                       i = cb->nblks - 1;
-
-                       /* add text from the last block first */
-                       if (cb->end > 0)
-                       {
-                               readcutblk(cb, i);
-                               tmpblk.c[cb->end] = '\0';
-                               add(at, tmpblk.c);
-                               i--;
-                       }
-
-                       /* add intervening blocks */
-                       while (i > 0)
-                       {
-                               readcutblk(cb, i);
-                               add(at, tmpblk.c);
-                               i--;
-                       }
-
-                       /* add text from the first cut block */
-                       readcutblk(cb, 0);
-                       add(at, &tmpblk.c[cb->start]);
-               }
-       }
-
-       /* Reporting... */
-       rptlines = markline(mark[27]) - markline(at);
-       rptlabel = "pasted";
-
-       /* return the mark at the beginning/end of inserted text */
-       if (retend)
-       {
-               return mark[27] - 1L;
-       }
-       return at;
-}
-
-
-
-
-#ifndef NO_AT
-
-/* This function copies characters from a cut buffer into a string.
- * It returns the number of characters in the cut buffer.  If the cut
- * buffer is too large to fit in the string (i.e. if cb2str() returns
- * a number >= size) then the characters will not have been copied.
- * It returns 0 if the cut buffer is empty, and -1 for invalid cut buffers.
- */
-int cb2str(name, buf, size)
-       int     name;   /* the name of a cut-buffer to get: a-z only! */
-       char    *buf;   /* where to put the string */
-       unsigned size;  /* size of buf */
-{
-       REG struct cutbuf       *cb;
-       REG char                *src;
-       REG char                *dest;
-
-       /* decide which cut buffer to use */
-       if (name >= 'a' && name <= 'z')
-       {
-               cb = &named[name - 'a'];
-       }
-       else
-       {
-               return -1;
-       }
-
-       /* if the buffer is empty, return 0 */
-       if (cb->nblks == 0)
-       {
-               return 0;
-       }
-
-       /* !!! if not a single-block cut, then fail */
-       if (cb->nblks != 1)
-       {
-               return size;
-       }
-
-       /* if too big, return the size now, without doing anything */
-       if (cb->end - cb->start >= size)
-       {
-               return cb->end - cb->start;
-       }
-
-       /* get the block */
-       readcutblk(cb, 0);
-
-       /* isolate the string within that blk */
-       if (cb->start == 0)
-       {
-               tmpblk.c[cb->end] = '\0';
-       }
-       else
-       {
-               for (dest = tmpblk.c, src = dest + cb->start; src < tmpblk.c + cb->end; )
-               {
-                       *dest++ = *src++;
-               }
-               *dest = '\0';
-       }
-
-       /* copy the string into the buffer */
-       if (buf != tmpblk.c)
-       {
-               strcpy(buf, tmpblk.c);
-       }
-
-       /* return the length */
-       return cb->end - cb->start;
-}
-#endif
diff --git a/commands/elvis/elvprsv.c b/commands/elvis/elvprsv.c
deleted file mode 100644 (file)
index f5ee575..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* elvprsv.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the portable sources for the "elvprsv" program.
- * "Elvprsv" is run by Elvis when Elvis is about to die.  It is also
- * run when the computer boots up.  It is not intended to be run directly
- * by the user, ever.
- *
- * Basically, this program does the following four things:
- *    - It extracts the text from the temporary file, and places the text in
- *     a file in the /usr/preserve directory.
- *    - It adds a line to the /usr/preserve/Index file, describing the file
- *     that it just preserved.
- *    - It removes the temporary file.
- *    -        It sends mail to the owner of the file, saying that the file was
- *     preserved, and how it can be recovered.
- *
- * The /usr/preserve/Index file is a log file that contains one line for each
- * file that has ever been preserved.  Each line of this file describes one
- * preserved file.  The first word on the line is the name of the file that
- * contains the preserved text.  The second word is the full pathname of the
- * file that was being edited; for anonymous buffers, this is the directory
- * name plus "/foo".
- *
- * If elvprsv's first argument (after the command name) starts with a hyphen,
- * then the characters after the hyphen are used as a description of when
- * the editor went away.  This is optional.
- *
- * The remaining arguments are all the names of temporary files that are
- * to be preserved.  For example, on a UNIX system, the /etc/rc file might
- * invoke it this way:
- *
- *     elvprsv "-the system went down" /tmp/elv_*.*
- *
- * This file contains only the portable parts of the preserve program.
- * It must #include a system-specific file.  The system-specific file is
- * expected to define the following functions:
- *
- *     char *ownername(char *filename) - returns name of person who owns file
- *
- *     void mail(char *user, char *name, char *when)
- *                                     - tell user that file was preserved
- */
-
-#include <stdio.h>
-#include "config.h"
-#include "vi.h"
-
-#if AMIGA
-BLK tmpblk;
-#error AMIGA here DEBUG
-# include "amiwild.c"
-# include "amiprsv.c"
-#endif
-
-#if OSK
-# undef sprintf
-#endif
-
-#if ANY_UNIX || OSK
-# include "prsvunix.c"
-#endif
-
-#if MSDOS || TOS
-# include "prsvdos.c"
-# define WILDCARD_NO_MAIN
-# include "wildcard.c"
-#endif
-
-
-BLK    buf;
-BLK    hdr;
-BLK    name;
-int    rewrite_now;    /* boolean: should we send text directly to orig file? */
-
-
-
-/* This function preserves a single file, and announces its success/failure
- * via an e-mail message.
- */
-void preserve(tname, when)
-       char    *tname;         /* name of a temp file to be preserved */
-       char    *when;          /* description of when the editor died */
-{
-       int     infd;           /* fd used for reading from the temp file */
-       FILE    *outfp;         /* fp used for writing to the recovery file */
-       FILE    *index;         /* fp used for appending to index file */
-       char    outname[100];   /* the name of the recovery file */
-       char    *user;          /* name of the owner of the temp file */
-#if AMIGA
-       char    *prsvdir;
-#endif
-       int     i;
-
-       /* open the temp file */
-       infd = open(tname, O_RDONLY|O_BINARY);
-       if (infd < 0)
-       {
-               /* if we can't open the file, then we should assume that
-                * the filename contains wildcard characters that weren't
-                * expanded... and also assume that they weren't expanded
-                * because there are no files that need to be preserved.
-                * THEREFORE... we should silently ignore it.
-                * (Or loudly ignore it if the user was using -R)
-                */
-               if (rewrite_now)
-               {
-                       perror(tname);
-               }
-               return;
-       }
-
-       /* read the header and name from the file */
-       if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
-        || read(infd, name.c, BLKSIZE) != BLKSIZE)
-       {
-               /* something wrong with the file - sorry */
-               fprintf(stderr, "%s: trucated header blocks\n", tname);
-               close(infd);
-               return;
-       }
-
-       /* If the filename block contains an empty string, then Elvis was
-        * only keeping the temp file around because it contained some text
-        * that was needed for a named cut buffer.  The user doesn't care
-        * about that kind of temp file, so we should silently delete it.
-        */
-       if (name.c[0] == '\0' && name.c[1] == '\177')
-       {
-               close(infd);
-               unlink(tname);
-               return;
-       }
-
-       if (rewrite_now)
-       {
-               /* we don't need to open the index file */
-               index = (FILE *)0;
-
-               /* make sure we can read every block! */
-               for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
-               {
-                       lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
-                       if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
-                       {
-                               /* messed up header */
-                               fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
-                               close(infd);
-                               return;
-                       }
-               }
-
-               /* open the user's file for writing */
-               outfp = fopen(name.c, "w");
-               if (!outfp)
-               {
-                       perror(name.c);
-                       close(infd);
-                       return;
-               }
-       }
-       else
-       {
-               /* open/create the index file */
-               index = fopen(PRSVINDEX, "a");
-               if (!index)
-               {
-                       perror(PRSVINDEX);
-                       exit(1);
-               }
-
-               /* create the recovery file in the PRESVDIR directory */
-#if AMIGA
-               prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
-               if (*prsvdir == '/' || *prsvdir == ':')
-               {
-                       sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
-               }
-               else
-#endif
-               sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
-               outfp = fopen(outname, "w");
-               if (!outfp)
-               {
-                       perror(outname);
-                       close(infd);
-                       fclose(index);
-                       return;
-               }
-       }
-
-       /* write the text of the file out to the recovery file */
-       for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
-       {
-               lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
-               if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
-               {
-                       /* messed up header */
-                       fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
-                       fclose(outfp);
-                       close(infd);
-                       if (index)
-                       {
-                               fclose(index);
-                       }
-                       unlink(outname);
-                       return;
-               }
-               fputs(buf.c, outfp);
-       }
-
-       /* add a line to the index file */
-       if (index)
-       {
-               fprintf(index, "%s %s\n", outname, name.c);
-       }
-
-       /* close everything */
-       close(infd);
-       fclose(outfp);
-       if (index)
-       {
-               fclose(index);
-       }
-
-       /* Are we doing this due to something more frightening than just
-        * a ":preserve" command?
-        */
-       if (*when)
-       {
-               /* send a mail message */
-               mail(ownername(tname), name.c, when);
-
-               /* remove the temp file -- the editor has died already */
-               unlink(tname);
-       }
-}
-
-main(argc, argv)
-       int     argc;
-       char    **argv;
-{
-       int     i;
-       char    *when = "the editor went away";
-
-#if MSDOS || TOS
-       /* expand any wildcards in the command line */
-       argv = wildexpand(&argc, argv);
-#endif
-
-       /* do we have a "when" argument? */
-       i = 1;
-       if (argc >= i + 1 && !strcmp(argv[i], "-R"))
-       {
-               rewrite_now = 1;
-               when = "";
-               i++;
-#if ANY_UNIX
-               setuid(geteuid());
-#endif
-       }
-#if OSK
-       else
-       {
-               setuid(0);
-       }
-#endif
-       if (argc >= i + 1 && argv[i][0] == '-')
-       {
-               when = argv[i] + 1;
-               i++;
-       }
-
-       /* preserve everything we're supposed to */
-       while (i < argc)
-       {
-               preserve(argv[i], when);
-               i++;
-       }
-}
diff --git a/commands/elvis/elvrec.c b/commands/elvis/elvrec.c
deleted file mode 100644 (file)
index 4e9c389..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/* elvrec.c */
-
-/* This file contains the file recovery program */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-#include <stdio.h>
-#include "config.h"
-#include "vi.h"
-#include <sys/stat.h>
-
-void recover(basename, outname)
-       char    *basename;      /* the name of the file to recover */
-       char    *outname;       /* the name of the file to write to */
-{
-       char    pathname[500];  /* full pathname of the file to recover */
-       char    line[600];      /* a line from the /usr/preserve/Index file */
-       int     ch;             /* a character from the text being recovered */
-       FILE    *from;          /* the /usr/preserve file, or /usr/preserve/Index */
-       FILE    *to;            /* the user's text file */
-       char    *ptr;
-       struct stat st;
-#if OSK
-       int             uid;
-#endif
-
-       /* convert basename to a full pathname */
-       if (basename)
-       {
-#ifndef CRUNCH
-# if MSDOS || TOS
-               if (!basename[0] || basename[1] != ':')
-# else
-               if (basename[0] != SLASH)
-# endif
-               {
-                       ptr = getcwd(pathname, sizeof pathname);
-                       if (ptr != pathname)
-                       {
-                               strcpy(pathname, ptr);
-                       }
-                       ptr = pathname + strlen(pathname);
-                       *ptr++ = SLASH;
-                       strcpy(ptr, basename);
-               }
-               else
-#endif
-               {
-                       strcpy(pathname, basename);
-               }
-       }
-
-#if OSK
-       uid = getuid();
-       if(setuid(0))
-               exit(_errmsg(errno, "Can't set uid\n"));
-#endif
-       /* scan the /usr/preserve/Index file, for the *oldest* unrecovered
-        * version of this file.
-        */
-       from = fopen(PRSVINDEX, "r");
-       while (from && fgets(line, sizeof line, from))
-       {
-               /* strip off the newline from the end of the string */
-               line[strlen(line) - 1] = '\0';
-
-               /* parse the line into a "preserve" name and a "text" name */
-               for (ptr = line; *ptr != ' '; ptr++)
-               {
-               }
-               *ptr++ = '\0';
-
-               /* If the "preserve" file is missing, then ignore this line
-                * because it describes a file that has already been recovered.
-                */
-               if (stat(line, &st) < 0)
-               {
-                       continue;
-               }
-
-               /* are we looking for a specific file? */
-               if (basename)
-               {
-                       /* quit if we found it */
-                       if (!strcmp(ptr, pathname))
-                       {
-                               break;
-                       }
-               }
-               else
-               {
-                       /* list this file as "available for recovery" */
-                       puts(ptr);
-               }
-       }
-
-       /* file not found? */
-       if (!basename || !from || feof(from))
-       {
-               if (from != NULL) fclose(from);
-               if (basename)
-               {
-                       fprintf(stderr, "%s: no recovered file has that exact name\n", pathname);
-               }
-               return;
-       }
-       if (from != NULL) fclose(from);
-
-       /* copy the recovered text back into the user's file... */
-
-       /* open the /usr/preserve file for reading */
-       from = fopen(line, "r");
-       if (!from)
-       {
-               perror(line);
-               exit(2);
-       }
-
-#if ANY_UNIX
-       /* Be careful about user-id.  We want to be running under the user's
-        * real id when we open/create the user's text file... but we want
-        * to be superuser when we delete the /usr/preserve file.  For UNIX,
-        * we accomplish this by deleting the /usr/preserve file *now*,
-        * when it is open but before we've read it.  Then we revert to the
-        * user's real id.
-        */
-       unlink(line);
-       setuid(getuid());
-#endif
-#if OSK
-       setuid(uid);
-#endif
-
-       if (outname == NULL) return;
-
-       /* open the user's file for writing */
-       to = fopen(outname, "w");
-       if (!to)
-       {
-               perror(ptr);
-               exit(2);
-       }
-
-       /* copy the text */
-       while ((ch = getc(from)) != EOF)
-       {
-               putc(ch, to);
-       }
-
-#if !ANY_UNIX
-#if OSK
-       fclose(from);
-       setuid(0);
-#endif
-       /* delete the /usr/preserve file */
-       unlink(line);
-#if OSK
-       setuid(uid);
-#endif
-#endif
-}
-
-main(argc, argv)
-       int     argc;
-       char    **argv;
-{
-       /* check arguments */
-       if (argc > 3)
-       {
-               fprintf(stderr, "usage: %s [preserved_file [recovery_file]]\n", argv[0]);
-               exit(1);
-       }
-
-       /* recover the requested file, or list recoverable files */
-       if (argc == 3)
-       {
-               /* recover the file, but write it to a different filename */
-               recover (argv[1], argv[2]);
-       }
-       else if (argc == 2)
-       {
-               /* recover the file */
-               recover(argv[1], argv[1]);
-       }
-       else
-       {
-               /* list the recoverable files */
-               recover((char *)0, (char *)0);
-       }
-
-       /* success! */
-       exit(0);
-}
diff --git a/commands/elvis/ex.c b/commands/elvis/ex.c
deleted file mode 100644 (file)
index 064e662..0000000
+++ /dev/null
@@ -1,722 +0,0 @@
-/* ex.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the code for reading ex commands. */
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-
-/* This data type is used to describe the possible argument combinations */
-typedef short ARGT;
-#define FROM   1               /* allow a linespec */
-#define        TO      2               /* allow a second linespec */
-#define BANG   4               /* allow a ! after the command name */
-#define EXTRA  8               /* allow extra args after command name */
-#define XFILE  16              /* expand wildcards in extra part */
-#define NOSPC  32              /* no spaces allowed in the extra part */
-#define        DFLALL  64              /* default file range is 1,$ */
-#define DFLNONE        128             /* no default file range */
-#define NODFL  256             /* do not default to the current file name */
-#define EXRCOK 512             /* can be in a .exrc file */
-#define NL     1024            /* if mode!=MODE_EX, then write a newline first */
-#define PLUS   2048            /* allow a line number, as in ":e +32 foo" */
-#define ZERO   4096            /* allow 0 to be given as a line number */
-#define NOBAR  8192            /* treat following '|' chars as normal */
-#define FILES  (XFILE + EXTRA) /* multiple extra files allowed */
-#define WORD1  (EXTRA + NOSPC) /* one extra word allowed */
-#define FILE1  (FILES + NOSPC) /* 1 file allowed, defaults to current file */
-#define NAMEDF (FILE1 + NODFL) /* 1 file allowed, defaults to "" */
-#define NAMEDFS        (FILES + NODFL) /* multiple files allowed, default is "" */
-#define RANGE  (FROM + TO)     /* range of linespecs allowed */
-#define NONE   0               /* no args allowed at all */
-
-/* This array maps ex command names to command codes. The order in which
- * command names are listed below is significant -- ambiguous abbreviations
- * are always resolved to be the first possible match.  (e.g. "r" is taken
- * to mean "read", not "rewind", because "read" comes before "rewind")
- */
-static struct
-{
-       char    *name;  /* name of the command */
-       CMD     code;   /* enum code of the command */
-       void    (*fn)();/* function which executes the command */
-       ARGT    argt;   /* command line arguments permitted/needed/used */
-}
-       cmdnames[] =
-{   /* cmd name        cmd code        function        arguments */
-       {"append",      CMD_APPEND,     cmd_append,     FROM+ZERO+BANG  },
-#ifdef DEBUG
-       {"bug",         CMD_DEBUG,      cmd_debug,      RANGE+BANG+EXTRA+NL},
-#endif
-       {"change",      CMD_CHANGE,     cmd_append,     RANGE+BANG      },
-       {"delete",      CMD_DELETE,     cmd_delete,     RANGE+WORD1     },
-       {"edit",        CMD_EDIT,       cmd_edit,       BANG+FILE1+PLUS },
-       {"file",        CMD_FILE,       cmd_file,       NAMEDF          },
-       {"global",      CMD_GLOBAL,     cmd_global,     RANGE+BANG+EXTRA+DFLALL+NOBAR},
-       {"insert",      CMD_INSERT,     cmd_append,     FROM+BANG       },
-       {"join",        CMD_INSERT,     cmd_join,       RANGE+BANG      },
-       {"k",           CMD_MARK,       cmd_mark,       FROM+WORD1      },
-       {"list",        CMD_LIST,       cmd_print,      RANGE+NL        },
-       {"move",        CMD_MOVE,       cmd_move,       RANGE+EXTRA     },
-       {"next",        CMD_NEXT,       cmd_next,       BANG+NAMEDFS    },
-       {"Next",        CMD_PREVIOUS,   cmd_next,       BANG            },
-       {"print",       CMD_PRINT,      cmd_print,      RANGE+NL        },
-       {"quit",        CMD_QUIT,       cmd_xit,        BANG            },
-       {"read",        CMD_READ,       cmd_read,       FROM+ZERO+NAMEDF},
-       {"substitute",  CMD_SUBSTITUTE, cmd_substitute, RANGE+EXTRA     },
-       {"to",          CMD_COPY,       cmd_move,       RANGE+EXTRA     },
-       {"undo",        CMD_UNDO,       cmd_undo,       NONE            },
-       {"vglobal",     CMD_VGLOBAL,    cmd_global,     RANGE+EXTRA+DFLALL+NOBAR},
-       {"write",       CMD_WRITE,      cmd_write,      RANGE+BANG+FILE1+DFLALL},
-       {"xit",         CMD_XIT,        cmd_xit,        BANG+NL         },
-       {"yank",        CMD_YANK,       cmd_delete,     RANGE+WORD1     },
-
-       {"!",           CMD_BANG,       cmd_shell,      EXRCOK+RANGE+NAMEDFS+DFLNONE+NL+NOBAR},
-       {"#",           CMD_NUMBER,     cmd_print,      RANGE+NL        },
-       {"<",           CMD_SHIFTL,     cmd_shift,      RANGE           },
-       {">",           CMD_SHIFTR,     cmd_shift,      RANGE           },
-       {"=",           CMD_EQUAL,      cmd_file,       RANGE           },
-       {"&",           CMD_SUBAGAIN,   cmd_substitute, RANGE           },
-#ifndef NO_AT
-       {"@",           CMD_AT,         cmd_at,         EXTRA           },
-#endif
-
-#ifndef NO_ABBR
-       {"abbreviate",  CMD_ABBR,       cmd_map,        EXRCOK+BANG+EXTRA},
-#endif
-       {"args",        CMD_ARGS,       cmd_args,       EXRCOK+NAMEDFS  },
-#ifndef NO_ERRLIST
-       {"cc",          CMD_CC,         cmd_make,       BANG+FILES      },
-#endif
-       {"cd",          CMD_CD,         cmd_cd,         EXRCOK+BANG+NAMEDF},
-       {"copy",        CMD_COPY,       cmd_move,       RANGE+EXTRA     },
-#ifndef NO_DIGRAPH
-       {"digraph",     CMD_DIGRAPH,    cmd_digraph,    EXRCOK+BANG+EXTRA},
-#endif
-#ifndef NO_ERRLIST
-       {"errlist",     CMD_ERRLIST,    cmd_errlist,    BANG+NAMEDF     },
-#endif
-       {"ex",          CMD_EDIT,       cmd_edit,       BANG+FILE1      },
-       {"mark",        CMD_MARK,       cmd_mark,       FROM+WORD1      },
-#ifndef NO_MKEXRC
-       {"mkexrc",      CMD_MKEXRC,     cmd_mkexrc,     NAMEDF          },
-#endif
-       {"number",      CMD_NUMBER,     cmd_print,      RANGE+NL        },
-       {"put",         CMD_PUT,        cmd_put,        FROM+ZERO+WORD1 },
-       {"set",         CMD_SET,        cmd_set,        EXRCOK+EXTRA    },
-       {"shell",       CMD_SHELL,      cmd_shell,      NL              },
-       {"source",      CMD_SOURCE,     cmd_source,     EXRCOK+NAMEDF   },
-#ifdef SIGTSTP
-       {"stop",        CMD_STOP,       cmd_suspend,    NONE            },
-#endif
-       {"tag",         CMD_TAG,        cmd_tag,        BANG+WORD1      },
-       {"version",     CMD_VERSION,    cmd_version,    EXRCOK+NONE     },
-       {"visual",      CMD_VISUAL,     cmd_edit,       BANG+NAMEDF     },
-       {"wq",          CMD_WQUIT,      cmd_xit,        NL              },
-
-#ifdef DEBUG
-       {"debug",       CMD_DEBUG,      cmd_debug,      RANGE+BANG+EXTRA+NL},
-       {"validate",    CMD_VALIDATE,   cmd_validate,   BANG+NL         },
-#endif
-       {"chdir",       CMD_CD,         cmd_cd,         EXRCOK+BANG+NAMEDF},
-#ifndef NO_COLOR
-       {"color",       CMD_COLOR,      cmd_color,      EXRCOK+EXTRA    },
-#endif
-#ifndef NO_ERRLIST
-       {"make",        CMD_MAKE,       cmd_make,       BANG+NAMEDFS    },
-#endif
-       {"map",         CMD_MAP,        cmd_map,        EXRCOK+BANG+EXTRA},
-       {"previous",    CMD_PREVIOUS,   cmd_next,       BANG            },
-       {"rewind",      CMD_REWIND,     cmd_next,       BANG            },
-#ifdef SIGTSTP
-       {"suspend",     CMD_SUSPEND,    cmd_suspend,    NONE            },
-#endif
-       {"unmap",       CMD_UNMAP,      cmd_map,        EXRCOK+BANG+EXTRA},
-#ifndef NO_ABBR
-       {"unabbreviate",CMD_UNABBR,     cmd_map,        EXRCOK+WORD1    },
-#endif
-
-       {(char *)0}
-};
-
-
-/* This function parses a search pattern - given a pointer to a / or ?,
- * it replaces the ending / or ? with a \0, and returns a pointer to the
- * stuff that came after the pattern.
- */
-char   *parseptrn(ptrn)
-       REG char        *ptrn;
-{
-       REG char        *scan;
-
-       for (scan = ptrn + 1;
-            *scan && *scan != *ptrn;
-            scan++)
-       {
-               /* allow backslashed versions of / and ? in the pattern */
-               if (*scan == '\\' && scan[1] != '\0')
-               {
-                       scan++;
-               }
-       }
-       if (*scan)
-       {
-               *scan++ = '\0';
-       }
-
-       return scan;
-}
-
-
-/* This function parses a line specifier for ex commands */
-char *linespec(s, markptr)
-       REG char        *s;             /* start of the line specifier */
-       MARK            *markptr;       /* where to store the mark's value */
-{
-       long            num;
-       REG char        *t;
-
-       /* parse each ;-delimited clause of this linespec */
-       do
-       {
-               /* skip an initial ';', if any */
-               if (*s == ';')
-               {
-                       s++;
-               }
-
-               /* skip leading spaces */
-               while (isspace(*s))
-               {
-                       s++;
-               }
-
-               /* dot means current position */
-               if (*s == '.')
-               {
-                       s++;
-                       *markptr = cursor;
-               }
-               /* '$' means the last line */
-               else if (*s == '$')
-               {
-                       s++;
-                       *markptr = MARK_LAST;
-               }
-               /* digit means an absolute line number */
-               else if (isdigit(*s))
-               {
-                       for (num = 0; isdigit(*s); s++)
-                       {
-                               num = num * 10 + *s - '0';
-                       }
-                       *markptr = MARK_AT_LINE(num);
-               }
-               /* appostrophe means go to a set mark */
-               else if (*s == '\'')
-               {
-                       s++;
-                       *markptr = m_tomark(cursor, 1L, (int)*s);
-                       s++;
-               }
-               /* slash means do a search */
-               else if (*s == '/' || *s == '?')
-               {
-                       /* put a '\0' at the end of the search pattern */
-                       t = parseptrn(s);
-
-                       /* search for the pattern */
-                       *markptr &= ~(BLKSIZE - 1);
-                       if (*s == '/')
-                       {
-                               pfetch(markline(*markptr));
-                               if (plen > 0)
-                                       *markptr += plen - 1;
-                               *markptr = m_fsrch(*markptr, s);
-                       }
-                       else
-                       {
-                               *markptr = m_bsrch(*markptr, s);
-                       }
-
-                       /* adjust command string pointer */
-                       s = t;
-               }
-
-               /* if linespec was faulty, quit now */
-               if (!*markptr)
-               {
-                       return s;
-               }
-
-               /* maybe add an offset */
-               t = s;
-               if (*t == '-' || *t == '+')
-               {
-                       s++;
-                       for (num = 0; isdigit(*s); s++)
-                       {
-                               num = num * 10 + *s - '0';
-                       }
-                       if (num == 0)
-                       {
-                               num = 1;
-                       }
-                       *markptr = m_updnto(*markptr, num, *t);
-               }
-       } while (*s == ';' || *s == '+' || *s == '-');
-
-       /* protect against invalid line numbers */
-       num = markline(*markptr);
-       if (num < 1L || num > nlines)
-       {
-               msg("Invalid line number -- must be from 1 to %ld", nlines);
-               *markptr = MARK_UNSET;
-       }
-
-       return s;
-}
-
-
-
-/* This function reads an ex command and executes it. */
-void ex()
-{
-       char            cmdbuf[150];
-       REG int         cmdlen;
-       static long     oldline;
-
-       significant = FALSE;
-       oldline = markline(cursor);
-
-       while (mode == MODE_EX)
-       {
-               /* read a line */
-#ifdef CRUNCH
-               cmdlen = vgets(':', cmdbuf, sizeof(cmdbuf));
-#else
-               cmdlen = vgets(*o_prompt ? ':' : '\0', cmdbuf, sizeof(cmdbuf));
-#endif
-               if (cmdlen < 0)
-               {
-                       return;
-               }
-
-               /* if empty line, assume ".+1" */
-               if (cmdlen == 0)
-               {
-                       strcpy(cmdbuf, ".+1");
-                       qaddch('\r');
-                       clrtoeol();
-               }
-               else
-               {
-                       addch('\n');
-               }
-               refresh();
-
-               /* parse & execute the command */
-               doexcmd(cmdbuf);
-
-               /* handle autoprint */
-               if (significant || markline(cursor) != oldline)
-               {
-                       significant = FALSE;
-                       oldline = markline(cursor);
-                       if (*o_autoprint && mode == MODE_EX)
-                       {
-                               cmd_print(cursor, cursor, CMD_PRINT, FALSE, "");
-                       }
-               }
-       }
-}
-
-void doexcmd(cmdbuf)
-       char            *cmdbuf;        /* string containing an ex command */
-{
-       REG char        *scan;          /* used to scan thru cmdbuf */
-       MARK            frommark;       /* first linespec */
-       MARK            tomark;         /* second linespec */
-       REG int         cmdlen;         /* length of the command name given */
-       CMD             cmd;            /* what command is this? */
-       ARGT            argt;           /* argument types for this command */
-       short           forceit;        /* bang version of a command? */
-       REG int         cmdidx;         /* index of command */
-       REG char        *build;         /* used while copying filenames */
-       int             iswild;         /* boolean: filenames use wildcards? */
-       int             isdfl;          /* using default line ranges? */
-       int             didsub;         /* did we substitute file names for % or # */
-
-       /* ex commands can't be undone via the shift-U command */
-       U_line = 0L;
-
-       /* permit extra colons at the start of the line */
-       for (; *cmdbuf == ':'; cmdbuf++)
-       {
-       }
-
-       /* ignore command lines that start with a double-quote */
-       if (*cmdbuf == '"')
-       {
-               return;
-       }
-       scan = cmdbuf;
-
-       /* parse the line specifier */
-       if (nlines < 1)
-       {
-               /* no file, so don't allow addresses */
-       }
-       else if (*scan == '%')
-       {
-               /* '%' means all lines */
-               frommark = MARK_FIRST;
-               tomark = MARK_LAST;
-               scan++;
-       }
-       else if (*scan == '0')
-       {
-               frommark = tomark = MARK_UNSET;
-               scan++;
-       }
-       else
-       {
-               frommark = cursor;
-               scan = linespec(scan, &frommark);
-               tomark = frommark;
-               if (frommark && *scan == ',')
-               {
-                       scan++;
-                       scan = linespec(scan, &tomark);
-               }
-               if (!tomark)
-               {
-                       /* faulty line spec -- fault already described */
-                       return;
-               }
-               if (frommark > tomark)
-               {
-                       msg("first address exceeds the second");
-                       return;
-               }
-       }
-       isdfl = (scan == cmdbuf);
-
-       /* skip whitespace */
-       while (isspace(*scan))
-       {
-               scan++;
-       }
-
-       /* if no command, then just move the cursor to the mark */
-       if (!*scan)
-       {
-               if (tomark != MARK_UNSET)
-                       cursor = tomark;
-               return;
-       }
-
-       /* figure out how long the command name is */
-       if (!isalpha(*scan))
-       {
-               cmdlen = 1;
-       }
-       else
-       {
-               for (cmdlen = 1;
-                    isalpha(scan[cmdlen]);
-                    cmdlen++)
-               {
-               }
-       }
-
-       /* lookup the command code */
-       for (cmdidx = 0;
-            cmdnames[cmdidx].name && strncmp(scan, cmdnames[cmdidx].name, cmdlen);
-            cmdidx++)
-       {
-       }
-       argt = cmdnames[cmdidx].argt;
-       cmd = cmdnames[cmdidx].code;
-       if (cmd == CMD_NULL)
-       {
-               msg("Unknown command \"%.*s\"", cmdlen, scan);
-               return;
-       }
-
-       /* !!! if the command doesn't have NOBAR set, then replace | with \0 */
-
-       /* if the command ended with a bang, set the forceit flag */
-       scan += cmdlen;
-       if ((argt & BANG) && *scan == '!')
-       {
-               scan++;
-               forceit = 1;
-       }
-       else
-       {
-               forceit = 0;
-       }
-
-       /* skip any more whitespace, to leave scan pointing to arguments */
-       while (isspace(*scan))
-       {
-               scan++;
-       }
-
-       /* a couple of special cases for filenames */
-       if (argt & XFILE)
-       {
-               /* if names were given, process them */
-               if (*scan)
-               {
-                       for (build = tmpblk.c, iswild = didsub = FALSE; *scan; scan++)
-                       {
-                               switch (*scan)
-                               {
-                                 case '\\':
-                                       if (scan[1] == '\\' || scan[1] == '%' || scan[1] == '#')
-                                       {
-                                               *build++ = *++scan;
-                                       }
-                                       else
-                                       {
-                                               *build++ = '\\';
-                                       }
-                                       break;
-
-                                 case '%':
-                                       if (!*origname)
-                                       {
-                                               msg("No filename to substitute for %%");
-                                               return;
-                                       }
-                                       strcpy(build, origname);
-                                       while (*build)
-                                       {
-                                               build++;
-                                       }
-                                       didsub = TRUE;
-                                       break;
-
-                                 case '#':
-                                       if (!*prevorig)
-                                       {
-                                               msg("No filename to substitute for #");
-                                               return;
-                                       }
-                                       strcpy(build, prevorig);
-                                       while (*build)
-                                       {
-                                               build++;
-                                       }
-                                       didsub = TRUE;
-                                       break;
-
-                                 case '*':
-                                 case '?':
-#if !(MSDOS || TOS)
-                                 case '[':
-                                 case '`':
-                                 case '{': /* } */
-                                 case '$':
-                                 case '~':
-#endif
-                                       *build++ = *scan;
-                                       iswild = TRUE;
-                                       break;
-
-                                 default:
-                                       *build++ = *scan;
-                               }
-                       }
-                       *build = '\0';
-
-                       if (cmd == CMD_BANG
-                        || cmd == CMD_READ && tmpblk.c[0] == '!'
-                        || cmd == CMD_WRITE && tmpblk.c[0] == '!')
-                       {
-                               if (didsub)
-                               {
-                                       if (mode != MODE_EX)
-                                       {
-                                               addch('\n');
-                                       }
-                                       addstr(tmpblk.c);
-                                       addch('\n');
-                                       exrefresh();
-                               }
-                       }
-                       else
-                       {
-                               if (iswild && tmpblk.c[0] != '>')
-                               {
-                                       scan = wildcard(tmpblk.c);
-                               }
-                       }
-               }
-               else /* no names given, maybe assume origname */
-               {
-                       if (!(argt & NODFL))
-                       {
-                               strcpy(tmpblk.c, origname);
-                       }
-                       else
-                       {
-                               *tmpblk.c = '\0';
-                       }
-               }
-
-               scan = tmpblk.c;
-       }
-
-       /* bad arguments? */
-       if (!(argt & EXRCOK) && nlines < 1L)
-       {
-               msg("Can't use the \"%s\" command in a %s file", cmdnames[cmdidx].name, EXRC);
-               return;
-       }
-       if (!(argt & (ZERO | EXRCOK)) && frommark == MARK_UNSET)
-       {
-               msg("Can't use address 0 with \"%s\" command.", cmdnames[cmdidx].name);
-               return;
-       }
-       if (!(argt & FROM) && frommark != cursor && nlines >= 1L)
-       {
-               msg("Can't use address with \"%s\" command.", cmdnames[cmdidx].name);
-               return;
-       }
-       if (!(argt & TO) && tomark != frommark && nlines >= 1L)
-       {
-               msg("Can't use a range with \"%s\" command.", cmdnames[cmdidx].name);
-               return;
-       }
-       if (!(argt & EXTRA) && *scan)
-       {
-               msg("Extra characters after \"%s\" command.", cmdnames[cmdidx].name);
-               return;
-       }
-       if ((argt & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!')))
-       {
-               build = scan;
-#ifndef CRUNCH
-               if ((argt & PLUS) && *build == '+')
-               {
-                       while (*build && !isspace(*build))
-                       {
-                               build++;
-                       }
-                       while (*build && isspace(*build))
-                       {
-                               build++;
-                       }
-               }
-#endif /* not CRUNCH */
-               for (; *build; build++)
-               {
-                       if (isspace(*build))
-                       {
-                               msg("Too many %s to \"%s\" command.",
-                                       (argt & XFILE) ? "filenames" : "arguments",
-                                       cmdnames[cmdidx].name);
-                               return;
-                       }
-               }
-       }
-
-       /* some commands have special default ranges */
-       if (isdfl && (argt & DFLALL))
-       {
-               frommark = MARK_FIRST;
-               tomark = MARK_LAST;
-       }
-       else if (isdfl && (argt & DFLNONE))
-       {
-               frommark = tomark = 0L;
-       }
-
-       /* write a newline if called from visual mode */
-       if ((argt & NL) && mode != MODE_EX && !exwrote)
-       {
-               addch('\n');
-               exrefresh();
-       }
-
-       /* act on the command */
-       (*cmdnames[cmdidx].fn)(frommark, tomark, cmd, forceit, scan);
-}
-
-
-/* This function executes EX commands from a file.  It returns 1 normally, or
- * 0 if the file could not be opened for reading.
- */
-int doexrc(filename)
-       char    *filename;      /* name of a ".exrc" file */
-{
-       int     fd;             /* file descriptor */
-       int     len;            /* length of the ".exrc" file */
-
-       /* !!! kludge: we use U_text as the buffer.  This has the side-effect
-        * of interfering with the shift-U visual command.  Disable shift-U.
-        */
-       U_line = 0L;
-
-       /* open the file, read it, and close */
-       fd = open(filename, O_RDONLY);
-       if (fd < 0)
-       {
-               return 0;
-       }
-       len = tread(fd, U_text, BLKSIZE);
-       close(fd);
-
-       /* execute the string */
-       exstring(U_text, len, ctrl('V'));
-
-       return 1;
-}
-
-/* This function executes EX commands from a string.  The commands may be
- * separated by newlines or by | characters.  It also handles quoting.
- * Each individual command is limited to 132 bytes, but the total string
- * may be longer.
- */
-void exstring(buf, len, qchar)
-       char    *buf;   /* the commands to execute */
-       int     len;    /* the length of the string */
-       int     qchar;  /* the quote character -- ^V for file, or \ for kbd */
-{
-       char    single[133];    /* a single command */
-       char    *src, *dest;
-       int     i;
-
-       /* find & do each command */
-       for (src = buf; src < &buf[len]; src++)
-       {
-               /* Copy a single command into single[].  Convert any quoted |
-                * into a normal |, and stop at a newline or unquoted |.
-                */
-               for (dest = single, i = 0;
-                    i < 132 && src < &buf[len] && *src != '\n' && *src != '|';
-                    src++, i++)
-               {
-                       if (src[0] == qchar && src[1] == '|')
-                       {
-                               src++;
-                       }
-                       *dest++ = *src;
-               }
-               *dest = '\0';
-
-               /* do it */
-               doexcmd(single);
-       }
-}
diff --git a/commands/elvis/fmt.c b/commands/elvis/fmt.c
deleted file mode 100644 (file)
index 72fe858..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/* fmt.c */
-
-/* usage: fmt [-width] [files]...
- *
- * Fmt rearrages text in order to make each line have roughly the
- * same width.  Indentation and word spacing is preserved.
- *
- * The default width is 72 characters, but you can override that via -width.
- * If no files are given on the command line, then it reads stdin.
- */
-
-#include <stdio.h>
-
-#ifndef TRUE
-# define TRUE  1
-# define FALSE 0
-#endif
-
-
-
-int    width = 72;     /* the desired line width */
-int    isblank;        /* is the current output line blank? */
-int    indent;         /* width of the indentation */
-char   ind[512];       /* indentation text */
-char   word[1024];     /* word buffer */
-
-/* This function displays a usage message and quits */
-void usage()
-{
-       fprintf(stderr, "usage: fmt [-width] [files]...\n");
-       exit(2);
-}
-
-
-
-/* This function outputs a single word.  It takes care of spacing and the
- * newlines within a paragraph.
- */
-void putword()
-{
-       int             i;              /* index into word[], or whatever */
-       int             ww;             /* width of the word */
-       int             sw;             /* width of spacing after word */
-       static int      psw;            /* space width of previous word */
-       static int      tab;            /* the width of text already written */
-
-
-       /* separate the word and its spacing */
-       for (ww = 0; word[ww] && word[ww] != ' '; ww++)
-       {
-       }
-       sw = strlen(word) - ww;
-       word[ww] = '\0';
-
-       /* if no spacing (that is, the word was at the end of the line) then
-        * assume 1 space unless the last char of the word was punctuation
-        */
-       if (sw == 0)
-       {
-               sw = 1;
-               if (word[ww - 1] == '.' || word[ww - 1] == '?' || word[ww - 1] == '!')
-                       sw = 2;
-       }
-
-       /* if this is the first word on the line... */
-       if (isblank)
-       {
-               /* output the indentation first */
-               fputs(ind, stdout);
-               tab = indent;
-       }
-       else /* text has already been written to this output line */
-       {
-               /* will the word fit on this line? */
-               if (psw + ww + tab <= width)
-               {
-                       /* yes - so write the previous word's spacing */
-                       for (i = 0; i < psw; i++)
-                       {
-                               putchar(' ');
-                       }
-                       tab += psw;
-               }
-               else
-               {
-                       /* no, so write a newline and the indentation */
-                       putchar('\n');
-                       fputs(ind, stdout);
-                       tab = indent;
-               }
-       }
-
-       /* write the word itself */
-       fputs(word, stdout);
-       tab += ww;
-
-       /* remember this word's spacing */
-       psw = sw;
-
-       /* this output line isn't blank anymore. */
-       isblank = FALSE;
-}
-
-
-
-/* This function reformats text. */
-void fmt(in)
-       FILE    *in;            /* the name of the input stream */
-{
-       int     ch;             /* character from input stream */
-       int     prevch;         /* the previous character in the loop */
-       int     i;              /* index into ind[] or word[] */
-       int     inword;         /* boolean: are we between indent & newline? */
-
-
-       /* for each character in the stream... */
-       for (indent = -1, isblank = TRUE, inword = FALSE, i = 0, prevch = '\n';
-            (ch = getc(in)) != EOF;
-            prevch = ch)
-       {
-               /* is this the end of a line? */
-               if (ch == '\n')
-               {
-                       /* if end of last word in the input line */
-                       if (inword)
-                       {
-                               /* if it really is a word */
-                               if (i > 0)
-                               {
-                                       /* output it */
-                                       word[i] = '\0';
-                                       putword();
-                               }
-                       }
-                       else /* blank line in input */
-                       {
-                               /* finish the previous paragraph */
-                               if (!isblank)
-                               {
-                                       putchar('\n');
-                                       isblank = TRUE;
-                               }
-
-                               /* output a blank line */
-                               putchar('\n');
-                       }
-
-                       /* continue with next input line... */
-                       indent = -1;
-                       i = 0;
-                       inword = FALSE;
-                       continue;
-               }
-
-               /* if we're expecting indentation now... */
-               if (indent < 0)
-               {
-                       /* if this is part of the indentation... */
-                       if (ch == ' ' || ch == '\t')
-                       {
-                               /* remember it */
-                               ind[i++] = ch;
-                       }
-                       else /* end of indentation */
-                       {
-                               /* mark the end of the indentation string */
-                               ind[i] = '\0';
-
-                               /* calculate the width of the indentation */
-                               for (i = indent = 0; ind[i]; i++)
-                               {
-                                       if (ind[i] == '\t')
-                                               indent = (indent | 7) + 1;
-                                       else
-                                               indent++;
-                               }
-
-                               /* reset the word index */
-                               i = 0;
-
-                               /* reprocess that last character */
-                               ungetc(ch, in);
-                       }
-
-                       /* continue in the for-loop */
-                       continue;
-               }
-
-               /* if we get here, we're either in a word or in the space
-                * after a word.
-                */
-               inword = TRUE;
-
-               /* is this the start of a new word? */
-               if (ch != ' ' && prevch == ' ')
-               {
-                       /* yes!  output the previous word */
-                       word[i] = '\0';
-                       putword();
-
-                       /* reset `i' to the start of the word[] buffer */
-                       i = 0;
-               }
-               word[i++] = ch;
-       }
-
-       /* if necessary, write a final newline */
-       if (!isblank)
-       {
-               putchar('\n');
-               isblank = TRUE;
-       }
-}
-
-
-
-
-
-int main(argc, argv)
-       int     argc;
-       char    **argv;
-{
-       FILE    *in;    /* an input stream */
-       int     error;  /* if non-zero, then an error occurred */
-       int     i;
-
-
-       /* handle the -width flag, if given */
-       if (argc > 1 && argv[1][0] == '-')
-       {
-               width = atoi(argv[1] + 1);
-               if (width <= 0)
-               {
-                       usage();
-               }
-               argc--;
-               argv++;
-       }
-
-       /* if no filenames given, then process stdin */
-       if (argc == 1)
-       {
-               fmt(stdin);
-       }
-       else /* one or more filenames given */
-       {
-               for (error = 0, i = 1; i < argc; i++)
-               {
-                       in = fopen(argv[i], "r");
-                       if (!in)
-                       {
-                               perror(argv[i]);
-                               error = 3;
-                       }
-                       else
-                       {
-                               fmt(in);
-                               fclose(in);
-                       }
-               }
-       }
-
-       /* exit, possibly indicating an error */
-       exit(error);
-       /*NOTREACHED*/
-}
diff --git a/commands/elvis/input.c b/commands/elvis/input.c
deleted file mode 100644 (file)
index 563f643..0000000
+++ /dev/null
@@ -1,852 +0,0 @@
-/* input.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the input() function, which implements vi's INPUT mode.
- * It also contains the code that supports digraphs.
- */
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-
-
-#ifndef NO_DIGRAPH
-static struct _DIG
-{
-       struct _DIG     *next;
-       char            key1;
-       char            key2;
-       char            dig;
-       char            save;
-} *digs;
-
-char digraph(key1, key2)
-       char    key1;   /* the underlying character */
-       char    key2;   /* the second character */
-{
-       int             newkey;
-       REG struct _DIG *dp;
-
-       /* if digraphs are disabled, then just return the new char */
-       if (!*o_digraph)
-       {
-               return key2;
-       }
-
-       /* remember the new key, so we can return it if this isn't a digraph */
-       newkey = key2;
-
-       /* sort key1 and key2, so that their original order won't matter */
-       if (key1 > key2)
-       {
-               key2 = key1;
-               key1 = newkey;
-       }
-
-       /* scan through the digraph chart */
-       for (dp = digs;
-            dp && (dp->key1 != key1 || dp->key2 != key2);
-            dp = dp->next)
-       {
-       }
-
-       /* if this combination isn't in there, just use the new key */
-       if (!dp)
-       {
-               return newkey;
-       }
-
-       /* else use the digraph key */
-       return dp->dig;
-}
-
-/* this function lists or defines digraphs */
-void do_digraph(bang, extra)
-       int     bang;
-       char    extra[];
-{
-       int             dig;
-       REG struct _DIG *dp;
-       struct _DIG     *prev;
-       static int      user_defined = FALSE; /* boolean: are all later digraphs user-defined? */
-       char            listbuf[8];
-
-       /* if "extra" is NULL, then we've reached the end of the built-ins */
-       if (!extra)
-       {
-               user_defined = TRUE;
-               return;
-       }
-
-       /* if no args, then display the existing digraphs */
-       if (*extra < ' ')
-       {
-               listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' ';
-               listbuf[7] = '\0';
-               for (dig = 0, dp = digs; dp; dp = dp->next)
-               {
-                       if (dp->save || bang)
-                       {
-                               dig += 7;
-                               if (dig >= COLS)
-                               {
-                                       addch('\n');
-                                       exrefresh();
-                                       dig = 7;
-                               }
-                               listbuf[3] = dp->key1;
-                               listbuf[4] = dp->key2;
-                               listbuf[6] = dp->dig;
-                               qaddstr(listbuf);
-                       }
-               }
-               addch('\n');
-               exrefresh();
-               return;
-       }
-
-       /* make sure we have at least two characters */
-       if (!extra[1])
-       {
-               msg("Digraphs must be composed of two characters");
-               return;
-       }
-
-       /* sort key1 and key2, so that their original order won't matter */
-       if (extra[0] > extra[1])
-       {
-               dig = extra[0];
-               extra[0] = extra[1];
-               extra[1] = dig;
-       }
-
-       /* locate the new digraph character */
-       for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++)
-       {
-       }
-       dig = extra[dig];
-       if (!bang && dig)
-       {
-               dig |= 0x80;
-       }
-
-       /* search for the digraph */
-       for (prev = (struct _DIG *)0, dp = digs;
-            dp && (dp->key1 != extra[0] || dp->key2 != extra[1]);
-            prev = dp, dp = dp->next)
-       {
-       }
-
-       /* deleting the digraph? */
-       if (!dig)
-       {
-               if (!dp)
-               {
-#ifndef CRUNCH
-                       msg("%c%c not a digraph", extra[0], extra[1]);
-#endif
-                       return;
-               }
-               if (prev)
-                       prev->next = dp->next;
-               else
-                       digs = dp->next;
-               free(dp);
-               return;
-       }
-
-       /* if necessary, create a new digraph struct for the new digraph */
-       if (dig && !dp)
-       {
-               dp = (struct _DIG *)malloc(sizeof *dp);
-               if (!dp)
-               {
-                       msg("Out of space in the digraph table");
-                       return;
-               }
-               if (prev)
-                       prev->next = dp;
-               else
-                       digs = dp;
-               dp->next = (struct _DIG *)0;
-       }
-
-       /* assign it the new digraph value */
-       dp->key1 = extra[0];
-       dp->key2 = extra[1];
-       dp->dig = dig;
-       dp->save = user_defined;
-}
-
-# ifndef NO_MKEXRC
-void savedigs(fd)
-       int             fd;
-{
-       static char     buf[] = "digraph! XX Y\n";
-       REG struct _DIG *dp;
-
-       for (dp = digs; dp; dp = dp->next)
-       {
-               if (dp->save)
-               {
-                       buf[9] = dp->key1;
-                       buf[10] = dp->key2;
-                       buf[12] = dp->dig;
-                       write(fd, buf, (unsigned)14);
-               }
-       }
-}
-# endif
-#endif
-
-
-/* This function allows the user to replace an existing (possibly zero-length)
- * chunk of text with typed-in text.  It returns the MARK of the last character
- * that the user typed in.
- */
-MARK input(from, to, when, above)
-       MARK    from;   /* where to start inserting text */
-       MARK    to;     /* extent of text to delete */
-       int     when;   /* either WHEN_VIINP or WHEN_VIREP */
-       int     above;  /* boolean: take indentation from lower line? */
-{
-       char    key[2]; /* key char followed by '\0' char */
-       char    *build; /* used in building a newline+indent string */
-       char    *scan;  /* used while looking at the indent chars of a line */
-       MARK    m;      /* some place in the text */
-#ifndef NO_EXTENSIONS
-       int     quit = FALSE;   /* boolean: are we exiting after this? */
-       int     inchg;  /* boolean: have we done a "beforedo()" yet? */
-#endif
-
-#ifdef DEBUG
-       /* if "from" and "to" are reversed, complain */
-       if (from > to)
-       {
-               msg("ERROR: input(%ld:%d, %ld:%d)",
-                       markline(from), markidx(from),
-                       markline(to), markidx(to));
-               return MARK_UNSET;
-       }
-#endif
-
-       key[1] = 0;
-
-       /* if we're replacing text with new text, save the old stuff */
-       /* (Alas, there is no easy way to save text for replace mode) */
-       if (from != to)
-       {
-               cut(from, to);
-       }
-
-       /* if doing a dot command, then reuse the previous text */
-       if (doingdot)
-       {
-               ChangeText
-               {
-                       /* delete the text that's there now */
-                       if (from != to)
-                       {
-                               delete(from, to);
-                       }
-
-                       /* insert the previous text */
-                       cutname('.');
-                       cursor = paste(from, FALSE, TRUE) + 1L;
-               }
-       }
-       else /* interactive version */
-       {
-               /* assume that whoever called this already did a beforedo() */
-#ifndef NO_EXTENSIONS
-               inchg = TRUE;
-#endif
-
-               /* if doing a change within the line... */
-               if (from != to && markline(from) == markline(to))
-               {
-                       /* mark the end of the text with a "$" */
-                       change(to - 1, to, "$");
-               }
-               else
-               {
-                       /* delete the old text right off */
-                       if (from != to)
-                       {
-                               delete(from, to);
-                       }
-                       to = from;
-               }
-
-               /* handle autoindent of the first line, maybe */
-               cursor = from;
-               m = (above ? (cursor + BLKSIZE) : (cursor - BLKSIZE));
-               if (*o_autoindent && markidx(m) == 0
-                && markline(m) >= 1L && markline(m) <= nlines)
-               {
-                       /* Only autoindent blank lines. */
-                       pfetch(markline(cursor));
-                       if (plen == 0)
-                       {
-                               /* Okay, we really want to autoindent */
-                               pfetch(markline(m));
-                               for (scan = ptext, build = tmpblk.c;
-                                    *scan == ' ' || *scan == '\t';
-                                    )
-                               {
-                                       *build++ = *scan++;
-                               }
-                               if (build > tmpblk.c)
-                               {
-                                       *build = '\0';
-                                       add(cursor, tmpblk.c);
-                                       cursor += (build - tmpblk.c);
-                                       if (cursor > to)
-                                               to = cursor;
-                               }
-                       }
-               }
-
-               /* repeatedly add characters from the user */
-               for (;;)
-               {
-                       /* Get a character */
-                       redraw(cursor, TRUE);
-#ifdef DEBUG2
-                       msg("cursor=%ld.%d, to=%ld.%d",
-                               markline(cursor), markidx(cursor),
-                               markline(to), markidx(to));
-#endif
-#ifndef NO_ABBR
-                       pfetch(markline(cursor));
-                       build = ptext;
-                       if (pline == markline(from))
-                               build += markidx(from);
-                       for (scan = ptext + markidx(cursor); --scan >= build && isalnum(*scan); )
-                       {
-                       }
-                       scan++;
-                       key[0] = getabkey(when, scan, (int)(ptext + markidx(cursor) - scan));
-#else
-                       key[0] = getkey(when);
-#endif
-#ifndef NO_VISIBLE
-                       if (key[0] != '\0' && V_from != MARK_UNSET)
-                       {
-                               msg("Can't modify text during a selection");
-                               beep();
-                               continue;
-                       }
-#endif
-
-#ifndef NO_EXTENSIONS
-                       if (key[0] == ctrl('O'))
-                       {
-                               if (inchg)
-                               {
-                                       if (cursor < to)
-                                       {
-                                               delete(cursor, to);
-                                               redraw(cursor, TRUE);
-                                       }
-                                       afterdo();
-                                       inchg = FALSE;
-                               }
-                       }
-                       else if (key[0] != ctrl('['))
-                       {
-                               if (!inchg)
-                               {
-                                       beforedo(FALSE);
-                                       inchg = TRUE;
-                               }
-                       }
-#endif
-
-#ifndef CRUNCH
-                       /* if wrapmargin is set & we're past the
-                        * warpmargin, then change the last whitespace
-                        * characters on line into a newline
-                        */
-                       if (*o_wrapmargin != 0)
-                       {
-                               pfetch(markline(cursor));
-                               if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
-                               {
-                                       build = tmpblk.c;
-                                       *build++ = '\n';
-                                       if (*o_autoindent)
-                                       {
-                                               /* figure out indent for next line */
-                                               for (scan = ptext; *scan == ' ' || *scan == '\t'; )
-                                               {
-                                                       *build++ = *scan++;
-                                               }
-                                       }
-                                       *build = '\0';
-
-                                       scan = ptext + plen;
-                                       m = cursor & ~(BLKSIZE - 1);
-                                       while (ptext < scan)
-                                       {
-                                               scan--;
-                                               if (*scan != ' ' && *scan != '\t')
-                                                       continue;
-
-                                               /*break up line, and we do autoindent if needed*/
-                                               change(m + (scan - ptext), m + (scan - ptext) + 1, tmpblk.c);
-                                               cursor = (cursor & ~(BLKSIZE - 1))
-                                                       + BLKSIZE
-                                                       + strlen(tmpblk.c) - 1
-                                                       + plen - (scan - ptext) - 1;
-
-                                               /*remove trailing spaces on previous line*/
-                                               pfetch(markline(m));
-                                               scan = ptext + plen;
-                                               while (ptext < scan)
-                                               {
-                                                       scan--;
-                                                       if (*scan != ' ' && *scan != '\t')
-                                                               break;
-                                               }
-                                               delete(m + (scan-ptext) + 1, m + plen);
-
-                                               break;
-                                       }
-                               }
-                       }
-#endif /* !CRUNCH */
-
-                       /* process it */
-                       switch (*key)
-                       {
-#ifndef NO_EXTENSIONS
-                         case ctrl('O'): /* special movement mapped keys */
-                               *key = getkey(0);
-                               switch (*key)
-                               {
-                                 case 'h':     m = m_left(cursor, 0L);         break;
-                                 case 'j':
-                                 case 'k':     m = m_updnto(cursor, 0L, *key); break;
-                                 case 'l':     m = cursor + 1;                 break;
-                                 case 'B':
-                                 case 'b':     m = m_bword(cursor, 0L, *key);  break;
-                                 case 'W':
-                                 case 'w':     m = m_fword(cursor, 0L, *key, '\0');    break;
-                                 case '^':     m = m_front(cursor, 0L);        break;
-                                 case '$':     m = m_rear(cursor, 0L);         break;
-                                 case ctrl('B'):
-                                 case ctrl('F'):
-                                               m = m_scroll(cursor, 0L, *key); break;
-                                 case 'x':
-#ifndef NO_VISIBLE
-                                               if (V_from)
-                                                       beep();
-                                               else
-#endif
-                                               ChangeText
-                                               {
-                                                       m = v_xchar(cursor, 0L, 'x');
-                                               }
-                                               break;
-                                 case 'i':     m = to = from = cursor;
-                                               when = WHEN_VIINP + WHEN_VIREP - when;
-                                                                               break;
-                                 case 'K':
-                                       pfetch(markline(cursor));
-                                       changes++; /* <- after this, we can alter ptext */
-                                       ptext[markidx(cursor)] = 0;
-                                       for (scan = ptext + markidx(cursor) - 1;
-                                            scan >= ptext && isalnum(*scan);
-                                            scan--)
-                                       {
-                                       }
-                                       scan++;
-                                       m = (*scan ? v_keyword(scan, cursor, 0L) : cursor);
-                                       break;
-
-# ifndef NO_VISIBLE
-                                 case 'v':
-                                 case 'V':
-                                       if (V_from)
-                                               V_from = MARK_UNSET;
-                                       else
-                                               V_from = cursor;
-                                       m = from = to = cursor;
-                                       V_linemd = (*key == 'V');
-                                       break;
-
-                                 case 'd':
-                                 case 'y':
-                                 case '\\':
-                                       /* do nothing if unmarked */
-                                       if (!V_from)
-                                       {
-                                               msg("You must mark the text first");
-                                               beep();
-                                               break;
-                                       }
-
-                                       /* "from" must come before "to" */
-                                       if (V_from < cursor)
-                                       {
-                                               from = V_from;
-                                               to = cursor;
-                                       }
-                                       else
-                                       {
-                                               from = cursor;
-                                               to = V_from;
-                                       }
-
-                                       /* we don't need V_from anymore */
-                                       V_from = MARK_UNSET;
-
-                                       if (V_linemd)
-                                       {
-                                               /* adjust for line mode */
-                                               from &= ~(BLKSIZE - 1);
-                                               to |= (BLKSIZE - 1);
-                                       }
-                                       else
-                                       {
-                                               /* in character mode, we must
-                                                * worry about deleting the newline
-                                                * at the end of the last line
-                                                */
-                                               pfetch(markline(to));
-                                               if (markidx(to) == plen)
-                                                       to |= (BLKSIZE - 1);
-                                       }
-                                       to++;
-
-                                       switch (*key)
-                                       {
-                                         case 'y':
-                                               cut(from, to);
-                                               break;
-
-                                         case 'd':
-                                               ChangeText
-                                               {
-                                                       cut(from, to);
-                                                       delete(from, to);
-                                               }
-                                               cursor = from;
-                                               break;
-
-#ifndef NO_POPUP
-                                         case '\\':
-                                               ChangeText
-                                               {
-                                                       cursor = v_popup(from, to);
-                                               }
-                                               break;
-#endif
-                                       }
-                                       m = from = to = cursor;
-                                       break;
-
-                                 case 'p':
-                                 case 'P':
-                                       V_from = MARK_UNSET;
-                                       ChangeText
-                                       {
-                                               m = from = to = cursor = paste(cursor, (*key == 'p'), FALSE);
-                                       }
-                                       break;
-# endif /* !NO_VISIBLE */
-                                 default:      m = MARK_UNSET;
-                               }
-
-                               /* adjust the moved cursor */
-                               if (m != cursor)
-                               {
-                                       m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0));
-                                       if (*key == '$' || (*key == 'l' && m <= cursor))
-                                       {
-                                               m++;
-                                       }
-                               }
-
-                               /* if the cursor is reasonable, use it */
-                               if (m == MARK_UNSET)
-                               {
-                                       beep();
-                               }
-                               else
-                               {
-                                       from = to = cursor = m;
-                               }
-                               break;
-
-                         case ctrl('Z'):
-                               if (getkey(0) == ctrl('Z'))
-                               {
-                                       quit = TRUE;
-                                       goto BreakBreak;
-                               }
-                               break;
-#endif
-
-                         case ctrl('['):
-                               /* if last line contains only whitespace, then remove whitespace */
-                               if (*o_autoindent)
-                               {
-                                       pfetch(markline(cursor));
-                                       for (scan = ptext; isspace(*scan); scan++)
-                                       {
-                                       }
-                                       if (scan > ptext && !*scan)
-                                       {
-                                               cursor &= ~(BLKSIZE - 1L);
-                                               if (to < cursor + plen)
-                                               {
-                                                       to = cursor + plen;
-                                               }
-                                       }
-                               }
-                               goto BreakBreak;
-
-                         case ctrl('U'):
-                               if (markline(cursor) == markline(from))
-                               {
-                                       cursor = from;
-                               }
-                               else
-                               {
-                                       cursor &= ~(BLKSIZE - 1);
-                               }
-                               break;
-
-                         case ctrl('D'):
-                         case ctrl('T'):
-                               if (to > cursor)
-                               {
-                                       delete(cursor, to);
-                               }
-                               mark[27] = cursor;
-                               cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
-                               if (mark[27])
-                               {
-                                       cursor = mark[27];
-                               }
-                               else
-                               {
-                                       cursor = m_front(cursor, 0L);
-                               }
-                               to = cursor;
-                               break;
-
-                         case '\b':
-                               if (cursor <= from)
-                               {
-                                       beep();
-                               }
-                               else if (markidx(cursor) == 0)
-                               {
-                                       cursor -= BLKSIZE;
-                                       pfetch(markline(cursor));
-                                       cursor += plen;
-                               }
-                               else
-                               {
-                                       cursor--;
-                               }
-                               break;
-
-                         case ctrl('W'):
-                               m = m_bword(cursor, 1L, 'b');
-                               if (markline(m) == markline(cursor) && m >= from)
-                               {
-                                       cursor = m;
-                                       if (from > cursor)
-                                       {
-                                               from = cursor;
-                                       }
-                               }
-                               else
-                               {
-                                       beep();
-                               }
-                               break;
-
-                         case '\n':
-#if OSK
-                         case '\l':
-#else                            
-                         case '\r':
-#endif
-                               build = tmpblk.c;
-                               *build++ = '\n';
-                               if (*o_autoindent)
-                               {
-                                       /* figure out indent for next line */
-                                       pfetch(markline(cursor));
-                                       for (scan = ptext; *scan == ' ' || *scan == '\t'; )
-                                       {
-                                               *build++ = *scan++;
-                                       }
-
-                                       /* remove indent from this line, if blank */
-                                       if ((scan - ptext) >= markidx(cursor) && plen > 0)
-                                       {
-                                               to = cursor &= ~(BLKSIZE - 1);
-                                               delete(cursor, cursor + plen);
-                                       }
-                               }
-                               *build = 0;
-                               if (cursor >= to && when != WHEN_VIREP)
-                               {
-                                       add(cursor, tmpblk.c);
-                               }
-                               else
-                               {
-                                       change(cursor, to, tmpblk.c);
-                               }
-                               redraw(cursor, TRUE);
-                               to = cursor = (cursor & ~(BLKSIZE - 1))
-                                               + BLKSIZE
-                                               + (int)(build - tmpblk.c) - 1;
-                               break;
-
-                         case ctrl('A'):
-                         case ctrl('P'):
-                               if (cursor < to)
-                               {
-                                       delete(cursor, to);
-                               }
-                               if (*key == ctrl('A'))
-                               {
-                                       cutname('.');
-                               }
-                               to = cursor = paste(cursor, FALSE, TRUE) + 1L;
-                               break;
-
-                         case ctrl('V'):
-                               if (cursor >= to && when != WHEN_VIREP)
-                               {
-                                       add(cursor, "^");
-                               }
-                               else
-                               {
-                                       change(cursor, to, "^");
-                                       to = cursor + 1;
-                               }
-                               redraw(cursor, TRUE);
-                               *key = getkey(0);
-                               if (*key == '\n')
-                               {
-                                       /* '\n' too hard to handle */
-#if OSK
-                                       *key = '\l';
-#else
-                                       *key = '\r';
-#endif
-                               }
-                               change(cursor, cursor + 1, key);
-                               cursor++;
-                               if (cursor > to)
-                               {
-                                       to = cursor;
-                               }
-                               break;
-
-                         case ctrl('L'):
-                         case ctrl('R'):
-                               redraw(MARK_UNSET, FALSE);
-                               break;
-
-                         default:
-                               if (cursor >= to && when != WHEN_VIREP)
-                               {
-                                       add(cursor, key);
-                                       cursor++;
-                                       to = cursor;
-                               }
-                               else
-                               {
-                                       pfetch(markline(cursor));
-                                       if (markidx(cursor) == plen)
-                                       {
-                                               add(cursor, key);
-                                       }
-                                       else
-                                       {
-#ifndef NO_DIGRAPH
-                                               *key = digraph(ptext[markidx(cursor)], *key);
-#endif
-                                               change(cursor, cursor + 1, key);
-                                       }
-                                       cursor++;
-                               }
-#ifndef NO_SHOWMATCH
-                               /* show matching "({[" if necessary */
-                               if (*o_showmatch && strchr(")}]", *key))
-                               {
-                                       redraw(cursor, TRUE);
-                                       m = m_match(cursor - 1, 0L);
-                                       if (markline(m) >= topline
-                                        && markline(m) <= botline)
-                                       {
-                                               redraw(m, TRUE);
-                                               refresh();
-                                               sleep(1);
-                                       }
-                               }
-#endif
-                       } /* end switch(*key) */
-               } /* end for(;;) */
-BreakBreak:;
-               /* delete any excess characters */
-               if (cursor < to)
-               {
-#ifndef NO_EXTENSIONS
-                       /* if we aren't in the middle of a change, start one! */
-                       if (!inchg)
-                       {
-                               beforedo(FALSE);
-                               inchg = TRUE;
-                       }
-#endif
-                       delete(cursor, to);
-               }
-
-       } /* end if doingdot else */
-
-       /* put the new text into a cut buffer for possible reuse */
-       if (!doingdot)
-       {
-               blksync();
-               cutname('.');
-               cut(from, cursor);
-       }
-
-       /* move to last char that we inputted, unless it was newline */
-       if (markidx(cursor) != 0)
-       {
-               cursor--;
-       }
-       redraw(cursor, FALSE);
-
-#ifndef NO_EXTENSIONS
-       if (quit)
-       {
-               /* if this is a nested "do", then cut it short */
-               abortdo();
-
-               /* exit, unless we can't write out the file */
-               cursor = v_xit(cursor, 0L, 'Z');
-       }
-#endif
-
-       rptlines = 0L;
-       return cursor;
-}
diff --git a/commands/elvis/main.c b/commands/elvis/main.c
deleted file mode 100644 (file)
index 0198b8b..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/* main.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the main() function of vi */
-
-/* HACK! bcc needs to disable use of precompiled headers for this file,
-   or else command line args will not be passed to elvis */
-#if __BORLANDC__
-#include "borland.h"
-#endif
-
-#include "config.h"
-#include <setjmp.h>
-#include "vi.h"
-
-extern         trapint(); /* defined below */
-extern char    *getenv();
-jmp_buf                jmpenv;
-
-#ifndef NO_DIGRAPH
-static init_digraphs();
-#endif
-
-/*---------------------------------------------------------------------*/
-
-#if AMIGA
-# include "amiwild.c"
-main (argc, argv)
-#else
-# if VMS
-#  include "vmswild.c"
-main (argc, argv)
-# else
-int main(argc, argv)
-# endif
-#endif
-       int     argc;
-       char    *argv[];
-{
-       int     i;
-       char    *cmd = (char *)0;
-       char    *err = (char *)0;
-       char    *str;
-       char    *tag = (char *)0;
-
-       /* set mode to MODE_VI or MODE_EX depending on program name */
-       switch (argv[0][strlen(argv[0]) - 1])
-       {
-         case 'x':                     /* "ex" */
-               mode = MODE_EX;
-               break;
-
-         case 'w':                     /* "view" */
-               mode = MODE_VI;
-               *o_readonly = TRUE;
-               break;
-#ifndef NO_EXTENSIONS
-         case 't':                     /* "edit" or "input" */
-               mode = MODE_VI;
-               *o_inputmode = TRUE;
-               break;
-#endif
-         default:                      /* "vi" or "elvis" */
-               mode = MODE_VI;
-       }
-
-#ifndef DEBUG
-# ifdef        SIGQUIT
-       /* normally, we ignore SIGQUIT.  SIGINT is trapped later */
-       signal(SIGQUIT, SIG_IGN);
-# endif
-#endif
-
-       /* temporarily ignore SIGINT */
-       signal(SIGINT, SIG_IGN);
-
-       /* start curses */
-       initscr();
-       cbreak();
-       noecho();
-       scrollok(stdscr, TRUE);
-
-       /* arrange for deadly signals to be caught */
-# ifdef SIGHUP
-       signal(SIGHUP, (void(*)()) deathtrap);
-# endif
-# ifndef DEBUG
-#  ifdef SIGILL
-       signal(SIGILL, (void(*)()) deathtrap);
-#  endif
-#  ifdef SIGBUS
-       signal(SIGBUS, (void(*)()) deathtrap);
-#  endif
-#  ifdef SIGSEGV
-       signal(SIGSEGV, (void(*)()) deathtrap);
-#  endif
-#  ifdef SIGSYS
-       signal(SIGSYS, (void(*)()) deathtrap);
-#  endif
-# endif /* !DEBUG */
-# ifdef SIGPIPE
-       signal(SIGPIPE, (void(*)()) deathtrap);
-# endif
-# ifdef SIGTERM
-       signal(SIGTERM, (void(*)()) deathtrap);
-# endif
-# ifdef SIGUSR1
-       signal(SIGUSR1, (void(*)()) deathtrap);
-# endif
-# ifdef SIGUSR2
-       signal(SIGUSR2, (void(*)()) deathtrap);
-# endif
-
-       /* initialize the options - must be done after initscr(), so that
-        * we can alter LINES and COLS if necessary.
-        */
-       initopts();
-
-       /* map the arrow keys.  The KU,KD,KL,and KR variables correspond to
-        * the :ku=: (etc.) termcap capabilities.  The variables are defined
-        * as part of the curses package.
-        */
-       if (has_KU) mapkey(has_KU, "k",    WHEN_VICMD|WHEN_INMV, "<Up>");
-       if (has_KD) mapkey(has_KD, "j",    WHEN_VICMD|WHEN_INMV, "<Down>");
-       if (has_KL) mapkey(has_KL, "h",    WHEN_VICMD|WHEN_INMV, "<Left>");
-       if (has_KR) mapkey(has_KR, "l",    WHEN_VICMD|WHEN_INMV, "<Right>");
-       if (has_HM) mapkey(has_HM, "^",    WHEN_VICMD|WHEN_INMV, "<Home>");
-       if (has_EN) mapkey(has_EN, "$",    WHEN_VICMD|WHEN_INMV, "<End>");
-       if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
-       if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
-       if (has_KI) mapkey(has_KI, "i",    WHEN_VICMD|WHEN_INMV, "<Insert>");
-#if MSDOS
-# if RAINBOW
-       if (!strcmp("rainbow", o_term))
-       {
-               mapkey("\033[1~",  "/",         WHEN_VICMD,             "<Find>");
-               mapkey("\033[3~",  "x",         WHEN_VICMD|WHEN_INMV,   "<Remove>");
-               mapkey("\033[4~",  "v",         WHEN_VICMD|WHEN_INMV,   "<Select>");
-               mapkey("\033[17~", ":sh\n",     WHEN_VICMD,             "<Intrpt>");
-               mapkey("\033[19~", ":q\n",      WHEN_VICMD,             "<Cancel>");
-               mapkey("\033[21~", "ZZ",        WHEN_VICMD,             "<Exit>");
-               mapkey("\033[26~", "V",         WHEN_VICMD|WHEN_INMV,   "<AddlOp>");
-               mapkey("\033[28~", "\\",        WHEN_VICMD|WHEN_INMV,   "<Help>");
-               mapkey("\033[29~", "K",         WHEN_VICMD|WHEN_INMV,   "<Do>");
-       }
-       else
-# endif /* RAINBOW */
-       {
-               mapkey("#S", "x", WHEN_VICMD|WHEN_INMV, "<Delete>");
-               mapkey("#s", "B", WHEN_VICMD|WHEN_INMV, "^<Left>");
-               mapkey("#t", "W", WHEN_VICMD|WHEN_INMV, "^<Right>");
-       }
-#else /* not MSDOS */
-# if COHERENT
-       mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
-# else
-#if AMIGA
-       mapkey("\233?~", "\\",  WHEN_VICMD|WHEN_INMV,   "<Help>");
-#endif
-
-       if (ERASEKEY != '\177')
-       {
-               mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
-       }
-# endif
-#endif
-
-#ifndef NO_DIGRAPH
-       init_digraphs();
-#endif /* NO_DIGRAPH */
-
-       /* process any flags */
-       for (i = 1; i < argc && *argv[i] == '-'; i++)
-       {
-               switch (argv[i][1])
-               {
-                 case 'R':     /* readonly */
-                       *o_readonly = TRUE;
-                       break;
-
-                 case 'L':
-                 case 'r':     /* recover */
-                       msg("Use the `elvrec` program to recover lost files");
-                       endmsgs();
-                       refresh();
-                       endwin();
-                       exit(0);
-                       break;
-
-                 case 't':     /* tag */
-                       if (argv[i][2])
-                       {
-                               tag = argv[i] + 2;
-                       }
-                       else
-                       {
-                               tag = argv[++i];
-                       }
-                       break;
-
-                 case 'v':     /* vi mode */
-                       mode = MODE_VI;
-                       break;
-
-                 case 'e':     /* ex mode */
-                       mode = MODE_EX;
-                       break;
-#ifndef NO_EXTENSIONS
-                 case 'i':     /* input mode */
-                       *o_inputmode = TRUE;
-                       break;
-#endif
-#ifndef NO_ERRLIST
-                 case 'm':     /* use "errlist" as the errlist */
-                       if (argv[i][2])
-                       {
-                               err = argv[i] + 2;
-                       }
-                       else if (i + 1 < argc)
-                       {
-                               err = argv[++i];
-                       }
-                       else
-                       {
-                               err = "";
-                       }
-                       break;
-#endif
-#ifndef CRUNCH
-                case 'c':      /* run the following command, later */
-                       if (argv[i][2])
-                       {
-                               cmd = argv[i] + 2;
-                       }
-                       else
-                       {
-                               cmd = argv[++i];
-                       }
-                       break;
-
-                 case 'w':     /* set the window size */
-                       if (argv[i][2])
-                       {
-                               *o_window = atoi(argv[i] + 2);
-                               wset = TRUE;
-                       }
-                       else
-                       {
-                               *o_window = atoi(argv[++i]);
-                               wset = TRUE;
-                       }
-                       break;
-#endif
-                 default:
-                       msg("Ignoring unknown flag \"%s\"", argv[i]);
-               }
-       }
-
-       /* if we were given an initial ex command, save it... */
-       if (i < argc && *argv[i] == '+')
-       {
-               if (argv[i][1])
-               {
-                       cmd = argv[i++] + 1;
-               }
-               else
-               {
-                       cmd = "$"; /* "vi + file" means start at EOF */
-                       i++;
-               }
-       }
-
-       /* the remaining args are file names. */
-       if (i < argc)
-       {
-               strcpy(args, argv[i]);
-               while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
-               {
-                       strcat(args, " ");
-                       strcat(args, argv[i]);
-               }
-#if MSDOS || TOS
-               /* expand wildcard characters, if necessary */
-               if (strchr(args, '*') || strchr(args, '?'))
-               {
-                       strcpy(args, wildcard(args));
-               }
-#endif
-               strcpy(tmpblk.c, args);
-               cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
-       }
-       else
-       {
-               /* empty args list */
-               args[0] = '\0';
-               nargs = 1;
-               argno = -1;
-       }
-
-       /* perform the .exrc files and EXINIT environment variable */
-#ifdef SYSEXRC
-       doexrc(SYSEXRC);
-#endif
-#ifdef HMEXRC
-       str = getenv("HOME");
-       if (str && *str)
-       {
-               strcpy(tmpblk.c, str);
-               str = tmpblk.c + strlen(tmpblk.c);
-#if !VMS
-# if AMIGA     /* Don't SLASH a device. "Elvis:.exrc" */
-               if (str[-1] != COLON && str[-1] != SLASH)
-# else
-               if (str[-1] != SLASH)
-# endif
-               {
-                       *str++ = SLASH;
-               }
-#endif
-               strcpy(str, HMEXRC);
-               doexrc(tmpblk.c);
-       }
-#endif
-#ifndef CRUNCH
-       if (*o_exrc)
-#endif
-       {
-               doexrc(EXRC);
-       }
-#ifdef EXINIT
-       str = getenv(EXINIT);
-       if (str)
-       {
-               exstring(str, strlen(str), ctrl('V'));
-       }
-#endif
-
-       /* search for a tag (or an error) now, if desired */
-       blkinit();
-       if (tag)
-       {
-               cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
-       }
-#ifndef NO_ERRLIST
-       else if (err)
-       {
-               cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
-       }
-#endif
-
-       /* if no tag/err, or tag failed, then start with first arg */
-       if (tmpfd < 0)
-       {
-               /* start with first arg */
-               cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
-
-               /* pretend to do something, just to force a recoverable
-                * version of the file out to disk
-                */
-               ChangeText
-               {
-               }
-               clrflag(file, MODIFIED);
-       }
-
-       /* now we do the immediate ex command that we noticed before */
-       if (cmd)
-       {
-               doexcmd(cmd);
-       }
-
-       /* repeatedly call ex() or vi() (depending on the mode) until the
-        * mode is set to MODE_QUIT
-        */
-       while (mode != MODE_QUIT)
-       {
-               if (setjmp(jmpenv))
-               {
-                       /* Maybe we just aborted a change? */
-                       abortdo();
-               }
-               signal(SIGINT, (void(*)()) trapint);
-
-               switch (mode)
-               {
-                 case MODE_VI:
-                       vi();
-                       break;
-
-                 case MODE_EX:
-                       ex();
-                       break;
-#ifdef DEBUG
-                 default:
-                       msg("mode = %d?", mode);
-                       mode = MODE_QUIT;
-#endif
-               }
-       }
-
-       /* free up the cut buffers */
-       cutend();
-
-       /* end curses */
-#ifndef        NO_CURSORSHAPE
-       if (has_CQ)
-               do_CQ();
-#endif
-       endmsgs();
-       move(LINES - 1, 0);
-       clrtoeol();
-       refresh();
-       endwin();
-
-       exit(0);
-       /*NOTREACHED*/
-}
-
-
-/*ARGSUSED*/
-int trapint(signo)
-       int     signo;
-{
-       beep();
-       resume_curses(FALSE);
-       abortdo();
-#if OSK
-       sigmask(-1);
-#endif
-       signal(signo, (void (*)())trapint);
-       doingglobal = FALSE;
-
-       longjmp(jmpenv, 1);
-
-       return 0;
-}
-
-
-
-#ifndef NO_DIGRAPH
-
-/* This stuff us used to build the default digraphs table. */
-static char    digtable[][4] =
-{
-# ifdef CS_IBMPC
-       "C,\200",       "u\"\1",        "e'\2",         "a^\3",
-       "a\"\4",        "a`\5",         "a@\6",         "c,\7",
-       "e^\10",        "e\"\211",      "e`\12",        "i\"\13",
-       "i^\14",        "i`\15",        "A\"\16",       "A@\17",
-       "E'\20",        "ae\21",        "AE\22",        "o^\23",
-       "o\"\24",       "o`\25",        "u^\26",        "u`\27",
-       "y\"\30",       "O\"\31",       "U\"\32",       "a'\240",
-       "i'!",          "o'\"",         "u'#",          "n~$",
-       "N~%",          "a-&",          "o-'",          "~?(",
-       "~!-",          "\"<.",         "\">/",
-#  ifdef CS_SPECIAL
-       "2/+",          "4/,",          "^+;",          "^q<",
-       "^c=",          "^r>",          "^t?",          "pp]",
-       "^^^",          "oo_",          "*a`",          "*ba",
-       "*pc",          "*Sd",          "*se",          "*uf",
-       "*tg",          "*Ph",          "*Ti",          "*Oj",
-       "*dk",          "*Hl",          "*hm",          "*En",
-       "*No",          "eqp",          "pmq",          "ger",
-       "les",          "*It",          "*iu",          "*/v",
-       "*=w",          "sq{",          "^n|",          "^2}",
-       "^3~",          "^_\377",
-#  endif /* CS_SPECIAL */
-# endif /* CS_IBMPC */
-# ifdef CS_LATIN1
-       "~!!",          "a-*",          "\">+",         "o-:",
-       "\"<>",         "~??",
-
-       "A`@",          "A'A",          "A^B",          "A~C",
-       "A\"D",         "A@E",          "AEF",          "C,G",
-       "E`H",          "E'I",          "E^J",          "E\"K",
-       "I`L",          "I'M",          "I^N",          "I\"O",
-       "-DP",          "N~Q",          "O`R",          "O'S",
-       "O^T",          "O~U",          "O\"V",         "O/X",
-       "U`Y",          "U'Z",          "U^[",          "U\"\\",
-       "Y'_",
-
-       "a``",          "a'a",          "a^b",          "a~c",
-       "a\"d",         "a@e",          "aef",          "c,g",
-       "e`h",          "e'i",          "e^j",          "e\"k",
-       "i`l",          "i'm",          "i^n",          "i\"o",
-       "-dp",          "n~q",          "o`r",          "o's",
-       "o^t",          "o~u",          "o\"v",         "o/x",
-       "u`y",          "u'z",          "u^{",          "u\"|",
-       "y'~",
-# endif /* CS_LATIN1 */
-       ""
-};
-
-static init_digraphs()
-{
-       int     i;
-
-       for (i = 0; *digtable[i]; i++)
-       {
-               do_digraph(FALSE, digtable[i]);
-       }
-       do_digraph(FALSE, (char *)0);
-       return 0;
-}
-#endif /* NO_DIGRAPH */
diff --git a/commands/elvis/misc.c b/commands/elvis/misc.c
deleted file mode 100644 (file)
index c9e0f68..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* misc.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains functions which didn't seem happy anywhere else */
-
-#include "config.h"
-#include "vi.h"
-
-
-/* find a particular line & return a pointer to a copy of its text */
-char *fetchline(line)
-       long    line;   /* line number of the line to fetch */
-{
-       int             i;
-       REG char        *scan;  /* used to search for the line in a BLK */
-       long            l;      /* line number counter */
-       static BLK      buf;    /* holds ONLY the selected line (as string) */
-       REG char        *cpy;   /* used while copying the line */
-       static long     nextline;       /* }  These four variables are used */
-       static long     chglevel;       /*  } to implement a shortcut when  */
-       static char     *nextscan;      /*  } consecutive lines are fetched */
-       static long     nextlnum;       /* }                                */
-
-       /* can we do a shortcut? */
-       if (changes == chglevel && line == nextline)
-       {
-               scan = nextscan;
-       }
-       else
-       {
-               /* scan lnum[] to determine which block its in */
-               for (i = 1; line > lnum[i]; i++)
-               {
-               }
-               nextlnum = lnum[i];
-
-               /* fetch text of the block containing that line */
-               scan = blkget(i)->c;
-
-               /* find the line in the block */
-               for (l = lnum[i - 1]; ++l < line; )
-               {
-                       while (*scan++ != '\n')
-                       {
-                       }
-               }
-       }
-
-       /* copy it into a block by itself, with no newline */
-       for (cpy = buf.c; *scan != '\n'; )
-       {
-               *cpy++ = *scan++;
-       }
-       *cpy = '\0';
-
-       /* maybe speed up the next call to fetchline() ? */
-       if (line < nextlnum)
-       {
-               nextline = line + 1;
-               chglevel = changes;
-               nextscan = scan + 1;
-       }
-       else
-       {
-               nextline = 0;
-       }
-
-       /* Calls to fetchline() interfere with calls to pfetch().  Make sure
-        * that pfetch() resets itself on its next invocation.
-        */
-       pchgs = 0L;
-
-       /* Return a pointer to the line's text */
-       return buf.c;
-}
-
-
-/* error message from the regexp code */
-void regerror(txt)
-       char    *txt;   /* an error message */
-{
-       msg("RE error: %s", txt);
-}
-
-/* This function is equivelent to the pfetch() macro */
-void   pfetch(l)
-       long    l;      /* line number of line to fetch */
-{
-       if(l != pline || changes != pchgs)
-       {
-               pline = (l);
-               ptext = fetchline(pline);
-               plen = strlen(ptext);
-               pchgs = changes;
-       }
-}
diff --git a/commands/elvis/modify.c b/commands/elvis/modify.c
deleted file mode 100644 (file)
index af79146..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-/* modify.c */
-
-/* This file contains the low-level file modification functions:
- *     delete(frommark, tomark)        - removes line or portions of lines
- *     add(frommark, text)             - inserts new text
- *     change(frommark, tomark, text)  - delete, then add
- */
-
-#include "config.h"
-#include "vi.h"
-
-#ifdef DEBUG2
-# include <stdio.h>
-static FILE *dbg;
-
-/*VARARGS1*/
-debout(msg, arg1, arg2, arg3, arg4, arg5)
-       char    *msg, *arg1, *arg2, *arg3, *arg4, *arg5;
-{
-       if (!dbg)
-       {
-               dbg = fopen("debug.out", "w");
-               if (!dbg)
-                       return;
-               setbuf(dbg, (FILE *)0);
-       }
-       fprintf(dbg, msg, arg1, arg2, arg3, arg4, arg5);
-}
-#endif /* DEBUG2 */
-
-/* delete a range of text from the file */
-void delete(frommark, tomark)
-       MARK            frommark;       /* first char to be deleted */
-       MARK            tomark;         /* AFTER last char to be deleted */
-{
-       int             i;              /* used to move thru logical blocks */
-       REG char        *scan;          /* used to scan thru text of the blk */
-       REG char        *cpy;           /* used when copying chars */
-       BLK             *blk;           /* a text block */
-       long            l;              /* a line number */
-       MARK            m;              /* a traveling version of frommark */
-
-#ifdef DEBUG2
-       debout("delete(%ld.%d, %ld.%d)\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark));
-#endif
-
-       /* if not deleting anything, quit now */
-       if (frommark == tomark)
-       {
-               return;
-       }
-
-       /* This is a change */
-       changes++;
-       significant = TRUE;
-
-       /* supply clues to the redraw module */
-       redrawrange(markline(frommark), markline(tomark), markline(frommark));
-
-       /* adjust marks 'a through 'z and '' as needed */
-       l = markline(tomark);
-       for (i = 0; i < NMARKS; i++)
-       {
-               if (mark[i] < frommark)
-               {
-                       continue;
-               }
-               else if (mark[i] < tomark)
-               {
-                       mark[i] = MARK_UNSET;
-               }
-               else if (markline(mark[i]) == l)
-               {
-                       if (markline(frommark) == l)
-                       {
-                               mark[i] -= markidx(tomark) - markidx(frommark);
-                       }
-                       else
-                       {
-                               mark[i] -= markidx(tomark);
-                       }
-               }
-               else
-               {
-                       mark[i] -= MARK_AT_LINE(l - markline(frommark));
-               }
-       }
-
-       /* Reporting... */
-       if (markidx(frommark) == 0 && markidx(tomark) == 0)
-       {
-               rptlines = markline(tomark) - markline(frommark);
-               rptlabel = "deleted";
-       }
-
-       /* find the block containing frommark */
-       l = markline(frommark);
-       for (i = 1; lnum[i] < l; i++)
-       {
-       }
-
-       /* process each affected block... */
-       for (m = frommark;
-            m < tomark && lnum[i] < INFINITY;
-            m = MARK_AT_LINE(lnum[i - 1] + 1))
-       {
-               /* fetch the block */
-               blk = blkget(i);
-
-               /* find the mark in the block */
-               scan = blk->c;
-               for (l = markline(m) - lnum[i - 1] - 1; l > 0; l--)
-               {
-                       while (*scan++ != '\n')
-                       {
-                       }
-               }
-               scan += markidx(m);
-
-               /* figure out where the changes to this block end */
-               if (markline(tomark) > lnum[i])
-               {
-                       cpy = blk->c + BLKSIZE;
-               }
-               else if (markline(tomark) == markline(m))
-               {
-                       cpy = scan - markidx(m) + markidx(tomark);
-               }
-               else
-               {
-                       cpy = scan;
-                       for (l = markline(tomark) - markline(m);
-                            l > 0;
-                            l--)
-                       {
-                               while (*cpy++ != '\n')
-                               {
-                               }
-                       }
-                       cpy += markidx(tomark);
-               }
-
-               /* delete the stuff by moving chars within this block */
-               while (cpy < blk->c + BLKSIZE)
-               {
-                       *scan++ = *cpy++;
-               }
-               while (scan < blk->c + BLKSIZE)
-               {
-                       *scan++ = '\0';
-               }
-
-               /* adjust tomark to allow for lines deleted from this block */
-               tomark -= MARK_AT_LINE(lnum[i] + 1 - markline(m));
-
-               /* if this block isn't empty now, then advance i */
-               if (*blk->c)
-               {
-                       i++;
-               }
-
-               /* the buffer has changed.  Update hdr and lnum. */
-               blkdirty(blk);
-       }
-
-       /* must have at least 1 line */
-       if (nlines == 0)
-       {
-               blk = blkadd(1);
-               blk->c[0] = '\n';
-               blkdirty(blk);
-               cursor = MARK_FIRST;
-       }
-}
-
-
-/* add some text at a specific place in the file */
-void add(atmark, newtext)
-       MARK            atmark;         /* where to insert the new text */
-       char            *newtext;       /* NUL-terminated string to insert */
-{
-       REG char        *scan;          /* used to move through string */
-       REG char        *build;         /* used while copying chars */
-       int             addlines;       /* number of lines we're adding */
-       int             lastpart;       /* size of last partial line */
-       BLK             *blk;           /* the block to be modified */
-       int             blkno;          /* the logical block# of (*blk) */
-       REG char        *newptr;        /* where new text starts in blk */
-       BLK             buf;            /* holds chars from orig blk */
-       BLK             linebuf;        /* holds part of line that didn't fit */
-       BLK             *following;     /* the BLK following the last BLK */
-       int             i;
-       long            l;
-
-#ifdef DEBUG2
-       debout("add(%ld.%d, \"%s\")\n", markline(atmark), markidx(atmark), newtext);
-#endif
-#ifdef lint
-       buf.c[0] = 0;
-#endif
-       /* if not adding anything, return now */
-       if (!*newtext)
-       {
-               return;
-       }
-
-       /* This is a change */
-       changes++;
-       significant = TRUE;
-
-       /* count the number of lines in the new text */
-       for (scan = newtext, lastpart = addlines = 0; *scan; )
-       {
-               if (*scan++ == '\n')
-               {
-                       addlines++;
-                       lastpart = 0;
-               }
-               else
-               {
-                       lastpart++;
-               }
-       }
-
-       /* Reporting... */
-       if (lastpart == 0 && markidx(atmark) == 0)
-       {
-               rptlines = addlines;
-               rptlabel = "added";
-       }
-
-       /* extract the line# from atmark */
-       l = markline(atmark);
-
-       /* supply clues to the redraw module */
-       if ((markidx(atmark) == 0 && lastpart == 0) || addlines == 0)
-       {
-               redrawrange(l, l, l + addlines);
-       }
-       else
-       {
-               /* make sure the last line gets redrawn -- it was
-                * split, so its appearance has changed
-                */
-               redrawrange(l, l + 1L, l + addlines + 1L);
-       }
-
-       /* adjust marks 'a through 'z and '' as needed */
-       for (i = 0; i < NMARKS; i++)
-       {
-               if (mark[i] < atmark)
-               {
-                       /* earlier line, or earlier in same line: no change */
-                       continue;
-               }
-               else if (markline(mark[i]) > l)
-               {
-                       /* later line: move down a whole number of lines */
-                       mark[i] += MARK_AT_LINE(addlines);
-               }
-               else
-               {
-                       /* later in same line */
-                       if (addlines > 0)
-                       {
-                               /* multi-line add, which split this line:
-                                * move down, and possibly left or right,
-                                * depending on where the split was and how
-                                * much text was inserted after the last \n
-                                */
-                               mark[i] += MARK_AT_LINE(addlines) + lastpart - markidx(atmark);
-                       }
-                       else
-                       {
-                               /* totally within this line: move right */
-                               mark[i] += lastpart;
-                       }
-               }
-       }
-
-       /* get the block to be modified */
-       for (blkno = 1; lnum[blkno] < l && lnum[blkno + 1] < INFINITY; blkno++)
-       {
-       }
-       blk = blkget(blkno);
-       buf = *blk;
-
-       /* figure out where the new text starts */
-       for (newptr = buf.c, l = markline(atmark) - lnum[blkno - 1] - 1;
-            l > 0;
-            l--)
-       {
-               while (*newptr++ != '\n')
-               {
-               }
-       }
-       newptr += markidx(atmark);
-
-       /* keep start of old block */
-       build = blk->c + (int)(newptr - buf.c);
-
-       /* fill this block (or blocks) from the newtext string */
-       while (*newtext)
-       {
-               while (*newtext && build < blk->c + BLKSIZE - 1)
-               {
-                       *build++ = *newtext++;
-               }
-               if (*newtext)
-               {
-                       /* save the excess */
-                       for (scan = linebuf.c + BLKSIZE;
-                            build > blk->c && build[-1] != '\n';
-                            )
-                       {
-                               *--scan = *--build;
-                       }
-
-                       /* write the block */
-                       while (build < blk->c + BLKSIZE)
-                       {
-                               *build++ = '\0';
-                       }
-                       blkdirty(blk);
-
-                       /* add another block */
-                       blkno++;
-                       blk = blkadd(blkno);
-
-                       /* copy in the excess from last time */
-                       for (build = blk->c; scan < linebuf.c + BLKSIZE; )
-                       {
-                               *build++ = *scan++;
-                       }
-               }
-       }
-
-       /* fill this block(s) from remainder of orig block */
-       while (newptr < buf.c + BLKSIZE && *newptr)
-       {
-               while (newptr < buf.c + BLKSIZE
-                   && *newptr
-                   && build < blk->c + BLKSIZE - 1)
-               {
-                       *build++ = *newptr++;
-               }
-               if (newptr < buf.c + BLKSIZE && *newptr)
-               {
-                       /* save the excess */
-                       for (scan = linebuf.c + BLKSIZE;
-                            build > blk->c && build[-1] != '\n';
-                            )
-                       {
-                               *--scan = *--build;
-                       }
-
-                       /* write the block */
-                       while (build < blk->c + BLKSIZE)
-                       {
-                               *build++ = '\0';
-                       }
-                       blkdirty(blk);
-
-                       /* add another block */
-                       blkno++;
-                       blk = blkadd(blkno);
-
-                       /* copy in the excess from last time */
-                       for (build = blk->c; scan < linebuf.c + BLKSIZE; )
-                       {
-                               *build++ = *scan++;
-                       }
-               }
-       }
-
-       /* see if we can combine our last block with the following block */
-       if (lnum[blkno] < nlines && lnum[blkno + 1] - lnum[blkno] < (BLKSIZE >> 6))
-       {
-               /* hey, we probably can!  Get the following block & see... */
-               following = blkget(blkno + 1);
-               if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
-               {
-                       /* we can!  Copy text from following to blk */
-                       for (scan = following->c; *scan; )
-                       {
-                               *build++ = *scan++;
-                       }
-                       while (build < blk->c + BLKSIZE)
-                       {
-                               *build++ = '\0';
-                       }
-                       blkdirty(blk);
-
-                       /* pretend the following was the last blk */
-                       blk = following;
-                       build = blk->c;
-               }
-       }
-
-       /* that last block is dirty by now */
-       while (build < blk->c + BLKSIZE)
-       {
-               *build++ = '\0';
-       }
-       blkdirty(blk);
-}
-
-
-/* change the text of a file */
-void change(frommark, tomark, newtext)
-       MARK    frommark, tomark;
-       char    *newtext;
-{
-       int     i;
-       long    l;
-       char    *text;
-       BLK     *blk;
-
-#ifdef DEBUG2
-       debout("change(%ld.%d, %ld.%d, \"%s\")\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark), newtext);
-#endif
-
-       /* optimize for single-character replacement */
-       if (frommark + 1 == tomark && newtext[0] && !newtext[1] && newtext[0] != '\n')
-       {
-               /* find the block containing frommark */
-               l = markline(frommark);
-               for (i = 1; lnum[i] < l; i++)
-               {
-               }
-
-               /* get the block */
-               blk = blkget(i);
-
-               /* find the line within the block */
-               for (text = blk->c, i = l - lnum[i - 1] - 1; i > 0; text++)
-               {
-                       if (*text == '\n')
-                       {
-                               i--;
-                       }
-               }
-
-               /* replace the char */
-               text += markidx(frommark);
-               if (*text == newtext[0])
-               {
-                       /* no change was needed - same char */
-                       return;
-               }
-               else if (*text != '\n')
-               {
-                       /* This is a change */
-                       changes++;
-                       significant = TRUE;
-                       ChangeText
-                       {
-                               *text = newtext[0];
-                               blkdirty(blk);
-                       }
-                       redrawrange(markline(frommark), markline(tomark), markline(frommark));
-                       return;
-               }
-               /* else it is a complex change involving newline... */
-       }
-
-       /* couldn't optimize, so do delete & add */
-       ChangeText
-       {
-               delete(frommark, tomark);
-               add(frommark, newtext);
-               rptlabel = "changed";
-       }
-}
diff --git a/commands/elvis/move1.c b/commands/elvis/move1.c
deleted file mode 100644 (file)
index f57ab9a..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-/* move1.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains most movement functions */
-
-#include "config.h"
-#include "vi.h"
-#include "ctype.h"
-
-MARK   m_updnto(m, cnt, cmd)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       char    cmd;    /* the command character */
-{
-       DEFAULT(cmd == 'G' ? nlines : 1L);
-
-       /* move up or down 'cnt' lines */
-       switch (cmd)
-       {
-         case ctrl('P'):
-         case '-':
-         case 'k':
-               m -= MARK_AT_LINE(cnt);
-               break;
-
-         case 'G':
-               if (cnt < 1L || cnt > nlines)
-               {
-                       msg("Only %ld lines", nlines);
-                       return MARK_UNSET;
-               }
-               m = MARK_AT_LINE(cnt);
-               break;
-
-         case '_':
-               cnt--;
-               /* fall through... */
-
-         default:
-               m += MARK_AT_LINE(cnt);
-       }
-
-       /* if that left us screwed up, then fail */
-       if (m < MARK_FIRST || markline(m) > nlines)
-       {
-               return MARK_UNSET;
-       }
-
-       return m;
-}
-
-/*ARGSUSED*/
-MARK   m_right(m, cnt, key, prevkey)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     key;    /* movement keystroke */
-       int     prevkey;/* operator keystroke, or 0 if none */
-{
-       int             idx;    /* index of the new cursor position */
-
-       DEFAULT(1);
-
-       /* If used with an operator, then move 1 less character, since the 'l'
-        * command includes the character that it moves onto.
-        */
-       if (prevkey != '\0')
-       {
-               cnt--;
-       }
-
-       /* move to right, if that's OK */
-       pfetch(markline(m));
-       idx = markidx(m) + cnt;
-       if (idx < plen)
-       {
-               m += cnt;
-       }
-       else
-       {
-               return MARK_UNSET;
-       }
-
-       return m;
-}
-
-/*ARGSUSED*/
-MARK   m_left(m, cnt)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-{
-       DEFAULT(1);
-
-       /* move to the left, if that's OK */
-       if (markidx(m) >= cnt)
-       {
-               m -= cnt;
-       }
-       else
-       {
-               return MARK_UNSET;
-       }
-
-       return m;
-}
-
-/*ARGSUSED*/
-MARK   m_tocol(m, cnt, cmd)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     cmd;    /* either ctrl('X') or '|' */
-{
-       char    *text;  /* text of the line */
-       int     col;    /* column number */
-       int     idx;    /* index into the line */
-
-
-       /* if doing ^X, then adjust for sideways scrolling */
-       if (cmd == ctrl('X'))
-       {
-               DEFAULT(*o_columns & 0xff);
-               cnt += leftcol;
-       }
-       else
-       {
-               DEFAULT(1);
-       }
-
-       /* internally, columns are numbered 0..COLS-1, not 1..COLS */
-       cnt--;
-
-       /* if 0, that's easy */
-       if (cnt == 0)
-       {
-               m &= ~(BLKSIZE - 1);
-               return m;
-       }
-
-       /* find that column within the line */
-       pfetch(markline(m));
-       text = ptext;
-       for (col = idx = 0; col < cnt && *text; text++, idx++)
-       {
-               if (*text == '\t' && !*o_list)
-               {
-                       col += *o_tabstop;
-                       col -= col % *o_tabstop;
-               }
-               else if (UCHAR(*text) < ' ' || *text == '\177')
-               {
-                       col += 2;
-               }
-#ifndef NO_CHARATTR
-               else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
-               {
-                       text += 2; /* plus one more as part of for loop */
-               }
-#endif
-               else
-               {
-                       col++;
-               }
-       }
-       if (!*text)
-       {
-               /* the desired column was past the end of the line, so
-                * act like the user pressed "$" instead.
-                */
-               return m | (BLKSIZE - 1);
-       }
-       else
-       {
-               m = (m & ~(BLKSIZE - 1)) + idx;
-       }
-       return m;
-}
-
-/*ARGSUSED*/
-MARK   m_front(m, cnt)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument (ignored) */
-{
-       char    *scan;
-
-       /* move to the first non-whitespace character */
-       pfetch(markline(m));
-       scan = ptext;
-       m &= ~(BLKSIZE - 1);
-       while (*scan == ' ' || *scan == '\t')
-       {
-               scan++;
-               m++;
-       }
-
-       return m;
-}
-
-/*ARGSUSED*/
-MARK   m_rear(m, cnt)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument (ignored) */
-{
-       /* Try to move *EXTREMELY* far to the right.  It is fervently hoped
-        * that other code will convert this to a more reasonable MARK before
-        * anything tries to actually use it.  (See adjmove() in vi.c)
-        */
-       return m | (BLKSIZE - 1);
-}
-
-#ifndef NO_SENTENCE
-static int isperiod(ptr)
-       char    *ptr;   /* pointer to possible sentence-ender */
-{
-       /* if not '.', '?', or '!', then it isn't a sentence ender */
-       if (*ptr != '.' && *ptr != '?' && *ptr != '!')
-       {
-               return FALSE;
-       }
-
-       /* skip any intervening ')', ']', or '"' characters */
-       do
-       {
-               ptr++;
-       } while (*ptr == ')' || *ptr == ']' || *ptr == '"');
-
-       /* do we have two spaces or EOL? */
-       if (!*ptr || ptr[0] == ' ' && ptr[1] == ' ')
-       {
-               return TRUE;
-       }
-       return FALSE;
-}
-
-/*ARGSUSED*/
-MARK   m_sentence(m, cnt, cmd)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     cmd;    /* either '(' or ')' */
-{
-       REG char        *text;
-       REG long        l;
-
-       DEFAULT(1);
-
-       /* If '(' command, then move back one word, so that if we hit '(' at
-        * the start of a sentence we don't simply stop at the end of the
-        * previous sentence and bounce back to the start of this one again.
-        */
-       if (cmd == '(')
-       {
-               m = m_bword(m, 1L, 'b');
-               if (!m)
-               {
-                       return m;
-               }
-       }
-
-       /* get the current line */
-       l = markline(m);
-       pfetch(l);
-       text = ptext + markidx(m);
-
-       /* for each requested sentence... */
-       while (cnt-- > 0)
-       {
-               /* search forward for one of [.?!] followed by spaces or EOL */
-               do
-               {
-                       if (cmd == ')')
-                       {
-                               /* move forward, wrap at end of line */
-                               if (!text[0])
-                               {
-                                       if (l >= nlines)
-                                       {
-                                               return MARK_UNSET;
-                                       }
-                                       l++;
-                                       pfetch(l);
-                                       text = ptext;
-                               }
-                               else
-                               {
-                                       text++;
-                               }
-                       }
-                       else
-                       {
-                               /* move backward, wrap at beginning of line */
-                               if (text == ptext)
-                               {
-                                       do
-                                       {
-                                               if (l <= 1)
-                                               {
-                                                       return MARK_FIRST;
-                                               }
-                                               l--;
-                                               pfetch(l);
-                                       } while (!*ptext);
-                                       text = ptext + plen - 1;
-                               }
-                               else
-                               {
-                                       text--;
-                               }
-                       }
-               } while (!isperiod(text));
-       }
-
-       /* construct a mark for this location */
-       m = buildmark(text);
-
-       /* move forward to the first word of the next sentence */
-       m = m_fword(m, 1L, 'w', '\0');
-
-       return m;
-}
-#endif
-
-MARK   m_paragraph(m, cnt, cmd)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     cmd;    /* either '{' or '}' */
-{
-       char    *text;  /* text of the current line */
-       char    *pscn;  /* used to scan thru value of "paragraphs" option */
-       long    l, ol;  /* current line number, original line number */
-       int     dir;    /* -1 if we're moving up, or 1 if down */
-       char    col0;   /* character to expect in column 0 */
-#ifndef NO_SENTENCE
-# define SENTENCE(x)   (x)
-       char    *list;  /* either o_sections or o_paragraph */
-#else
-# define SENTENCE(x)
-#endif
-
-       DEFAULT(1);
-
-       /* set the direction, based on the command */
-       switch (cmd)
-       {
-         case '{':
-               dir = -1;
-               col0 = '\0';
-               SENTENCE(list = o_paragraphs); 
-               break;
-
-         case '}':
-               dir = 1;
-               col0 = '\0';
-               SENTENCE(list = o_paragraphs); 
-               break;
-
-         case '[':
-               if (getkey(0) != '[')
-               {
-                       return MARK_UNSET;
-               }
-               dir = -1;
-               col0 = '{';
-               SENTENCE(list = o_sections); 
-               break;
-
-         case ']':
-               if (getkey(0) != ']')
-               {
-                       return MARK_UNSET;
-               }
-               dir = 1;
-               col0 = '{';
-               SENTENCE(list = o_sections); 
-               break;
-       }
-       ol = l = markline(m);
-
-       /* for each paragraph that we want to travel through... */
-       while (l > 0 && l <= nlines && cnt-- > 0)
-       {
-               /* skip blank lines between paragraphs */
-               while (l > 0 && l <= nlines && col0 == *(text = fetchline(l)))
-               {
-                       l += dir;
-               }
-
-               /* skip non-blank lines that aren't paragraph separators
-                */
-               do
-               {
-#ifndef NO_SENTENCE
-                       if (*text == '.' && l != ol)
-                       {
-                               for (pscn = list; pscn[0] && pscn[1]; pscn += 2)
-                               {
-                                       if (pscn[0] == text[1] && pscn[1] == text[2])
-                                       {
-                                               pscn = (char *)0;
-                                               goto BreakBreak;
-                                       }
-                               }
-                       }
-#endif
-                       l += dir;
-               } while (l > 0 && l <= nlines && col0 != *(text = fetchline(l)));
-BreakBreak:    ;
-       }
-
-       if (l > nlines)
-       {
-               m = MARK_LAST;
-       }
-       else if (l <= 0)
-       {
-               m = MARK_FIRST;
-       }
-       else
-       {
-               m = MARK_AT_LINE(l);
-       }
-       return m;
-}
-
-
-/*ARGSUSED*/
-MARK   m_match(m, cnt)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument (normally 0) */
-{
-       long    l;
-       REG char        *text;
-       REG char        match;
-       REG char        nest;
-       REG int         count;
-
-#ifndef NO_EXTENSIONS
-       /* if we're given a number, then treat it as a percentage of the file */
-       if (cnt > 0)
-       {
-               /* make sure it is a reasonable number */
-               if (cnt > 100)
-               {
-                       msg("can only be from 1%% to 100%%");
-                       return MARK_UNSET;
-               }
-
-               /* return the appropriate line number */
-               l = (nlines - 1L) * cnt / 100L + 1L;
-               return MARK_AT_LINE(l);
-       }
-#endif /* undef NO_EXTENSIONS */
-
-       /* get the current line */
-       l = markline(m);
-       pfetch(l);
-       text = ptext + markidx(m);
-
-       /* search forward within line for one of "[](){}" */
-       for (match = '\0'; !match && *text; text++)
-       {
-               /* tricky way to recognize 'em in ASCII */
-               nest = *text;
-               if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
-               {
-                       match = nest ^ ('[' ^ ']');
-               }
-               else if ((nest & 0xfe) == '(')
-               {
-                       match = nest ^ ('(' ^ ')');
-               }
-               else
-               {
-                       match = 0;
-               }
-       }
-       if (!match)
-       {
-               return MARK_UNSET;
-       }
-       text--;
-
-       /* search forward or backward for match */
-       if (match == '(' || match == '[' || match == '{')
-       {
-               /* search backward */
-               for (count = 1; count > 0; )
-               {
-                       /* wrap at beginning of line */
-                       if (text == ptext)
-                       {
-                               do
-                               {
-                                       if (l <= 1L)
-                                       {
-                                               return MARK_UNSET;
-                                       }
-                                       l--;
-                                       pfetch(l);
-                               } while (!*ptext);
-                               text = ptext + plen - 1;
-                       }
-                       else
-                       {
-                               text--;
-                       }
-
-                       /* check the char */
-                       if (*text == match)
-                               count--;
-                       else if (*text == nest)
-                               count++;
-               }
-       }
-       else
-       {
-               /* search forward */
-               for (count = 1; count > 0; )
-               {
-                       /* wrap at end of line */
-                       if (!*text)
-                       {
-                               if (l >= nlines)
-                               {
-                                       return MARK_UNSET;
-                               }
-                               l++;
-                               pfetch(l);
-                               text = ptext;
-                       }
-                       else
-                       {
-                               text++;
-                       }
-
-                       /* check the char */
-                       if (*text == match)
-                               count--;
-                       else if (*text == nest)
-                               count++;
-               }
-       }
-
-       /* construct a mark for this place */
-       m = buildmark(text);
-       return m;
-}
-
-/*ARGSUSED*/
-MARK   m_tomark(m, cnt, key)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* (ignored) */
-       int     key;    /* keystroke - the mark to move to */
-{
-       /* mark '' is a special case */
-       if (key == '\'' || key == '`')
-       {
-               if (mark[26] == MARK_UNSET)
-               {
-                       return MARK_FIRST;
-               }
-               else
-               {
-                       return mark[26];
-               }
-       }
-
-       /* if not a valid mark number, don't move */
-       if (key < 'a' || key > 'z')
-       {
-               return MARK_UNSET;
-       }
-
-       /* return the selected mark -- may be MARK_UNSET */
-       if (!mark[key - 'a'])
-       {
-               msg("mark '%c is unset", key);
-       }
-       return mark[key - 'a'];
-}
-
diff --git a/commands/elvis/move2.c b/commands/elvis/move2.c
deleted file mode 100644 (file)
index b664153..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/* move2.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This function contains the movement functions that perform RE searching */
-
-#include "config.h"
-#include "vi.h"
-#include "regexp.h"
-
-extern long    atol();
-
-static regexp  *re;    /* compiled version of the pattern to search for */
-static         prevsf; /* boolean: previous search direction was forward? */
-
-#ifndef NO_EXTENSIONS
-/*ARGSUSED*/
-MARK m_wsrch(word, m, cnt)
-       char    *word;  /* the word to search for */
-       MARK    m;      /* the starting point */
-       int     cnt;    /* ignored */
-{
-       char    buffer[30];
-
-       /* wrap \< and \> around the word */
-       strcpy(buffer, "/\\<");
-       strcat(buffer, word);
-       strcat(buffer, "\\>");
-
-       /* show the searched-for word on the bottom line */
-       move(LINES - 1, 0);
-       qaddstr(buffer);
-       clrtoeol();
-       refresh();
-
-       /* search for the word */
-       return m_fsrch(m, buffer);
-}
-#endif
-
-MARK   m_nsrch(m)
-       MARK    m;      /* where to start searching */
-{
-       if (prevsf)
-       {
-               m = m_fsrch(m, (char *)0);
-               prevsf = TRUE;
-       }
-       else
-       {
-               m = m_bsrch(m, (char *)0);
-               prevsf = FALSE;
-       }
-       return m;
-}
-
-MARK   m_Nsrch(m)
-       MARK    m;      /* where to start searching */
-{
-       if (prevsf)
-       {
-               m = m_bsrch(m, (char *)0);
-               prevsf = TRUE;
-       }
-       else
-       {
-               m = m_fsrch(m, (char *)0);
-               prevsf = FALSE;
-       }
-       return m;
-}
-
-MARK   m_fsrch(m, ptrn)
-       MARK    m;      /* where to start searching */
-       char    *ptrn;  /* pattern to search for */
-{
-       long    l;      /* line# of line to be searched */
-       char    *line;  /* text of line to be searched */
-       int     wrapped;/* boolean: has our search wrapped yet? */
-       int     pos;    /* where we are in the line */
-#ifndef CRUNCH
-       long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
-#endif
-
-       /* remember: "previous search was forward" */
-       prevsf = TRUE;
-
-       if (ptrn && *ptrn)
-       {
-               /* locate the closing '/', if any */
-               line = parseptrn(ptrn);
-#ifndef CRUNCH
-               if (*line)
-               {
-                       delta = atol(line);
-               }
-#endif
-               ptrn++;
-
-               /* free the previous pattern */
-               if (re) free(re);
-
-               /* compile the pattern */
-               re = regcomp(ptrn);
-               if (!re)
-               {
-                       return MARK_UNSET;
-               }
-       }
-       else if (!re)
-       {
-               msg("No previous expression");
-               return MARK_UNSET;
-       }
-
-       /* search forward for the pattern */
-       pos = markidx(m) + 1;
-       pfetch(markline(m));
-       if (pos >= plen)
-       {
-               pos = 0;
-               m = (m | (BLKSIZE - 1)) + 1;
-       }
-       wrapped = FALSE;
-       for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
-       {
-               /* wrap search */
-               if (l > nlines)
-               {
-                       /* if we wrapped once already, then the search failed */
-                       if (wrapped)
-                       {
-                               break;
-                       }
-
-                       /* else maybe we should wrap now? */
-                       if (*o_wrapscan)
-                       {
-                               l = 0;
-                               wrapped = TRUE;
-                               continue;
-                       }
-                       else
-                       {
-                               break;
-                       }
-               }
-
-               /* get this line */
-               line = fetchline(l);
-
-               /* check this line */
-               if (regexec(re, &line[pos], (pos == 0)))
-               {
-                       /* match! */
-                       if (wrapped && *o_warn)
-                               msg("(wrapped)");
-#ifndef CRUNCH
-                       if (delta != INFINITY)
-                       {
-                               l += delta;
-                               if (l < 1 || l > nlines)
-                               {
-                                       msg("search offset too big");
-                                       return MARK_UNSET;
-                               }
-                               force_flags = LNMD|INCL;
-                               return MARK_AT_LINE(l);
-                       }
-#endif
-                       return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
-               }
-               pos = 0;
-       }
-
-       /* not found */
-       msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
-       return MARK_UNSET;
-}
-
-MARK   m_bsrch(m, ptrn)
-       MARK    m;      /* where to start searching */
-       char    *ptrn;  /* pattern to search for */
-{
-       long    l;      /* line# of line to be searched */
-       char    *line;  /* text of line to be searched */
-       int     wrapped;/* boolean: has our search wrapped yet? */
-       int     pos;    /* last acceptable idx for a match on this line */
-       int     last;   /* remembered idx of the last acceptable match on this line */
-       int     try;    /* an idx at which we strat searching for another match */
-#ifndef CRUNCH
-       long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
-#endif
-
-       /* remember: "previous search was not forward" */
-       prevsf = FALSE;
-
-       if (ptrn && *ptrn)
-       {
-               /* locate the closing '?', if any */
-               line = parseptrn(ptrn);
-#ifndef CRUNCH
-               if (*line)
-               {
-                       delta = atol(line);
-               }
-#endif
-               ptrn++;
-
-               /* free the previous pattern, if any */
-               if (re) free(re);
-
-               /* compile the pattern */
-               re = regcomp(ptrn);
-               if (!re)
-               {
-                       return MARK_UNSET;
-               }
-       }
-       else if (!re)
-       {
-               msg("No previous expression");
-               return MARK_UNSET;
-       }
-
-       /* search backward for the pattern */
-       pos = markidx(m);
-       wrapped = FALSE;
-       for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
-       {
-               /* wrap search */
-               if (l < 1)
-               {
-                       if (*o_wrapscan)
-                       {
-                               l = nlines + 1;
-                               wrapped = TRUE;
-                               continue;
-                       }
-                       else
-                       {
-                               break;
-                       }
-               }
-
-               /* get this line */
-               line = fetchline(l);
-
-               /* check this line */
-               if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
-               {
-                       /* match!  now find the last acceptable one in this line */
-                       do
-                       {
-                               last = (int)(re->startp[0] - line);
-                               try = (int)(re->endp[0] - line);
-                       } while (try > 0
-                                && regexec(re, &line[try], FALSE)
-                                && (int)(re->startp[0] - line) < pos);
-
-                       if (wrapped && *o_warn)
-                               msg("(wrapped)");
-#ifndef CRUNCH
-                       if (delta != INFINITY)
-                       {
-                               l += delta;
-                               if (l < 1 || l > nlines)
-                               {
-                                       msg("search offset too big");
-                                       return MARK_UNSET;
-                               }
-                               force_flags = LNMD|INCL;
-                               return MARK_AT_LINE(l);
-                       }
-#endif
-                       return MARK_AT_LINE(l) + last;
-               }
-               pos = BLKSIZE;
-       }
-
-       /* not found */
-       msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
-       return MARK_UNSET;
-}
-
diff --git a/commands/elvis/move3.c b/commands/elvis/move3.c
deleted file mode 100644 (file)
index a9e46ea..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/* move3.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains movement functions that perform character searches */
-
-#include "config.h"
-#include "vi.h"
-
-#ifndef NO_CHARSEARCH
-static MARK    (*prevfwdfn)(); /* function to search in same direction */
-static MARK    (*prevrevfn)(); /* function to search in opposite direction */
-static char    prev_key;       /* sought cvhar from previous [fFtT] */
-
-MARK   m__ch(m, cnt, cmd)
-       MARK    m;      /* current position */
-       long    cnt;
-       char    cmd;    /* command: either ',' or ';' */
-{
-       MARK    (*tmp)();
-
-       if (!prevfwdfn)
-       {
-               msg("No previous f, F, t, or T command");
-               return MARK_UNSET;
-       }
-
-       if (cmd == ',')
-       {
-               m =  (*prevrevfn)(m, cnt, prev_key);
-
-               /* Oops! we didn't want to change the prev*fn vars! */
-               tmp = prevfwdfn;
-               prevfwdfn = prevrevfn;
-               prevrevfn = tmp;
-
-               return m;
-       }
-       else
-       {
-               return (*prevfwdfn)(m, cnt, prev_key);
-       }
-}
-
-/* move forward within this line to next occurrence of key */
-MARK   m_fch(m, cnt, key)
-       MARK    m;      /* where to search from */
-       long    cnt;
-       char    key;    /* what to search for */
-{
-       REG char        *text;
-
-       DEFAULT(1);
-
-       prevfwdfn = m_fch;
-       prevrevfn = m_Fch;
-       prev_key = key;
-
-       pfetch(markline(m));
-       text = ptext + markidx(m);
-       while (cnt-- > 0)
-       {
-               do
-               {
-                       m++;
-                       text++;
-               } while (*text && *text != key);
-       }
-       if (!*text)
-       {
-               return MARK_UNSET;
-       }
-       return m;
-}
-
-/* move backward within this line to previous occurrence of key */
-MARK   m_Fch(m, cnt, key)
-       MARK    m;      /* where to search from */
-       long    cnt;
-       char    key;    /* what to search for */
-{
-       REG char        *text;
-
-       DEFAULT(1);
-
-       prevfwdfn = m_Fch;
-       prevrevfn = m_fch;
-       prev_key = key;
-
-       pfetch(markline(m));
-       text = ptext + markidx(m);
-       while (cnt-- > 0)
-       {
-               do
-               {
-                       m--;
-                       text--;
-               } while (text >= ptext && *text != key);
-       }
-       if (text < ptext)
-       {
-               return MARK_UNSET;
-       }
-       return m;
-}
-
-/* move forward within this line almost to next occurrence of key */
-MARK   m_tch(m, cnt, key)
-       MARK    m;      /* where to search from */
-       long    cnt;
-       char    key;    /* what to search for */
-{
-       /* skip the adjacent char */
-       pfetch(markline(m));
-       if (plen <= markidx(m))
-       {
-               return MARK_UNSET;
-       }
-       m++;
-
-       m = m_fch(m, cnt, key);
-       if (m == MARK_UNSET)
-       {
-               return MARK_UNSET;
-       }
-
-       prevfwdfn = m_tch;
-       prevrevfn = m_Tch;
-
-       return m - 1;
-}
-
-/* move backward within this line almost to previous occurrence of key */
-MARK   m_Tch(m, cnt, key)
-       MARK    m;      /* where to search from */
-       long    cnt;
-       char    key;    /* what to search for */
-{
-       /* skip the adjacent char */
-       if (markidx(m) == 0)
-       {
-               return MARK_UNSET;
-       }
-       m--;
-
-       m = m_Fch(m, cnt, key);
-       if (m == MARK_UNSET)
-       {
-               return MARK_UNSET;
-       }
-
-       prevfwdfn = m_Tch;
-       prevrevfn = m_tch;
-
-       return m + 1;
-}
-#endif
diff --git a/commands/elvis/move4.c b/commands/elvis/move4.c
deleted file mode 100644 (file)
index a31ef88..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/* move4.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains movement functions which are screen-relative */
-
-#include "config.h"
-#include "vi.h"
-
-/* This moves the cursor to a particular row on the screen */
-/*ARGSUSED*/
-MARK m_row(m, cnt, key)
-       MARK    m;      /* the cursor position */
-       long    cnt;    /* the row we'll move to */
-       int     key;    /* the keystroke of this move - H/L/M */
-{
-       DEFAULT(1);
-
-       /* calculate destination line based on key */
-       cnt--;
-       switch (key)
-       {
-         case 'H':
-               cnt = topline + cnt;
-               break;
-
-         case 'M':
-               cnt = topline + (LINES - 1) / 2;
-               break;
-
-         case 'L':
-               cnt = botline - cnt;
-               break;
-       }
-
-       /* return the mark of the destination line */
-       return MARK_AT_LINE(cnt);
-}
-
-
-/* This function repositions the current line to show on a given row */
-MARK m_z(m, cnt, key)
-       MARK    m;      /* the cursor */
-       long    cnt;    /* the line number we're repositioning */
-       int     key;    /* key struck after the z */
-{
-       long    newtop;
-       int     i;
-
-       /* Which line are we talking about? */
-       if (cnt < 0 || cnt > nlines)
-       {
-               return MARK_UNSET;
-       }
-       if (cnt)
-       {
-               m = MARK_AT_LINE(cnt);
-               newtop = cnt;
-       }
-       else
-       {
-               newtop = markline(m);
-       }
-
-       /* allow a "window size" number to be entered */
-       for (i = 0; key >= '0' && key <= '9'; key = getkey(0))
-       {
-               i = i * 10 + key - '0';
-       }
-#ifndef CRUNCH
-       if (i > 0 && i <= LINES - 1)
-       {
-               *o_window = i;
-               wset = TRUE;
-       }
-#else
-       /* the number is ignored if -DCRUNCH */
-#endif
-
-       /* figure out which line will have to be at the top of the screen */
-       switch (key)
-       {
-         case '\n':
-#if OSK
-         case '\l':
-#else
-         case '\r':
-#endif
-         case '+':
-               break;
-
-         case '.':
-         case 'z':
-               newtop -= LINES / 2;
-               break;
-
-         case '-':
-               newtop -= LINES - 1;
-               break;
-
-         default:
-               return MARK_UNSET;
-       }
-
-       /* make the new topline take effect */
-       redraw(MARK_UNSET, FALSE);
-       if (newtop >= 1)
-       {
-               topline = newtop;
-       }
-       else
-       {
-               topline = 1L;
-       }
-       redrawrange(0L, INFINITY, INFINITY);
-
-       /* The cursor doesn't move */
-       return m;
-}
-
-
-/* This function scrolls the screen.  It does this by calling redraw() with
- * an off-screen line as the argument.  It will move the cursor if necessary
- * so that the cursor is on the new screen.
- */
-/*ARGSUSED*/
-MARK m_scroll(m, cnt, key)
-       MARK    m;      /* the cursor position */
-       long    cnt;    /* for some keys: the number of lines to scroll */
-       int     key;    /* keystroke that causes this movement */
-{
-       MARK    tmp;    /* a temporary mark, used as arg to redraw() */
-
-       /* adjust cnt, and maybe *o_scroll, depending of key */
-       switch (key)
-       {
-         case ctrl('F'):
-         case ctrl('B'):
-               DEFAULT(1);
-               redrawrange(0L, INFINITY, INFINITY); /* force complete redraw */
-               cnt = cnt * (LINES - 1) - 2; /* keeps two old lines on screen */
-               break;
-
-         case ctrl('E'):
-         case ctrl('Y'):
-               DEFAULT(1);
-               break;
-
-         case ctrl('U'):
-         case ctrl('D'):
-               if (cnt == 0) /* default */
-               {
-                       cnt = *o_scroll;
-               }
-               else
-               {
-                       if (cnt > LINES - 1)
-                       {
-                               cnt = LINES - 1;
-                       }
-                       *o_scroll = cnt;
-               }
-               break;
-       }
-
-       /* scroll up or down, depending on key */
-       switch (key)
-       {
-         case ctrl('B'):
-         case ctrl('Y'):
-         case ctrl('U'):
-               cnt = topline - cnt;
-               if (cnt < 1L)
-               {
-                       cnt = 1L;
-                       m = MARK_FIRST;
-               }
-               tmp = MARK_AT_LINE(cnt) + markidx(m);
-               redraw(tmp, FALSE);
-               if (markline(m) > botline)
-               {
-                       m = MARK_AT_LINE(botline);
-               }
-               break;
-
-         case ctrl('F'):
-         case ctrl('E'):
-         case ctrl('D'):
-               cnt = botline + cnt;
-               if (cnt > nlines)
-               {
-                       cnt = nlines;
-                       m = MARK_LAST;
-               }
-               tmp = MARK_AT_LINE(cnt) + markidx(m);
-               redraw(tmp, FALSE);
-               if (markline(m) < topline)
-               {
-                       m = MARK_AT_LINE(topline);
-               }
-               break;
-       }
-
-       return m;
-}
diff --git a/commands/elvis/move5.c b/commands/elvis/move5.c
deleted file mode 100644 (file)
index aec5e78..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/* move5.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the word-oriented movement functions */
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-
-MARK   m_fword(m, cnt, cmd, prevkey)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     cmd;    /* either 'w' or 'W' */
-       int     prevkey;/* previous command... if 'c' then exclude whitespace */
-{
-       REG long        l;
-       REG char        *text;
-       REG int         i;
-
-       DEFAULT(1);
-
-       l = markline(m);
-       pfetch(l);
-       text = ptext + markidx(m);
-
-#ifndef CRUNCH
-       /* As a special case, "cw" or "cW" on whitespace without a count
-        * treats the single whitespace character under the cursor as a word.
-        */
-       if (cnt == 1L && prevkey == 'c' && isspace(*text))
-       {
-               return m + 1L;
-       }
-#endif
-
-       while (cnt-- > 0) /* yes, ASSIGNMENT! */
-       {
-               i = *text++;
-
-               if (cmd == 'W')
-               {
-                       /* include any non-whitespace */
-                       while (i && !isspace(i))
-                       {
-                               i = *text++;
-                       }
-               }
-               else if (isalnum(i) || i == '_')
-               {
-                       /* include an alphanumeric word */
-                       while (i && isalnum(i))
-                       {
-                               i = *text++;
-                       }
-               }
-               else
-               {
-                       /* include contiguous punctuation */
-                       while (i && !isalnum(i) && !isspace(i))
-                       {
-                               i = *text++;
-                       }
-               }
-
-               /* if not part of "cw" or "cW" command... */
-               if (prevkey != 'c' || cnt > 0)
-               {
-                       /* include trailing whitespace */
-                       while (!i || isspace(i))
-                       {
-                               /* did we hit the end of this line? */
-                               if (!i)
-                               {
-                                       /* "dw" shouldn't delete newline after word */
-                                       if (prevkey && cnt == 0)
-                                       {
-                                               break;
-                                       }
-
-                                       /* move to next line, if there is one */
-                                       l++;
-                                       if (l > nlines)
-                                       {
-                                               return MARK_UNSET;
-                                       }
-                                       pfetch(l);
-                                       text = ptext;
-                               }
-
-                               i = *text++;
-                       }
-               }
-               text--;
-       }
-
-       /* if argument to operator, then back off 1 char since "w" and "W"
-        * include the last char in the affected text.
-        */
-       if (prevkey)
-       {
-               text--;
-       }
-
-       /* construct a MARK for this place */
-       m = buildmark(text);
-       return m;
-}
-
-
-MARK   m_bword(m, cnt, cmd)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     cmd;    /* either 'b' or 'B' */
-{
-       REG long        l;
-       REG char        *text;
-
-       DEFAULT(1);
-
-       l = markline(m);
-       pfetch(l);
-       text = ptext + markidx(m);
-       while (cnt-- > 0) /* yes, ASSIGNMENT! */
-       {
-               text--;
-
-               /* include preceding whitespace */
-               while (text < ptext || isspace(*text))
-               {
-                       /* did we hit the end of this line? */
-                       if (text < ptext)
-                       {
-                               /* move to preceding line, if there is one */
-                               l--;
-                               if (l <= 0)
-                               {
-                                       return MARK_UNSET;
-                               }
-                               pfetch(l);
-                               text = ptext + plen - 1;
-                       }
-                       else
-                       {
-                               text--;
-                       }
-               }
-
-               if (cmd == 'B')
-               {
-                       /* include any non-whitespace */
-                       while (text >= ptext && !isspace(*text))
-                       {
-                               text--;
-                       }
-               }
-               else if (isalnum(*text) || *text == '_')
-               {
-                       /* include an alphanumeric word */
-                       while (text >= ptext && isalnum(*text))
-                       {
-                               text--;
-                       }
-               }
-               else
-               {
-                       /* include contiguous punctuation */
-                       while (text >= ptext && !isalnum(*text) && !isspace(*text))
-                       {
-                               text--;
-                       }
-               }
-               text++;
-       }
-
-       /* construct a MARK for this place */
-       m = buildmark(text);
-       return m;
-}
-
-MARK   m_eword(m, cnt, cmd)
-       MARK    m;      /* movement is relative to this mark */
-       long    cnt;    /* a numeric argument */
-       int     cmd;    /* either 'e' or 'E' */
-{
-       REG long        l;
-       REG char        *text;
-       REG int         i;
-
-       DEFAULT(1);
-
-       l = markline(m);
-       pfetch(l);
-       text = ptext + markidx(m);
-       while (cnt-- > 0) /* yes, ASSIGNMENT! */
-       {
-               if (*text)
-                       text++;
-               i = *text++;
-
-               /* include preceding whitespace */
-               while (!i || isspace(i))
-               {
-                       /* did we hit the end of this line? */
-                       if (!i)
-                       {
-                               /* move to next line, if there is one */
-                               l++;
-                               if (l > nlines)
-                               {
-                                       return MARK_UNSET;
-                               }
-                               pfetch(l);
-                               text = ptext;
-                       }
-
-                       i = *text++;
-               }
-
-               if (cmd == 'E')
-               {
-                       /* include any non-whitespace */
-                       while (i && !isspace(i))
-                       {
-                               i = *text++;
-                       }
-               }
-               else if (isalnum(i) || i == '_')
-               {
-                       /* include an alphanumeric word */
-                       while (i && isalnum(i))
-                       {
-                               i = *text++;
-                       }
-               }
-               else
-               {
-                       /* include contiguous punctuation */
-                       while (i && !isalnum(i) && !isspace(i))
-                       {
-                               i = *text++;
-                       }
-               }
-               text -= 2;
-       }
-
-       /* construct a MARK for this place */
-       m = buildmark(text);
-       return m;
-}
diff --git a/commands/elvis/opts.c b/commands/elvis/opts.c
deleted file mode 100644 (file)
index 7552ac6..0000000
+++ /dev/null
@@ -1,795 +0,0 @@
-/* opts.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the code that manages the run-time options -- The 
- * values that can be modified via the "set" command.
- */
-
-#include "config.h"
-#include "vi.h"
-#include "ctype.h"
-#include <sys/null.h>
-extern char    *getenv();
-
-/* maximum width to permit for strings, including ="" */
-#define MAXWIDTH 20
-
-/* These are the default values of all options */
-char   o_autoindent[1] =       {FALSE};
-char   o_autoprint[1] =        {TRUE};
-char   o_autotab[1] =          {TRUE};
-char   o_autowrite[1] =        {FALSE};
-char   o_columns[3] =          {80, 32, 255};
-char   o_directory[30] =       TMPDIR;
-char   o_edcompatible[1] =     {FALSE};
-char   o_equalprg[80] =        {"fmt"};
-char   o_errorbells[1] =       {TRUE};
-char   o_exrefresh[1] =        {TRUE};
-char   o_ignorecase[1] =       {FALSE};
-char   o_keytime[3] =          {1, 0, 50};
-char   o_keywordprg[80] =      {KEYWORDPRG};
-char   o_lines[3] =            {25, 2, 96};
-char   o_list[1] =             {FALSE};
-char   o_number[1] =           {FALSE};
-char   o_readonly[1] =         {FALSE};
-char   o_remap[1] =            {TRUE};
-char   o_report[3] =           {5, 1, 127};
-char   o_scroll[3] =           {12, 1, 127};
-char   o_shell[60] =           SHELL;
-char   o_shiftwidth[3] =       {8, 1, 255};
-char   o_sidescroll[3] =       {8, 1, 40};
-char   o_sync[1] =             {NEEDSYNC};
-char   o_tabstop[3] =          {8, 1, 40};
-char   o_term[30] =            "?";
-char   o_flash[1] =            {TRUE};
-char   o_warn[1] =             {TRUE};
-char   o_wrapscan[1] =         {TRUE};
-
-#ifndef CRUNCH
-char   o_beautify[1] =         {FALSE};
-char   o_exrc[1] =             {FALSE};
-char   o_mesg[1] =             {TRUE};
-char   o_more[1] =             {TRUE};
-char   o_novice[1] =           {FALSE};
-char   o_prompt[1] =           {TRUE};
-char   o_taglength[3] =        {0, 0, 30};
-char   o_terse[1] =            {FALSE};
-char   o_window[3] =           {0, 1, 24};
-char   o_wrapmargin[3] =       {0, 0, 255};
-char   o_writeany[1] =         {FALSE};
-#endif
-
-#ifndef NO_ERRLIST
-char   o_cc[30] =              {CC_COMMAND};
-char   o_make[30] =            {MAKE_COMMAND};
-#endif
-
-#ifndef NO_CHARATTR
-char   o_charattr[1] =         {FALSE};
-#endif
-
-#ifndef NO_DIGRAPH
-char   o_digraph[1] =          {FALSE};
-char   o_flipcase[80]
-# ifdef CS_IBMPC
-       = {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
-# endif
-# ifdef CS_LATIN1
-       /* initialized by initopts() */
-# endif
-       ;
-#endif
-
-#ifndef NO_SENTENCE
-char   o_hideformat[1] =       {FALSE};
-#endif
-
-#ifndef NO_EXTENSIONS
-char   o_inputmode[1] =        {FALSE};
-char   o_ruler[1] =            {FALSE};
-#endif
-
-#ifndef NO_MAGIC
-char   o_magic[1] =            {TRUE};
-#endif
-
-#ifndef NO_MODELINES
-char   o_modelines[1] =        {FALSE};
-#endif
-
-#ifndef NO_SENTENCE
-char   o_paragraphs[30] =      "PPppIPLPQP";
-char   o_sections[30] =        "NHSHSSSEse";
-#endif
-
-#if MSDOS
-char   o_pcbios[1] =           {TRUE};
-#endif
-
-#ifndef NO_SHOWMATCH
-char   o_showmatch[1] =        {FALSE};
-#endif
-
-#ifndef        NO_SHOWMODE
-char   o_smd[1] =              {FALSE};
-#endif
-
-
-/* The following describes the names & types of all options */
-#define BOOL   0
-#define        NUM     1
-#define        STR     2
-#define SET    0x01    /* this option has had its value altered */
-#define CANSET 0x02    /* this option can be set at any time */
-#define RCSET  0x06    /* this option can be set in a .exrc file only */
-#define NOSAVE 0x0a    /* this option should never be saved by mkexrc */
-#define WSET   0x20    /* is this the "window" size option? */
-#define MR     0x40    /* does this option affect the way text is displayed? */
-struct
-{
-       char    *name;  /* name of an option */
-       char    *nm;    /* short name of an option */
-       char    type;   /* type of an option */
-       char    flags;  /* boolean: has this option been set? */
-       char    *value; /* value */
-}
-       opts[] =
-{
-       /* name                 type    flags           value */
-       { "autoindent", "ai",   BOOL,   CANSET,         o_autoindent    },
-       { "autoprint",  "ap",   BOOL,   CANSET,         o_autoprint     },
-       { "autotab",    "at",   BOOL,   CANSET,         o_autotab       },
-       { "autowrite",  "aw",   BOOL,   CANSET,         o_autowrite     },
-#ifndef CRUNCH
-       { "beautify",   "bf",   BOOL,   CANSET,         o_beautify      },
-#endif
-#ifndef NO_ERRLIST
-       { "cc",         "cc",   STR,    CANSET,         o_cc            },
-#endif
-#ifndef NO_CHARATTR
-       { "charattr",   "ca",   BOOL,   CANSET|MR,      o_charattr      },
-#endif
-       { "columns",    "co",   NUM,    SET|NOSAVE|MR,  o_columns       },
-#ifndef NO_DIGRAPH
-       { "digraph",    "dig",  BOOL,   CANSET,         o_digraph       },
-#endif
-       { "directory",  "dir",  STR,    RCSET,          o_directory     },
-       { "edcompatible","ed",  BOOL,   CANSET,         o_edcompatible  },
-       { "equalprg",   "ep",   STR,    CANSET,         o_equalprg      },
-       { "errorbells", "eb",   BOOL,   CANSET,         o_errorbells    },
-#ifndef CRUNCH
-       { "exrc",       "exrc", BOOL,   CANSET,         o_exrc          },
-#endif
-       { "exrefresh",  "er",   BOOL,   CANSET,         o_exrefresh     },
-       { "flash",      "vbell",BOOL,   CANSET,         o_flash         },
-#ifndef NO_DIGRAPH
-       { "flipcase",   "fc",   STR,    CANSET,         o_flipcase      },
-#endif
-#ifndef NO_SENTENCE
-       { "hideformat", "hf",   BOOL,   CANSET|MR,      o_hideformat    },
-#endif
-       { "ignorecase", "ic",   BOOL,   CANSET,         o_ignorecase    },
-#ifndef NO_EXTENSIONS
-       { "inputmode",  "im",   BOOL,   CANSET,         o_inputmode     },
-#endif
-       { "keytime",    "kt",   NUM,    CANSET,         o_keytime       },
-       { "keywordprg", "kp",   STR,    CANSET,         o_keywordprg    },
-       { "lines",      "ls",   NUM,    SET|NOSAVE|MR,  o_lines         },
-       { "list",       "li",   BOOL,   CANSET|MR,      o_list          },
-#ifndef NO_MAGIC
-       { "magic",      "ma",   BOOL,   CANSET,         o_magic         },
-#endif
-#ifndef NO_ERRLIST
-       { "make",       "mk",   STR,    CANSET,         o_make          },
-#endif
-#ifndef CRUNCH
-       { "mesg",       "me",   BOOL,   CANSET,         o_mesg          },
-#endif
-#ifndef NO_MODELINES
-       { "modelines",  "ml",   BOOL,   CANSET,         o_modelines     },
-#endif
-#ifndef CRUNCH
-       { "more",       "mo",   BOOL,   CANSET,         o_more          },
-       { "novice",     "nov",  BOOL,   CANSET,         o_novice        },
-#endif
-       { "number",     "nu",   BOOL,   CANSET|MR,      o_number        },
-#ifndef NO_SENTENCE
-       { "paragraphs", "para", STR,    CANSET,         o_paragraphs    },
-#endif
-#if MSDOS
-       { "pcbios",     "pc",   BOOL,   SET|NOSAVE,     o_pcbios        },
-#endif
-#ifndef CRUNCH
-       { "prompt",     "pr",   BOOL,   CANSET,         o_prompt        },
-#endif
-       { "readonly",   "ro",   BOOL,   CANSET,         o_readonly      },
-       { "remap",      "remap",BOOL,   CANSET,         o_remap         },
-       { "report",     "re",   NUM,    CANSET,         o_report        },
-#ifndef NO_EXTENSIONS
-       { "ruler",      "ru",   BOOL,   CANSET,         o_ruler         },
-#endif
-       { "scroll",     "sc",   NUM,    CANSET,         o_scroll        },
-#ifndef NO_SENTENCE
-       { "sections",   "sect", STR,    CANSET,         o_sections      },
-#endif
-       { "shell",      "sh",   STR,    CANSET,         o_shell         },
-#ifndef NO_SHOWMATCH
-       { "showmatch",  "sm",   BOOL,   CANSET,         o_showmatch     },
-#endif
-#ifndef        NO_SHOWMODE
-       { "showmode",   "smd",  BOOL,   CANSET,         o_smd           },
-#endif
-       { "shiftwidth", "sw",   NUM,    CANSET,         o_shiftwidth    },
-       { "sidescroll", "ss",   NUM,    CANSET,         o_sidescroll    },
-       { "sync",       "sy",   BOOL,   CANSET,         o_sync          },
-       { "tabstop",    "ts",   NUM,    CANSET|MR,      o_tabstop       },
-#ifndef CRUNCH
-       { "taglength",  "tl",   NUM,    CANSET,         o_taglength     },
-#endif
-       { "term",       "te",   STR,    SET,            o_term          },
-#ifndef CRUNCH
-       { "terse",      "tr",   BOOL,   CANSET,         o_terse         },
-       { "timeout",    "to",   BOOL,   CANSET,         o_keytime       },
-#endif
-#ifndef CRUNCH
-       { "window",     "wi",   NUM,    CANSET|MR|WSET, o_window        },
-       { "wrapmargin", "wm",   NUM,    CANSET,         o_wrapmargin    },
-#endif
-       { "wrapscan",   "ws",   BOOL,   CANSET,         o_wrapscan      },
-#ifndef CRUNCH
-       { "writeany",   "wr",   BOOL,   CANSET,         o_writeany      },
-#endif
-       { NULL, NULL, 0, CANSET, NULL }
-};
-
-
-/* This function initializes certain options from environment variables, etc. */
-void initopts()
-{
-       char    *val;
-       int     i;
-
-       /* set some stuff from environment variables */
-#if MSDOS
-       if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
-#else
-       if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
-#endif
-       {
-               strcpy(o_shell, val);
-       }
-
-       strcpy(o_term, termtype);
-#if MSDOS
-       if (strcmp(termtype, "pcbios"))
-       {
-               o_pcbios[0] = FALSE;
-       }
-       else
-       {
-               o_pcbios[0] = TRUE;
-       }
-#endif
-
-#if AMIGA || MSDOS || TOS
-       if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
-       ||  (val = getenv("TEMP")))
-               strcpy(o_directory, val);
-#endif
-
-#ifndef CRUNCH
-       if ((val = getenv("LINES")) && atoi(val) > 4) /* yes, ASSIGNMENT! */
-       {
-               LINES = atoi(val);
-       }
-       if ((val = getenv("COLUMNS")) && atoi(val) > 30) /* yes, ASSIGNMENT! */
-       {
-               COLS = atoi(val);
-       }
-#endif
-       *o_lines = LINES;
-       *o_columns = COLS;
-       *o_scroll = LINES / 2 - 1;
-#ifndef CRUNCH
-       if (o_window[0] == 0)
-       {
-               o_window[0] = o_window[2] = *o_lines;
-       }
-#endif
-
-       /* disable the flash option if we don't know how to do a flash */
-       if (!has_VB)
-       {
-               for (i = 0; opts[i].value != o_flash; i++)
-               {
-               }
-               opts[i].flags &= ~CANSET;
-               *o_flash = FALSE;
-       }
-
-#ifndef NO_DIGRAPH
-# ifdef CS_LATIN1
-       for (i = 0, val = o_flipcase; i < 32; i++)
-       {
-               /* leave out the multiply/divide symbols */
-               if (i == 23)
-                       continue;
-
-               /* add lower/uppercase pair */
-               *val++ = i + 0xe0;
-               *val++ = i + 0xc0;
-       }
-       *val = '\0';
-# endif /* CS_LATIN1 */
-
-       /* initialize the ctype package */
-       _ct_init(o_flipcase);
-#else
-       _ct_init("");
-#endif /* not NO_DIGRAPH */
-}
-
-/* This function lists the current values of all options */
-void dumpopts(all)
-       int     all;    /* boolean: dump all options, or just set ones? */
-{
-#ifndef NO_OPTCOLS
-       int     i, j, k;
-       char    nbuf[4];        /* used for converting numbers to ASCII */
-       int     widths[5];      /* width of each column, including gap */
-       int     ncols;          /* number of columns */
-       int     nrows;          /* number of options per column */
-       int     nset;           /* number of options to be output */
-       int     width;          /* width of a particular option */
-       int     todump[60];     /* indicies of options to be dumped */
-
-       /* step 1: count the number of set options */
-       for (nset = i = 0; opts[i].name; i++)
-       {
-               if (all || (opts[i].flags & SET))
-               {
-                       todump[nset++] = i;
-               }
-       }
-
-       /* step two: try to use as many columns as possible */
-       for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
-       {
-               /* how many would go in this column? */
-               nrows = (nset + ncols - 1) / ncols;
-
-               /* figure out the width of each column */
-               for (i = 0; i < ncols; i++)
-               {
-                       widths[i] = 0;
-                       for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
-                       {
-                               /* figure out the width of a particular option */
-                               switch (opts[todump[k]].type)
-                               {
-                                 case BOOL:
-                                       if (!*opts[todump[k]].value)
-                                               width = 2;
-                                       else
-                                               width = 0;
-                                       break;
-
-                                 case STR:
-                                       width = 3 + strlen(opts[todump[k]].value);
-                                       if (width > MAXWIDTH)
-                                               width = MAXWIDTH;
-                                       break;
-
-                                 case NUM:
-                                       width = 4;
-                                       break;
-                               }
-                               width += strlen(opts[todump[k]].name);
-
-                               /* if this is the widest so far, widen col */
-                               if (width > widths[i])
-                               {
-                                       widths[i] = width;
-                               }
-                       }
-
-               }
-
-               /* if the total width is narrow enough, then use it */
-               for (width = -2, i = 0; i < ncols; i++)
-               {
-                       width += widths[i] + 2;
-               }
-               if (width < COLS - 1)
-               {
-                       break;
-               }
-       }
-
-       /* step 3: output the columns */
-       nrows = (nset + ncols - 1) / ncols;
-       for (i = 0; i < nrows; i++)
-       {
-               for (j = 0; j < ncols; j++)
-               {
-                       /* if we hit the end of the options, quit */
-                       k = i + j * nrows;
-                       if (k >= nset)
-                       {
-                               break;
-                       }
-
-                       /* output this option's value */
-                       width = 0;
-                       switch (opts[todump[k]].type)
-                       {
-                         case BOOL:
-                               if (!*opts[todump[k]].value)
-                               {
-                                       qaddch('n');
-                                       qaddch('o');
-                                       width = 2;
-                               }
-                               qaddstr(opts[todump[k]].name);
-                               width += strlen(opts[todump[k]].name);
-                               break;
-
-                         case NUM:
-                               sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
-                               qaddstr(opts[todump[k]].name);
-                               qaddch('=');
-                               qaddstr(nbuf);
-                               width = 4 + strlen(opts[todump[k]].name);
-                               break;
-
-                         case STR:
-                               qaddstr(opts[todump[k]].name);
-                               qaddch('=');
-                               qaddch('"');
-                               strcpy(tmpblk.c, opts[todump[k]].value);
-                               width = 3 + strlen(tmpblk.c);
-                               if (width > MAXWIDTH)
-                               {
-                                       width = MAXWIDTH;
-                                       strcpy(tmpblk.c + MAXWIDTH - 6, "...");
-                               }
-                               qaddstr(tmpblk.c);
-                               qaddch('"');
-                               width += strlen(opts[todump[k]].name);
-                               break;
-                       }
-
-                       /* pad the field to the correct size */
-                       if (k + nrows <= nset)
-                       {
-                               while (width < widths[j] + 2)
-                               {
-                                       qaddch(' ');
-                                       width++;
-                               }
-                       }
-               }
-               addch('\n');
-               exrefresh();
-       }
-#else
-       int     i;
-       int     col;
-       char    nbuf[4];
-
-       for (i = col = 0; opts[i].name; i++)
-       {
-               /* if not set and not all, ignore this option */
-               if (!all && !(opts[i].flags & SET))
-               {
-                       continue;
-               }
-
-               /* align this option in one of the columns */
-               if (col > 52)
-               {
-                       addch('\n');
-                       col = 0;
-               }
-               else if (col > 26)
-               {
-                       while (col < 52)
-                       {
-                               qaddch(' ');
-                               col++;
-                       }
-               }
-               else if (col > 0)
-               {
-                       while (col < 26)
-                       {
-                               qaddch(' ');
-                               col++;
-                       }
-               }
-
-               switch (opts[i].type)
-               {
-                 case BOOL:
-                       if (!*opts[i].value)
-                       {
-                               qaddch('n');
-                               qaddch('o');
-                               col += 2;
-                       }
-                       qaddstr(opts[i].name);
-                       col += strlen(opts[i].name);
-                       break;
-
-                 case NUM:
-                       sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
-                       qaddstr(opts[i].name);
-                       qaddch('=');
-                       qaddstr(nbuf);
-                       col += 4 + strlen(opts[i].name);
-                       break;
-
-                 case STR:
-                       qaddstr(opts[i].name);
-                       qaddch('=');
-                       qaddch('"');
-                       qaddstr(opts[i].value);
-                       qaddch('"');
-                       col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
-                       break;
-               }
-               exrefresh();
-       }
-       if (col > 0)
-       {
-               addch('\n');
-               exrefresh();
-       }
-#endif
-}
-
-#ifndef NO_MKEXRC
-/* This function saves the current configuration of options to a file */
-void saveopts(fd)
-       int     fd;     /* file descriptor to write to */
-{
-       int     i;
-       char    buf[256], *pos;
-
-       /* write each set options */
-       for (i = 0; opts[i].name; i++)
-       {
-               /* if unset or unsettable, ignore this option */
-               if ((opts[i].flags & (SET|CANSET|NOSAVE)) != (SET|CANSET))
-               {
-                       continue;
-               }
-
-               strcpy(buf, "set ");
-               pos = &buf[4];
-               switch (opts[i].type)
-               {
-                 case BOOL:
-                       if (!*opts[i].value)
-                       {
-                               *pos++='n';
-                               *pos++='o';
-                       }
-                       strcpy(pos, opts[i].name);
-                       strcat(pos, "\n");
-                       break;
-
-                 case NUM:
-                       sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
-                       break;
-
-                 case STR:
-                       sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
-                       break;
-               }
-               twrite(fd, buf, (unsigned)strlen(buf));
-       }
-}
-#endif
-
-
-/* This function changes the values of one or more options. */
-void setopts(assignments)
-       char    *assignments;   /* a string containing option assignments */
-{
-       char    *name;          /* name of variable in assignments */
-       char    *value;         /* value of the variable */
-       char    *scan;          /* used for moving through strings */
-       char    *build;         /* used for copying chars from "scan" */
-       char    *prefix;        /* pointer to "neg" or "no" at front of a boolean */
-       int     quote;          /* boolean: inside '"' quotes? */
-       int     i, j;
-
-#ifndef CRUNCH
-       /* reset the upper limit of "window" option to lines-1 */
-       *o_window = *o_lines - 1;
-#endif
-
-       /* for each assignment... */
-       for (name = assignments; *name; )
-       {
-               /* skip whitespace */
-               if (*name == ' ' || *name == '\t')
-               {
-                       name++;
-                       continue;
-               }
-
-               /* after the name, find the value (if any) */
-               for (scan = name; isalnum(*scan); scan++)
-               {
-               }
-               if (*scan == '=')
-               {
-                       *scan++ = '\0';
-                       value = build = scan;
-                       for (quote = FALSE; *scan && (quote || !isspace(*scan)); scan++)
-                       {
-                               if (*scan == '"')
-                               {
-                                       quote = !quote;
-                               }
-                               else if (*scan == '\\' && scan[1])
-                               {
-                                       *build++ = *++scan;
-                               }
-                               else
-                               {
-                                       *build++ = *scan;
-                               }
-                       }
-                       if (*scan)
-                               scan++;
-                       *build = '\0';
-               }
-               else /* no "=" so it is probably boolean... */
-               {
-                       if (*scan)
-                       {
-                               *scan++ = '\0';
-                       }
-                       value = NULL;
-                       prefix = name;
-#ifndef CRUNCH
-                       if (!strcmp(name, "novice"))
-                               /* don't check for a "no" prefix */;
-                       else
-#endif
-                       if (prefix[0] == 'n' && prefix[1] == 'o')
-                               name += 2;
-                       else if (prefix[0] == 'n' && prefix[1] == 'e' && prefix[2] == 'g')
-                               name += 3;
-               }
-
-               /* find the variable */
-               for (i = 0;
-                    opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
-                    i++)
-               {
-               }
-
-               /* change the variable */
-               if (!opts[i].name)
-               {
-                       msg("invalid option name \"%s\"", name);
-               }
-               else if ((opts[i].flags & CANSET) != CANSET)
-               {
-                       msg("option \"%s\" can't be altered", name);
-               }
-               else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
-               {
-                       msg("option \"%s\" can only be set in a %s file", name, EXRC);
-               }
-               else if (value)
-               {
-                       switch (opts[i].type)
-                       {
-                         case BOOL:
-                               msg("option \"[no]%s\" is boolean", name);
-                               break;
-
-                         case NUM:
-                               j = atoi(value);
-                               if (j == 0 && *value != '0')
-                               {
-                                       msg("option \"%s\" must have a numeric value", name);
-                               }
-                               else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
-                               {
-                                       msg("option \"%s\" must have a value between %d and %d",
-                                               name, opts[i].value[1], opts[i].value[2] & 0xff);
-                               }
-                               else
-                               {
-                                       *opts[i].value = atoi(value);
-                                       opts[i].flags |= SET;
-                               }
-                               break;
-
-                         case STR:
-                               strcpy(opts[i].value, value);
-                               opts[i].flags |= SET;
-                               break;
-                       }
-                       if (opts[i].flags & MR)
-                       {
-                               redraw(MARK_UNSET, FALSE);
-                       }
-#ifndef CRUNCH
-                       if (opts[i].flags & WSET)
-                       {
-                               wset = TRUE;
-                       }
-#endif
-               }
-               else /* valid option, no value */
-               {
-                       if (opts[i].type == BOOL)
-                       {
-                               if (prefix == name)
-                                       *opts[i].value = TRUE;
-                               else if (prefix[1] == 'o')
-                                       *opts[i].value = FALSE;
-                               else
-                                       *opts[i].value = !*opts[i].value;
-
-                               opts[i].flags |= SET;
-                               if (opts[i].flags & MR)
-                               {
-                                       redraw(MARK_UNSET, FALSE);
-                               }
-                       }
-                       else
-                       {
-                               msg("option \"%s\" must be given a value", name);
-                       }
-               }
-
-               /* move on to the next option */
-               name = scan;
-       }
-
-       /* special processing ... */
-
-#ifndef CRUNCH
-       /* if "novice" is set, then ":set report=1 showmode nomagic" */
-       if (*o_novice)
-       {
-               *o_report = 1;
-# ifndef NO_SHOWMODE
-               *o_smd = TRUE;
-# endif
-# ifndef NO_MAGIC
-               *o_magic = FALSE;
-# endif
-       }
-#endif
-
-       /* if "readonly" then set the READONLY flag for this file */
-       if (*o_readonly)
-       {
-               setflag(file, READONLY);
-       }
-
-#ifndef NO_DIGRAPH
-       /* re-initialize the ctype package */
-       _ct_init(o_flipcase);
-#endif /* not NO_DIGRAPH */
-
-       /* copy o_lines and o_columns into LINES and COLS */
-       LINES = (*o_lines & 255);
-       COLS = (*o_columns & 255);
-}
diff --git a/commands/elvis/prsvunix.c b/commands/elvis/prsvunix.c
deleted file mode 100644 (file)
index 4af722e..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* prsvunix.c */
-
-/* This file contains the UNIX-specific parts of the "elvprsv" program. */
-
-#if OSK
-#define ELVPRSV
-#include "osk.c"
-#else
-#include <sys/stat.h>
-#include <pwd.h>
-#endif
-
-/* This variable is used to add extra error messages for mail sent to root */
-char *ps;
-
-/* This function returns the login name of the owner of a file */
-char *ownername(filename)
-       char    *filename;      /* name of a file */
-{
-       struct stat     st;
-       struct passwd   *pw;
-
-       /* stat the file, to get its uid */
-       if (stat(filename, &st) < 0)
-       {
-               ps = "stat() failed";
-               return "root";
-       }
-
-       /* get the /etc/passwd entry for that user */
-       pw = getpwuid(st.st_uid);
-       if (!pw)
-       {
-               ps = "uid not found in password file";
-               return "root";
-       }
-
-       /* return the user's name */
-       return pw->pw_name;
-}
-
-
-/* This function sends a mail message to a given user, saying that a file
- * has been preserved.
- */
-void mail(user, file, when)
-       char    *user;  /* name of user who should receive the mail */
-       char    *file;  /* name of original text file that was preserved */
-       char    *when;  /* description of why the file was preserved */
-{
-       char    cmd[80];/* buffer used for constructing a "mail" command */
-       FILE    *m, *popen();   /* stream used for giving text to the "mail" program */
-       char    *base;  /* basename of the file */
-
-       /* separate the directory name from the basename. */
-       for (base = file + strlen(file); --base > file && *base != SLASH; )
-       {
-       }
-       if (*base == SLASH)
-       {
-               *base++ = '\0';
-       }
-
-       /* for anonymous buffers, pretend the name was "foo" */
-       if (!strcmp(base, "*"))
-       {
-               base = "foo";
-       }
-
-       /* open a pipe to the "mail" program */
-#if OSK
-       sprintf(cmd, "mail \"-s=%s preserved!\" %s", base, user);
-#else /* ANY_UNIX */
-       sprintf(cmd, "mail %s >/dev/null 2>/dev/null", user);
-#endif
-       m = popen(cmd, "w");
-       if (!m)
-       {
-               /* Can't send mail!  Hope the user figures it out. */
-               return;
-       }
-
-       /* Tell the user that the file was preserved */
-       fprintf(m, "A version of your file \"%s%c%s\"\n", file, SLASH, base);
-       fprintf(m, "was preserved when %s.\n", when);
-       fprintf(m, "To recover this file, do the following:\n");
-       fprintf(m, "\n");
-#if OSK
-       fprintf(m, "     chd %s\n", file);
-#else /* ANY_UNIX */
-       fprintf(m, "     cd %s\n", file);
-#endif
-       fprintf(m, "     elvrec %s\n", base);
-       fprintf(m, "\n");
-       fprintf(m, "With fond wishes for a speedy recovery,\n");
-       fprintf(m, "                                    Elvis\n");
-       if (ps)
-       {
-               fprintf(m, "\nP.S. %s\n", ps);
-               ps = (char *)0;
-       }
-
-       /* close the stream */
-       pclose(m);
-}
diff --git a/commands/elvis/recycle.c b/commands/elvis/recycle.c
deleted file mode 100644 (file)
index 4216036..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/* recycle.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the functions perform garbage collection and allocate
- * reusable blocks.
- */
-
-#include "config.h"
-#include "vi.h"
-
-#ifndef NO_RECYCLE
-/* this whole file would have be skipped if NO_RECYCLE is defined */
-
-
-#define BTST(bitno, byte)      ((byte) & (1 << (bitno)))
-#define BSET(bitno, byte)      ((byte) |= (1 << (bitno)))
-#define BCLR(bitno, byte)      ((byte) &= ~(1 << (bitno)))
-
-#define TST(blkno)             ((blkno) < MAXBIT ? BTST((blkno) & 7, bitmap[(blkno) >> 3]) : 1)
-#define SET(blkno)             if ((blkno) < MAXBIT) BSET((blkno) & 7, bitmap[(blkno) >> 3])
-#define CLR(blkno)             if ((blkno) < MAXBIT) BCLR((blkno) & 7, bitmap[(blkno) >> 3])
-
-/* bitmap of free blocks in first 4096k of tmp file */
-static unsigned char bitmap[512];
-#define MAXBIT (sizeof bitmap << 3)
-
-/* this function locates all free blocks in the current tmp file */
-void garbage()
-{
-       int     i;
-       BLK     oldhdr;
-
-       /* start by assuming every block is free */
-       for (i = 0; i < sizeof bitmap; i++)
-       {
-               bitmap[i] = 255;
-       }
-
-       /* header blocks aren't free */
-#ifndef lint
-       CLR(0);
-       CLR(1);
-#endif
-
-       /* blocks needed for current hdr aren't free */
-       for (i = 1; i < MAXBLKS; i++)
-       {
-               CLR(hdr.n[i]);
-       }
-
-       /* blocks needed for undo version aren't free */
-       lseek(tmpfd, 0L, 0);
-       if (read(tmpfd, &oldhdr, (unsigned)sizeof oldhdr) != sizeof oldhdr)
-       {
-               msg("garbage() failed to read oldhdr??");
-               for (i = 0; i < sizeof bitmap; i++)
-               {
-                       bitmap[i] = 0;
-               }
-               return;
-       }
-       for (i = 1; i < MAXBLKS; i++)
-       {
-               CLR(oldhdr.n[i]);
-       }
-
-       /* blocks needed for cut buffers aren't free */
-       for (i = cutneeds(&oldhdr) - 1; i >= 0; i--)
-       {
-               CLR(oldhdr.n[i]);
-       }
-}
-
-/* This function allocates the first available block in the tmp file */
-long allocate()
-{
-       int     i;
-       long    offset;
-
-       /* search for the first byte with a free bit set */
-       for (i = 0; i < sizeof bitmap && bitmap[i] == 0; i++)
-       {
-       }
-
-       /* if we hit the end of the bitmap, return the end of the file */
-       if (i == sizeof bitmap)
-       {
-               offset = lseek(tmpfd, 0L, 2);
-       }
-       else /* compute the offset for the free block */
-       {
-               for (i <<= 3; TST(i) == 0; i++)
-               {
-               }
-               offset = (long)i * (long)BLKSIZE;
-
-               /* mark the block as "allocated" */
-               CLR(i);
-       }
-
-       return offset;
-}
-
-#endif
-
-#ifdef DEBUG
-# include <stdio.h>
-# undef malloc
-# undef free
-# define MEMMAGIC 0x19f72cc0L
-# define MAXALLOC 800
-static char *allocated[MAXALLOC];
-static char *fromfile[MAXALLOC];
-static int  fromline[MAXALLOC]; 
-static int  sizes[MAXALLOC];
-
-char *dbmalloc(size, file, line)
-       int     size;
-       char    *file;
-       int     line;
-{
-       char    *ret;
-       int     i;
-
-       size = size + sizeof(long) - (size % sizeof(long));
-       ret = (char *)malloc(size + 2 * sizeof(long)) + sizeof(long);
-       for (i = 0; i < MAXALLOC && allocated[i]; i++)
-       {
-       }
-       if (i == MAXALLOC)
-       {
-               endwin();
-               fprintf(stderr, "\r\n%s(%d): Too many malloc calls!\n", file, line);
-               abort();
-       }
-       sizes[i] = size/sizeof(long);
-       allocated[i] = ret;
-       fromfile[i] = file;
-       fromline[i] = line;
-       ((long *)ret)[-1] = MEMMAGIC;
-       ((long *)ret)[sizes[i]] = MEMMAGIC;
-       return ret;
-}
-
-dbfree(ptr, file, line)
-       char    *ptr;
-       char    *file;
-       int     line;
-{
-       int     i;
-
-       for (i = 0; i < MAXALLOC && allocated[i] != ptr; i++)
-       {
-       }
-       if (i == MAXALLOC)
-       {
-               endwin();
-               fprintf(stderr, "\r\n%s(%d): attempt to free mem that wasn't allocated\n", file, line);
-               abort();
-       }
-       allocated[i] = (char *)0;
-       if (((long *)ptr)[-1] != MEMMAGIC)
-       {
-               endwin();
-               fprintf(stderr, "\r\n%s(%d): underflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
-               abort();
-       }
-       if (((long *)ptr)[sizes[i]] != MEMMAGIC)
-       {
-               endwin();
-               fprintf(stderr, "\r\n%s(%d): overflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
-               abort();
-       }
-       free(ptr - sizeof(long));
-}
-#endif
diff --git a/commands/elvis/redraw.c b/commands/elvis/redraw.c
deleted file mode 100644 (file)
index ae923cf..0000000
+++ /dev/null
@@ -1,1295 +0,0 @@
-/* redraw.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains functions that draw text on the screen.  The major entry
- * points are:
- *     redrawrange()   - called from modify.c to give hints about what parts
- *                       of the screen need to be redrawn.
- *     redraw()        - redraws the screen (or part of it) and positions
- *                       the cursor where it belongs.
- *     idx2col()       - converts a markidx() value to a logical column number.
- */
-
-#include "config.h"
-#include "vi.h"
-
-/* This variable contains the line number that smartdrawtext() knows best */
-static long smartlno;
-
-/* This function remembers where changes were made, so that the screen can be
- * redraw in a more efficient manner.
- */
-static long    redrawafter;    /* line# of first line that must be redrawn */
-static long    preredraw;      /* line# of last line changed, before change */
-static long    postredraw;     /* line# of last line changed, after change */
-static int     mustredraw;     /* boolean: anything forcing a screen update? */
-void redrawrange(after, pre, post)
-       long    after;  /* lower bound of redrawafter */
-       long    pre;    /* upper bound of preredraw */
-       long    post;   /* upper bound of postredraw */
-{
-       if (after == redrawafter)
-       {
-               /* multiple insertions/deletions at the same place -- combine
-                * them
-                */
-               preredraw -= (post - pre);
-               if (postredraw < post)
-               {
-                       preredraw += (post - postredraw);
-                       postredraw = post;
-               }
-               if (redrawafter > preredraw)
-               {
-                       redrawafter = preredraw;
-               }
-               if (redrawafter < 1L)
-               {
-                       redrawafter = 0L;
-                       preredraw = postredraw = INFINITY;
-               }
-       }
-       else if (postredraw > 0L)
-       {
-               /* multiple changes in different places -- redraw everything
-                * after "after".
-                */
-               postredraw = preredraw = INFINITY;
-               if (after < redrawafter)
-                       redrawafter = after;
-       }
-       else
-       {
-               /* first change */
-               redrawafter = after;
-               preredraw = pre;
-               postredraw = post;
-       }
-       mustredraw = TRUE;
-}
-
-
-#ifndef NO_CHARATTR
-/* see if a given line uses character attribute strings */
-static int hasattr(lno, text)
-       long            lno;    /* the line# of the cursor */
-       REG char        *text;  /* the text of the line, from fetchline */
-{
-       static long     plno;   /* previous line number */
-       static long     chgs;   /* previous value of changes counter */
-       static int      panswer;/* previous answer */
-       char            *scan;
-
-       /* if charattr is off, then the answer is "no, it doesn't" */
-       if (!*o_charattr)
-       {
-               chgs = 0; /* <- forces us to check if charattr is later set */
-               return FALSE;
-       }
-
-       /* if we already know the answer, return it... */
-       if (lno == plno && chgs == changes)
-       {
-               return panswer;
-       }
-
-       /* get the line & look for "\fX" */
-       if (!text[0] || !text[1] || !text[2])
-       {
-               panswer = FALSE;
-       }
-       else
-       {
-               for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
-               {
-               }
-               panswer = (scan[2] != '\0');
-       }
-
-       /* save the results */
-       plno = lno;
-       chgs = changes;
-
-       /* return the results */
-       return panswer;
-}
-#endif
-
-
-#ifndef NO_VISIBLE
-/* This function checks to make sure that the correct lines are shown in
- * reverse-video.  This is used to handle the "v" and "V" commands.
- */
-static long    vizlow, vizhigh;        /* the starting and ending lines */
-static int     vizleft, vizright;      /* starting & ending indicies */
-static int     vizchange;              /* boolean: must use stupid drawtext? */
-static void setviz(curs)
-       MARK            curs;
-{
-       long            newlow, newhigh;
-       long            extra = 0L;
-
-       /* for now, assume the worst... */
-       vizchange = TRUE;
-
-       /* set newlow & newhigh according to V_from and cursor */
-       if (!V_from)
-       {
-               /* no lines should have reverse-video */
-               if (vizlow)
-               {
-                       redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
-                       vizlow = vizhigh = 0L;
-               }
-               else
-               {
-                       vizchange = FALSE;
-               }
-               return;
-       }
-
-       /* figure out which lines *SHOULD* have hilites */
-       if (V_from < curs)
-       {
-               newlow = markline(V_from);
-               newhigh = markline(curs);
-               vizleft = markidx(V_from);
-               vizright = markidx(curs) + 1;
-       }
-       else
-       {
-               newlow = markline(curs);
-               newhigh = markline(V_from);
-               vizleft = markidx(curs);
-               vizright = markidx(V_from) + 1;
-       }
-
-       /* adjust for line-mode hiliting */
-       if (V_linemd)
-       {
-               vizleft = 0;
-               vizright = BLKSIZE - 1;
-       }
-       else
-       {
-               extra = 1L;
-       }
-
-       /* arrange for the necessary lines to be redrawn */
-       if (vizlow == 0L)
-       {
-               /* just starting to redraw */
-               redrawrange(newlow, newhigh, newhigh);
-       }
-       else
-       {
-               /* Were new lines added/removed at the front? */
-               if (newlow != vizlow)
-               {
-                       if (newlow < vizlow)
-                               redrawrange(newlow, vizlow + extra, vizlow + extra);
-                       else
-                               redrawrange(vizlow, newlow + extra, newlow + extra);
-               }
-
-               /* Were new lines added/removed at the back? */
-               if (newhigh != vizhigh)
-               {
-                       if (newhigh < vizhigh)
-                               redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
-                       else
-                               redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
-               }
-       }
-
-       /* remember which lines will contain hilighted text now */
-       vizlow = newlow;
-       vizhigh = newhigh;
-}
-#endif /* !NO_VISIBLE */
-
-
-/* This function converts a MARK to a column number.  It doesn't automatically
- * adjust for leftcol; that must be done by the calling function
- */
-int idx2col(curs, text, inputting)
-       MARK            curs;   /* the line# & index# of the cursor */
-       REG char        *text;  /* the text of the line, from fetchline */
-       int             inputting;      /* boolean: called from input() ? */
-{
-       static MARK     pcursor;/* previous cursor, for possible shortcut */
-       static MARK     pcol;   /* column number for pcol */
-       static long     chgs;   /* previous value of changes counter */
-       REG int         col;    /* used to count column numbers */
-       REG int         idx;    /* used to count down the index */
-       REG int         i;
-
-       /* for now, assume we have to start counting at the left edge */
-       col = 0;
-       idx = markidx(curs);
-
-       /* if the file hasn't changed & line number is the same & it has no
-        * embedded character attribute strings, can we do shortcuts?
-        */
-       if (chgs == changes
-        && !((curs ^ pcursor) & ~(BLKSIZE - 1))
-#ifndef NO_CHARATTR
-        && !hasattr(markline(curs), text)
-#endif
-       )
-       {
-               /* no movement? */
-               if (curs == pcursor)
-               {
-                       /* return the column of the char; for tabs, return its last column */
-                       if (text[idx] == '\t' && !inputting && !*o_list)
-                       {
-                               return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
-                       }
-                       else
-                       {
-                               return pcol;
-                       }
-               }
-
-               /* movement to right? */
-               if (curs > pcursor)
-               {
-                       /* start counting from previous place */
-                       col = pcol;
-                       idx = markidx(curs) - markidx(pcursor);
-                       text += markidx(pcursor);
-               }
-       }
-
-       /* count over to the char after the idx position */
-       while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
-       {
-               if (i == '\t' && !*o_list)
-               {
-                       col += *o_tabstop;
-                       col -= col % *o_tabstop;
-               }
-               else if (i >= '\0' && i < ' ' || i == '\177')
-               {
-                       col += 2;
-               }
-#ifndef NO_CHARATTR
-               else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
-               {
-                       text += 2; /* plus one more at bottom of loop */
-                       idx -= 2;
-               }                       
-#endif
-               else
-               {
-                       col++;
-               }
-               text++;
-               idx--;
-       }
-
-       /* save stuff to speed next call */
-       pcursor = curs;
-       pcol = col;
-       chgs = changes;
-
-       /* return the column of the char; for tabs, return its last column */
-       if (*text == '\t' && !inputting && !*o_list)
-       {
-               return col + *o_tabstop - (col % *o_tabstop) - 1;
-       }
-       else
-       {
-               return col;
-       }
-}
-
-
-/* This function is similar to idx2col except that it takes care of sideways
- * scrolling - for the given line, at least.
- */
-int mark2phys(m, text, inputting)
-       MARK    m;              /* a mark to convert */
-       char    *text;          /* the line that m refers to */
-       int     inputting;      /* boolean: caled from input() ? */
-{
-       int     i;
-
-       i = idx2col(m, text, inputting);
-       while (i < leftcol)
-       {
-               leftcol -= *o_sidescroll;
-               mustredraw = TRUE;
-               redrawrange(1L, INFINITY, INFINITY);
-       }
-       while (i > rightcol)
-       {
-               leftcol += *o_sidescroll;
-               mustredraw = TRUE;
-               redrawrange(1L, INFINITY, INFINITY);
-       }
-       physrow = markline(m) - topline;
-       physcol = i - leftcol;
-       if (*o_number)
-               physcol += 8;
-
-       return physcol;
-}
-
-/* This function draws a single line of text on the screen.  The screen's
- * cursor is assumed to be located at the leftmost column of the appropriate
- * row.
- */
-static void drawtext(text, lno, clr)
-       REG char        *text;  /* the text to draw */
-       long            lno;    /* the number of the line to draw */
-       int             clr;    /* boolean: do a clrtoeol? */
-{
-       REG int         col;    /* column number */
-       REG int         i;
-       REG int         tabstop;        /* *o_tabstop */
-       REG int         limitcol;       /* leftcol or leftcol + COLS */
-       int             abnormal;       /* boolean: charattr != A_NORMAL? */
-#ifndef NO_VISIBLE
-       int             rev;            /* boolean: standout mode, too? */
-       int             idx = 0;
-#endif
-       char            numstr[9];
-
-       /* show the line number, if necessary */
-       if (*o_number)
-       {
-               sprintf(numstr, "%6ld |", lno);
-               qaddstr(numstr);
-       }
-
-#ifndef NO_SENTENCE
-       /* if we're hiding format lines, and this is one of them, then hide it */
-       if (*o_hideformat && *text == '.')
-       {
-               clrtoeol();
-#if OSK
-               qaddch('\l');
-#else
-               qaddch('\n');
-#endif
-               return;
-       }
-#endif
-
-       /* move some things into registers... */
-       limitcol = leftcol;
-       tabstop = *o_tabstop;
-       abnormal = FALSE;
-
-#ifndef CRUNCH
-       if (clr)
-               clrtoeol();
-#endif
-
-       /* skip stuff that was scrolled off left edge */
-       for (col = 0;
-            (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
-            text++)
-       {
-#ifndef NO_VISIBLE
-               idx++;
-#endif
-               if (i == '\t' && !*o_list)
-               {
-                       col = col + tabstop - (col % tabstop);
-               }
-               else if (i >= 0 && i < ' ' || i == '\177')
-               {
-                       col += 2;
-               }
-#ifndef NO_CHARATTR
-               else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
-               {
-                       text += 2; /* plus one more as part of "for" loop */
-
-                       /* since this attribute might carry over, we need it */
-                       switch (*text)
-                       {
-                         case 'R':
-                         case 'P':
-                               attrset(A_NORMAL);
-                               abnormal = FALSE;
-                               break;
-
-                         case 'B':
-                               attrset(A_BOLD);
-                               abnormal = TRUE;
-                               break;
-
-                         case 'U':
-                               attrset(A_UNDERLINE);
-                               abnormal = TRUE;
-                               break;
-
-                         case 'I':
-                               attrset(A_ALTCHARSET);
-                               abnormal = TRUE;
-                               break;
-                       }
-               }
-#endif
-               else
-               {
-                       col++;
-               }
-       }
-
-#ifndef NO_VISIBLE
-       /* Should we start hiliting at the first char of this line? */
-       if ((lno > vizlow && lno <= vizhigh
-           || lno == vizlow && vizleft < idx)
-          && !(lno == vizhigh && vizright < idx))
-       {
-               do_VISIBLE();
-               rev = TRUE;
-       }
-#endif
-
-       /* adjust for control char that was partially visible */
-       while (col > limitcol)
-       {
-               qaddch(' ');
-               limitcol++;
-       }
-
-       /* now for the visible characters */
-       limitcol = leftcol + COLS;
-       if (*o_number)
-               limitcol -= 8;
-       for (; (i = *text) && col < limitcol; text++)
-       {
-#ifndef NO_VISIBLE
-               /* maybe turn hilite on/off in the middle of the line */
-               if (lno == vizlow && vizleft == idx)
-               {
-                       do_VISIBLE();
-                       rev = TRUE;
-               }
-               if (lno == vizhigh && vizright == idx)
-               {
-                       do_SE();
-                       rev = FALSE;
-               }
-               idx++;
-
-               /* if hiliting, never emit physical tabs */
-               if (rev && i == '\t' && !*o_list)
-               {
-                       i = col + tabstop - (col % tabstop);
-                       do
-                       {
-                               qaddch(' ');
-                               col++;
-                       } while (col < i);
-               }
-               else
-#endif /* !NO_VISIBLE */
-               if (i == '\t' && !*o_list)
-               {
-                       i = col + tabstop - (col % tabstop);
-                       if (i < limitcol)
-                       {
-#ifdef CRUNCH
-                               if (!clr && has_PT && !((i - leftcol) & 7))
-#else
-                               if (has_PT && !((i - leftcol) & 7))
-#endif
-                               {
-                                       do
-                                       {
-                                               qaddch('\t');
-                                               col += 8; /* not exact! */
-                                       } while (col < i);
-                                       col = i; /* NOW it is exact */
-                               }
-                               else
-                               {
-                                       do
-                                       {
-                                               qaddch(' ');
-                                               col++;
-                                       } while (col < i);
-                               }
-                       }
-                       else /* tab ending after screen? next line! */
-                       {
-                               col = limitcol;
-                               if (has_AM)
-                               {
-                                       addch('\n');    /* GB */
-                               }
-                       }
-               }
-               else if (i >= 0 && i < ' ' || i == '\177')
-               {
-                       col += 2;
-                       qaddch('^');
-                       if (col <= limitcol)
-                       {
-                               qaddch(i ^ '@');
-                       }
-               }
-#ifndef NO_CHARATTR
-               else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
-               {
-                       text += 2; /* plus one more as part of "for" loop */
-                       switch (*text)
-                       {
-                         case 'R':
-                         case 'P':
-                               attrset(A_NORMAL);
-                               abnormal = FALSE;
-                               break;
-
-                         case 'B':
-                               attrset(A_BOLD);
-                               abnormal = TRUE;
-                               break;
-
-                         case 'U':
-                               attrset(A_UNDERLINE);
-                               abnormal = TRUE;
-                               break;
-
-                         case 'I':
-                               attrset(A_ALTCHARSET);
-                               abnormal = TRUE;
-                               break;
-                       }
-               }
-#endif
-               else
-               {
-                       col++;
-                       qaddch(i);
-               }
-       }
-
-       /* get ready for the next line */
-#ifndef NO_CHARATTR
-       if (abnormal)
-       {
-               attrset(A_NORMAL);
-       }
-#endif
-       if (*o_list && col < limitcol)
-       {
-               qaddch('$');
-               col++;
-       }
-
-#ifndef NO_VISIBLE
-       /* did we hilite this whole line?  If so, STOP! */
-       if (rev)
-       {
-               do_SE();
-       }
-#endif
-
-#ifdef CRUNCH
-       if (clr && col < limitcol)
-       {
-               clrtoeol();
-       }
-#endif
-       if (!has_AM || col < limitcol)
-       {
-               addch('\n');
-       }
-
-       wqrefresh();
-}
-
-
-#ifndef CRUNCH
-static void nudgecursor(same, scan, new, lno)
-       int     same;   /* number of chars to be skipped over */
-       char    *scan;  /* where the same chars end */
-       char    *new;   /* where the visible part of the line starts */
-       long    lno;    /* line number of this line */
-{
-       int     col;
-
-       if (same > 0)
-       {
-               if (same < 5)
-               {
-                       /* move the cursor by overwriting */
-                       while (same > 0)
-                       {
-                               qaddch(scan[-same]);
-                               same--;
-                       }
-               }
-               else
-               {
-                       /* move the cursor by calling move() */
-                       col = (int)(scan - new);
-                       if (*o_number)
-                               col += 8;
-                       move((int)(lno - topline), col);
-               }
-       }
-}
-#endif /* not CRUNCH */
-
-/* This function draws a single line of text on the screen, possibly with
- * some cursor optimization.  The cursor is repositioned before drawing
- * begins, so its position before doesn't really matter.
- */
-static void smartdrawtext(text, lno, showit)
-       REG char        *text;  /* the text to draw */
-       long            lno;    /* line number of the text */
-       int             showit; /* boolean: output line? (else just remember it) */
-{
-#ifdef CRUNCH
-       move((int)(lno - topline), 0);
-       if (showit)
-       {
-               drawtext(text, lno, TRUE);
-       }
-#else /* not CRUNCH */
-       static char     old[256];       /* how the line looked last time */
-       char            new[256];       /* how it looks now */
-       char            *build;         /* used to put chars into new[] */
-       char            *scan;          /* used for moving thru new[] or old[] */
-       char            *end;           /* last non-blank changed char */
-       char            *shift;         /* used to insert/delete chars */
-       int             same;           /* length of a run of unchanged chars */
-       int             limitcol;
-       int             col;
-       int             i;
-       char            numstr[9];
-
-# ifndef NO_CHARATTR
-       /* if this line has attributes, do it the dumb way instead */
-       if (hasattr(lno, text))
-       {
-               move((int)(lno - topline), 0);
-               drawtext(text, lno, TRUE);
-               return;
-       }
-# endif
-# ifndef NO_SENTENCE
-       /* if this line is a format line, & we're hiding format lines, then
-        * let the dumb drawtext() function handle it
-        */
-       if (*o_hideformat && *text == '.')
-       {
-               move((int)(lno - topline), 0);
-               drawtext(text, lno, TRUE);
-               return;
-       }
-# endif
-# ifndef NO_VISIBLE
-       if (vizchange)
-       {
-               move((int)(lno - topline), 0);
-               drawtext(text, lno, TRUE);
-               smartlno = 0L;
-               return;
-       }
-# endif
-
-       /* skip stuff that was scrolled off left edge */
-       limitcol = leftcol;
-       for (col = 0;
-            (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
-            text++)
-       {
-               if (i == '\t' && !*o_list)
-               {
-                       col = col + *o_tabstop - (col % *o_tabstop);
-               }
-               else if (i >= 0 && i < ' ' || i == '\177')
-               {
-                       col += 2;
-               }
-               else
-               {
-                       col++;
-               }
-       }
-
-       /* adjust for control char that was partially visible */
-       build = new;
-       while (col > limitcol)
-       {
-               *build++ = ' ';
-               limitcol++;
-       }
-
-       /* now for the visible characters */
-       limitcol = leftcol + COLS;
-       if (*o_number)
-               limitcol -= 8;
-       for (; (i = *text) && col < limitcol; text++)
-       {
-               if (i == '\t' && !*o_list)
-               {
-                       i = col + *o_tabstop - (col % *o_tabstop);
-                       while (col < i && col < limitcol)
-                       {
-                               *build++ = ' ';
-                               col++;
-                       }
-               }
-               else if (i >= 0 && i < ' ' || i == '\177')
-               {
-                       col += 2;
-                       *build++ = '^';
-                       if (col <= limitcol)
-                       {
-                               *build++ = (i ^ '@');
-                       }
-               }
-               else
-               {
-                       col++;
-                       *build++ = i;
-               }
-       }
-       if (col < limitcol && *o_list)
-       {
-               *build++ = '$';
-               col++;
-       }
-       end = build;
-       while (col < limitcol)
-       {
-               *build++ = ' ';
-               col++;
-       }
-
-       /* if we're just supposed to remember this line, then remember it */
-       if (!showit)
-       {
-               smartlno = lno;
-               strncpy(old, new, COLS);
-               return;
-       }
-
-       /* locate the last non-blank character */
-       while (end > new && end[-1] == ' ')
-       {
-               end--;
-       }
-
-       /* can we optimize the displaying of this line? */
-       if (lno != smartlno)
-       {
-               /* nope, can't optimize - different line */
-               move((int)(lno - topline), 0);
-
-               /* show the line number, if necessary */
-               if (*o_number)
-               {
-                       sprintf(numstr, "%6ld |", lno);
-                       qaddstr(numstr);
-               }
-
-               /* show the new line */
-               for (scan = new, build = old; scan < end; )
-               {
-                       qaddch(*scan);
-                       *build++ = *scan++;
-               }
-               if (end < new + COLS - (*o_number ? 8 : 0))
-               {
-                       clrtoeol();
-                       while (build < old + COLS)
-                       {
-                               *build++ = ' ';
-                       }
-               }
-               smartlno = lno;
-               return;
-       }
-
-       /* skip any initial unchanged characters */
-       for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
-       {
-       }
-       i = (scan - new);
-       if (*o_number)
-               i += 8;
-       move((int)(lno - topline), i);
-
-       /* The in-between characters must be changed */
-       same = 0;
-       while (scan < end)
-       {
-               /* is this character a match? */
-               if (scan[0] == build[0])
-               {
-                       same++;
-               }
-               else /* do we want to insert? */
-               if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
-               {
-                       nudgecursor(same, scan, new, lno);
-                       same = 0;
-
-                       insch(*scan);
-                       for (shift = old + COLS; --shift > build; )
-                       {
-                               shift[0] = shift[-1];
-                       }
-                       *build = *scan;
-               }
-               else /* do we want to delete? */
-               if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
-               {
-                       nudgecursor(same, scan, new, lno);
-                       same = 0;
-
-                       delch();
-                       same++;
-                       for (shift = build; shift < old + COLS - 1; shift++)
-                       {
-                               shift[0] = shift[1];
-                       }
-                       if (*o_number)
-                               shift -= 8;
-                       *shift = ' ';
-               }
-               else /* we must overwrite */
-               {
-                       nudgecursor(same, scan, new, lno);
-                       same = 0;
-
-                       addch(*scan);
-                       *build = *scan;
-               }
-
-               build++;
-               scan++;
-       }
-
-       /* maybe clear to EOL */
-       end = old + COLS - (*o_number ? 8 : 0);
-       while (build < end && *build == ' ')
-       {
-               build++;
-       }
-       if (build < end)
-       {
-               nudgecursor(same, scan, new, lno);
-               same = 0;
-
-               clrtoeol();
-               while (build < old + COLS)
-               {
-                       *build++ = ' ';
-               }
-       }
-#endif /* not CRUNCH */
-}
-
-
-/* This function is used in visual mode for drawing the screen (or just parts
- * of the screen, if that's all thats needed).  It also takes care of
- * scrolling.
- */
-void redraw(curs, inputting)
-       MARK    curs;           /* where to leave the screen's cursor */
-       int     inputting;      /* boolean: being called from input() ? */
-{
-       char            *text;          /* a line of text to display */
-       static long     chgs;           /* previous changes level */
-       long            l;
-       int             i;
-#ifndef CRUNCH
-       static long     showtop;        /* top line in window */
-       static long     showbottom;     /* bottom line in window */
-#endif
-
-       /* if curs == MARK_UNSET, then we should reset internal vars */
-       if (curs == MARK_UNSET)
-       {
-               if (topline < 1 || topline > nlines)
-               {
-                       topline = 1L;
-               }
-               else
-               {
-                       move(LINES - 1, 0);
-                       clrtoeol();
-               }
-               leftcol = 0;
-               mustredraw = TRUE;
-               redrawafter = INFINITY;
-               preredraw = 0L;
-               postredraw = 0L;
-               chgs = 0;
-               smartlno = 0L;
-#ifndef NO_VISIBLE
-               vizlow = vizhigh = 0L;
-               vizchange = FALSE;
-#endif
-#ifndef CRUNCH
-               showtop = 0;
-               showbottom = INFINITY;
-#endif
-               return;
-       }
-
-#ifndef NO_VISIBLE
-       /* adjustments to hilited area may force extra lines to be redrawn. */
-       setviz(curs);
-#endif
-
-       /* figure out which column the cursor will be in */
-       l = markline(curs);
-       text = fetchline(l);
-       mark2phys(curs, text, inputting);
-
-#ifndef NO_COLOR
-       fixcolor();
-#endif
-
-       /* adjust topline, if necessary, to get the cursor on the screen */
-       if (l >= topline && l <= botline)
-       {
-               /* it is on the screen already */
-
-               /* if the file was changed but !mustredraw, then redraw line */
-               if (!mustredraw && (chgs != changes
-#ifndef NO_VISIBLE
-                       || V_from
-#endif
-#ifndef CRUNCH
-                       || l < showtop || l > showbottom
-#endif
-                                                       ))
-               {
-                       smartdrawtext(text, l, (chgs != changes));
-               }
-       }
-       else if (l < topline && l > topline - LINES && (has_SR || has_AL))
-       {
-               /* near top - scroll down */
-               if (!mustredraw)
-               {
-                       move(0,0);
-                       while (l < topline)
-                       {
-                               topline--;
-                               if (has_SR)
-                               {
-                                       do_SR();
-                               }
-                               else
-                               {
-                                       insertln();
-                               }
-                               text = fetchline(topline);
-                               drawtext(text, topline, FALSE);
-                               do_UP();
-                       }
-
-                       /* blank out the last line */
-                       move(LINES - 1, 0);
-                       clrtoeol();
-               }
-               else
-               {
-                       topline = l;
-                       redrawrange(0L, INFINITY, INFINITY);
-               }
-       }
-       else if (l > topline && l < botline + LINES)
-       {
-               /* near bottom -- scroll up */
-               if (!mustredraw)
-               {
-                       move(LINES - 1,0);
-                       clrtoeol();
-                       while (l > botline)
-                       {
-                               topline++; /* <-- also adjusts botline */
-                               text = fetchline(botline);
-                               drawtext(text, botline, FALSE);
-                       }
-#ifndef CRUNCH
-                       showbottom = l;
-#endif
-               }
-               else
-               {
-                       topline = l - (LINES - 2);
-                       redrawrange(0L, INFINITY, INFINITY);
-               }
-       }
-       else
-       {
-               /* distant line - center it & force a redraw */
-               topline = l - (LINES / 2) - 1;
-               if (topline < 1)
-               {
-                       topline = 1;
-               }
-               redrawrange(0L, INFINITY, INFINITY);
-               changes++;
-       }
-
-#ifndef CRUNCH
-       /* make sure the current line is included in the "window" */
-       if (l < showtop)
-       {
-               redrawrange(l, showtop, showtop);
-               showtop = l;
-       }
-       if (l > showbottom)
-       {
-               redrawrange(showbottom, l, l);
-               showbottom = l;
-       }
-#endif
-
-
-       /* Now... do we really have to redraw? */
-       if (mustredraw)
-       {
-               /* If redrawfter (and friends) aren't set, assume we should
-                * redraw everything.
-                */
-               if (redrawafter == INFINITY)
-               {
-                       redrawafter = 0L;
-                       preredraw = postredraw = INFINITY;
-               }
-
-#ifndef CRUNCH
-               /* shrink the window, if possible */
-               if (showtop < topline)
-               {
-                       showtop = topline;
-               }
-               if (showbottom > botline)
-               {
-                       showbottom = botline;
-               }
-               if (postredraw == INFINITY)
-               {
-                       /* these will be set to more reasonable values later */
-                       showtop = INFINITY;
-                       showbottom = 0L;
-               }
-#endif
-
-               /* adjust smartlno to correspond with inserted/deleted lines */
-               if (smartlno >= redrawafter)
-               {
-                       if (smartlno < preredraw && postredraw != preredraw) /*!!!*/
-                       {
-                               smartlno = 0L;
-                       }
-                       else
-                       {
-                               smartlno += (postredraw - preredraw);
-                       }
-               }
-
-               /* should we insert some lines into the screen? */
-               if (preredraw < postredraw && preredraw <= botline)
-               {
-                       /* lines were inserted into the file */
-
-                       /* decide where insertion should start */
-                       if (preredraw < topline)
-                       {
-                               l = topline;
-                       }
-                       else
-                       {
-                               l = preredraw;
-                       }
-
-                       /* insert the lines... maybe */
-                       if (l + postredraw - preredraw > botline || !has_AL || *o_number)
-                       {
-                               /* Whoa!  a whole screen full - just redraw */
-                               preredraw = postredraw = INFINITY;
-                       }
-                       else
-                       {
-                               /* really insert 'em */
-                               move((int)(l - topline), 0);
-                               for (i = postredraw - preredraw; i > 0; i--)
-                               {
-                                       insertln();
-                               }
-
-                               /* NOTE: the contents of those lines will be
-                                * drawn as part of the regular redraw loop.
-                                */
-
-                               /* clear the last line */
-                               move(LINES - 1, 0);
-                               clrtoeol();
-                       }
-               }
-
-               /* do we want to delete some lines from the screen? */
-               if (preredraw > postredraw && postredraw <= botline)
-               {
-                       if (preredraw > botline || !has_DL || *o_number)
-                       {
-                               postredraw = preredraw = INFINITY;
-                       }
-                       else /* we'd best delete some lines from the screen */
-                       {
-                               /* clear the last line, so it doesn't look
-                                * ugly as it gets pulled up into the screen
-                                */
-                               move(LINES - 1, 0);
-                               clrtoeol();
-
-                               /* delete the lines */
-                               move((int)(postredraw - topline), 0);
-                               for (l = postredraw;
-                                    l < preredraw && l <= botline;
-                                    l++)
-                               {
-                                       deleteln();
-                               }
-
-                               /* draw the lines that are now newly visible
-                                * at the bottom of the screen
-                                */
-                               i = LINES - 1 + (postredraw - preredraw);
-                               move(i, 0);
-                               for (l = topline + i; l <= botline; l++)
-                               {
-                                       /* clear this line */
-                                       clrtoeol();
-
-                                       /* draw the line, or ~ for non-lines */
-                                       if (l <= nlines)
-                                       {
-                                               text = fetchline(l);
-                                               drawtext(text, l, FALSE);
-                                       }
-                                       else
-                                       {
-                                               addstr("~\n");
-                                       }
-                               }
-                       }
-               }
-
-               /* redraw the current line */
-               l = markline(curs);
-               pfetch(l);
-               smartdrawtext(ptext, l, TRUE);
-
-#ifndef CRUNCH
-               /* decide which lines must be in the "window" around the cursor */
-               l = markline(curs);
-               if ((*o_window & 0xff) + 1 == LINES)
-               {
-                       showtop = 1;
-                       showbottom = INFINITY;
-               }
-               else if (l < showtop || l > showbottom)
-               {
-                       l -= (*o_window & 0xff) / 2;
-                       if (l < topline)
-                       {
-                               l = topline;
-                       }
-                       if (l < showtop)
-                       {
-                               showtop = l;
-                       }
-                       l += (*o_window & 0xff) - 1;
-                       if (l > botline)
-                       {
-                               showtop = showtop - l + botline;
-                               l = botline;
-                       }
-                       if (l > showbottom)
-                       {
-                               showbottom = l;
-                       }
-               }
-#endif
-
-               /* decide where we should start redrawing from */
-               if (redrawafter < topline)
-               {
-                       l = topline;
-               }
-               else
-               {
-                       l = redrawafter;
-               }
-               if (l <= botline && l < postredraw && (l != smartlno || botline != smartlno))
-               {
-                       /* draw the other lines */
-                       move((int)(l - topline), 0);
-                       for (; l <= botline && l < postredraw; l++)
-                       {
-                               /* we already drew the current line, so skip it now */
-                               if (l == smartlno)
-                               {
-#if OSK
-                                       qaddch('\l');
-#else
-                                       qaddch('\n');
-#endif
-                                       continue;
-                               }
-
-                               /* draw the line, or ~ for non-lines */
-                               if (l > nlines)
-                               {
-                                       qaddch('~');
-                                       clrtoeol();
-                                       addch('\n');
-                               }
-#ifndef CRUNCH
-                               else if (l < showtop || l > showbottom)
-                               {
-                                       qaddch('@');
-                                       clrtoeol();
-                                       addch('\n');
-                               }
-#endif
-                               else
-                               {
-                                       text = fetchline(l);
-                                       drawtext(text, l, TRUE);
-                               }
-                       }
-               }
-
-               mustredraw = FALSE;
-       }
-
-       /* force total (non-partial) redraw next time if not set */
-       redrawafter = INFINITY;
-       preredraw = 0L;
-       postredraw = 0L;
-
-       /* move the cursor to where it belongs */
-       move((int)(markline(curs) - topline), physcol);
-       wqrefresh();
-
-       chgs = changes;
-}
diff --git a/commands/elvis/ref.c b/commands/elvis/ref.c
deleted file mode 100644 (file)
index c830464..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-/* ref2.c */
-
-/* This is a totally rewritten version of ref.  This version looks for the
- * desired function name in the "tags" file, and then reads the header out
- * from the source file.  There is no longer any need for a "refs" file.
- *
- * Usage:      ref [-a] [-t] [-f file] [-c class] tag
- * Options:    -t         output tag info, not the description
- *             -f file    default filename for static functions
- *             -c class   default class names for class functions
- */
-
-#include <stdio.h>
-#include "config.h"
-extern char    *getenv();
-extern char    *fgets();
-
-
-/* This is the default path that is searched for tags */
-#if OSK
-# define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
-#else
-# if ANY_UNIX
-#  define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
-# else
-#  if MSDOS || TOS
-#   define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
-#   define SEP ';'
-#  else
-#   if AMIGA
-#    define DEFTAGPATH ".;Include:;Include:sys"
-#    define SEP ';'
-#   else /* any other OS */
-#    define DEFTAGPATH "."
-#   endif
-#  endif
-# endif
-#endif
-
-#ifndef SEP
-# define SEP ':'
-#endif
-
-
-/* These variables reflect the command-line options given by the user. */
-int    taginfo;        /* boolean: give only the tag info? (not header?) */
-char   *def_file;      /* default filename for static functions */
-char   *def_class;     /* default classname for class members */
-int    colons;         /* #colons in tag: 0=normal, 1=static, 2=member */
-
-/* This function checks for a tag in the "tags" file of given directory.
- * If the tag is found, then it returns a pointer to a static buffer which
- * contains the filename, a tab character, and a linespec for finding the
- * the tag.  If the tag is not found in the "tags" file, or if the "tags"
- * file cannot be opened or doesn't exist, then this function returns NULL.
- */
-char *cktagdir(tag, dir)
-       char    *tag;   /* name of the tag to look for */
-       char    *dir;   /* name of the directory to check */
-{
-       char    buf[BLKSIZE];
-       static char found[BLKSIZE];
-       FILE    *tfile;
-       int     len;
-
-#if AMIGA
-       if (dir[strlen(dir) - 1] == COLON)
-           sprintf(buf, "%s%s", dir, TAGS);   /* no slash after colon. */
-       else
-#endif
-       /* construct the name of the "tags" file in this directory */
-       sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
-
-       /* Try to open the tags file.  Return NULL if can't open */
-#if AMIGA
-       if (buf[0] == '.' && buf[1] == SLASH)
-           tfile = fopen(&buf[2], "r");
-       else
-#endif
-       tfile = fopen(buf, "r");
-       if (!tfile)
-       {
-               return (char *)0;
-       }
-
-       /* compute the length of the tagname once */
-       len = strlen(tag);
-
-       /* read lines until we get the one for this tag */
-       found[0] = '\0';
-       while (fgets(buf, sizeof buf, tfile))
-       {
-               /* is this the one we want? */
-               if (!strncmp(buf, tag, len) && buf[len] == '\t')
-               {
-                       /* we've found a match -- remember it */
-                       strcpy(found, buf);
-
-                       /* if there is no default file, or this match is in
-                        * the default file, then we've definitely found the
-                        * one we want.  Break out of the loop now.
-                        */
-                       if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
-                       {
-                               break;
-                       }
-               }
-       }
-
-       /* we're through reading */
-       fclose(tfile);
-
-       /* if there's anything in found[], use it */
-       if (found[0])
-       {
-               return &found[len + 1];
-       }
-
-       /* else we didn't find it */
-       return (char *)0;
-}
-
-/* This function reads a single textline from a binary file.  It returns
- * the number of bytes read, or 0 at EOF.
- */
-#ifdef __NBSD_LIBC
-/* Avoid name pollution with stdio's getline. */
-#define getline ref_getline
-#endif
-int getline(buf, limit, fp)
-       char    *buf;   /* buffer to read into */
-       int     limit;  /* maximum characters to read */
-       FILE    *fp;    /* binary stream to read from */
-{
-       int     bytes;  /* number of bytes read so far */
-       int     ch;     /* single character from file */
-
-       for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
-       {
-#if MSDOS || TOS
-               /* since this is a binary file, we'll need to manually strip CR's */
-               if (ch == '\r')
-               {
-                       continue;
-               }
-#endif
-               *buf++ = ch;
-       }
-       *buf = '\0';
-
-       return bytes;
-}
-
-
-/* This function reads a source file, looking for a given tag.  If it finds
- * the tag, then it displays it and returns TRUE.  Otherwise it returns FALSE.
- * To display the tag, it attempts to output any introductory comment, the
- * tag line itself, and any arguments.  Arguments are assumed to immediately
- * follow the tag line, and start with whitespace.  Comments are assumed to
- * start with lines that begin with "/ *", "//", "(*", or "--", and end at the
- * tag line or at a blank line.
- */
-int lookup(dir, entry)
-       char    *dir;   /* name of the directory that contains the source */
-       char    *entry; /* source filename, <Tab>, linespec */
-{
-       char    buf[BLKSIZE];   /* pathname of sourcefile */
-       long    lnum;           /* line number */
-       long    here;           /* seek position where current line began */
-       long    comment;        /* seek position of introductory comment, or -1L */
-       FILE    *sfile;         /* used for reading the source file */
-       int     len;            /* length of string */
-       char    *ptr;
-
-
-       /* construct the pathname of the source file */
-       strcpy(buf, dir);
-       ptr = buf + strlen(buf);
-#if AMIGA
-       if (ptr[-1] != COLON)
-#endif
-       *ptr++ = SLASH;
-       while (*entry != '\t')
-       {
-               *ptr++ = *entry++;
-       }
-       *ptr = '\0';
-       entry++;
-
-       /* searching for string or number? */
-       if (*entry >= '0' && *entry <= '9')
-       {
-               /* given a specific line number */
-               lnum = atol(entry);
-               entry = (char *)0;
-       }
-       else
-       {
-               /* given a string -- strip off "/^" and "$/\n" */
-               entry += 2;
-               len = strlen(entry) - 2;
-               if (entry[len - 1] == '$')
-               {
-                       entry[len - 1] = '\n';
-               }
-               lnum = 0L;
-       }
-
-       /* Open the file.  Note that we open the file in binary mode even
-        * though we know it is a text file, because ftell() and fseek()
-        * don't work on text files.
-        */
-#if MSDOS || TOS
-       sfile = fopen(buf, "rb");
-#else
-# if AMIGA
-       if (buf[0] == '.' && buf[1] == SLASH)
-           sfile = fopen(&buf[2], "r");
-       else
-# endif
-       sfile = fopen(buf, "r");
-#endif
-       if (!sfile)
-       {
-               /* can't open the real source file.  Try "refs" instead */
-#if AMIGA
-               if (dir[strlen(dir) - 1] == COLON)
-                       sprintf(buf, "%srefs", dir);
-               else
-#endif
-               sprintf(buf, "%s%crefs", dir, SLASH);
-#if MSDOS || TOS
-               sfile = fopen(buf, "rb");
-#else
-# if AMIGA
-               if (buf[0] == '.' && buf[1] == SLASH)
-                   sfile = fopen(&buf[2], "r");
-               else
-# endif
-               sfile = fopen(buf, "r");
-#endif
-               if (!sfile)
-               {
-                       /* failed! */
-                       return 0;
-               }
-       }
-
-       /* search the file */
-       for (comment = -1L; here = ftell(sfile), getline(buf, BLKSIZE, sfile) > 0; )
-       {
-               /* Is this the start/end of a comment? */
-               if (comment == -1L)
-               {
-                       /* starting a comment? */
-                       if (buf[0] == '/' && buf[1] == '*'
-                        || buf[0] == '/' && buf[1] == '/'
-                        || buf[0] == '(' && buf[1] == '*'
-                        || buf[0] == '-' && buf[1] == '-')
-                       {
-                               comment = here;
-                       }
-               }
-               else
-               {
-                       /* ending a comment? */
-                       if (buf[0] == '\n' || buf[0] == '#')
-                       {
-                               comment = -1L;
-                       }
-               }
-
-               /* is this the tag line? */
-               if (--lnum == 0L || (entry && !strncmp(buf, entry, len)))
-               {
-                       /* if there were introductory comments, show them */
-                       if (comment != -1L)
-                       {
-                               fseek(sfile, comment, 0);
-                               while (comment != here)
-                               {
-                                       getline(buf, BLKSIZE, sfile);
-                                       fputs(buf, stdout);
-                                       comment = ftell(sfile);
-                               }
-
-                               /* re-fetch the tag line */
-                               fgets(buf, BLKSIZE, sfile);
-                       }
-
-                       /* show the tag line */
-                       fputs(buf, stdout);
-
-                       /* show any argument lines */
-                       while (getline(buf, BLKSIZE, sfile) > 0
-                           && buf[0] != '#'
-                           && strchr(buf, '{') == (char *)0)
-                       {
-                               fputs(buf, stdout);
-                       }
-
-                       /* Done!  Close the file, and return TRUE */
-                       fclose(sfile);
-                       return 1;
-               }
-       }
-
-       /* not found -- return FALSE */
-       return 0;
-}
-
-/* This function searches through the entire search path for a given tag.
- * If it finds the tag, then it displays the info and returns TRUE;
- * otherwise it returns FALSE.
- */
-int find(tag)
-       char    *tag;   /* the tag to look up */
-{
-       char    *tagpath;
-       char    dir[80];
-       char    *ptr;
-       int     len;
-
-       if (colons == 1)
-       {
-               /* looking for static function -- only look in current dir */
-               tagpath = ".";
-       }
-       else
-       {
-               /* get the tagpath from the environment.  Default to DEFTAGPATH */
-               tagpath = getenv("TAGPATH");
-               if (!tagpath)
-               {
-                       tagpath = DEFTAGPATH;
-               }
-       }
-
-       /* for each entry in the path... */
-       while (*tagpath)
-       {
-               /* Copy the entry into the dir[] buffer */
-               for (ptr = dir; *tagpath && *tagpath != SEP; tagpath++)
-               {
-                       *ptr++ = *tagpath;
-               }
-               if (*tagpath == SEP)
-               {
-                       tagpath++;
-               }
-
-               /* if the entry ended with "/tags", then strip that off */
-               len = strlen(TAGS);
-               if (&dir[len] < ptr && ptr[-len - 1] == SLASH && !strncmp(&ptr[-len], TAGS, len))
-               {
-                       ptr -= len + 1;
-               }
-
-               /* if the entry is now an empty string, then assume "." */
-               if (ptr == dir)
-               {
-                       *ptr++ = '.';
-               }
-               *ptr = '\0';
-
-               /* look for the tag in this path.  If found, then display it
-                * and exit.
-                */
-               ptr = cktagdir(tag, dir);
-               if (ptr)
-               {
-                       /* just supposed to display tag info? */
-                       if (taginfo)
-                       {
-                               /* then do only that! */
-                               if (strcmp(dir, "."))
-                               {
-                                       printf("%s%c%s", dir, SLASH, ptr);
-                               }
-                               else
-                               {
-                                       /* avoid leading "./" if possible */
-                                       fputs(ptr, stdout);
-                               }
-                               return 1;
-                       }
-                       else
-                       {
-                               /* else look up the declaration of the thing */
-                               return lookup(dir, ptr);
-                       }
-               }
-       }
-
-       /* if we get here, then the tag wasn't found anywhere */
-       return 0;
-}
-
-void usage()
-{
-       fputs("usage: ref [-a] [-t] [-c class] [-f file] tag\n", stderr);
-       fputs("   -a        function's args may be flush against left margin\n", stderr);
-       fputs("   -t        output tag info, instead of the function header\n", stderr);
-       fputs("   -f File   tag might be a static function in File\n", stderr);
-       fputs("   -c Class  tag might be a member of class Class\n", stderr);
-       exit(2);
-}
-
-
-int countcolons(str)
-       char    *str;
-{
-       while (*str != ':' && *str)
-       {
-               str++;
-       }
-       if (str[0] != ':')
-       {
-               return 0;
-       }
-       else if (str[1] != ':')
-       {
-               return 1;
-       }
-       return 2;
-}
-
-int main(argc, argv)
-       int     argc;
-       char    **argv;
-{
-       char    def_tag[100];   /* used to build tag name with default file/class */
-       int     i;
-
-       /* parse flags */
-       for (i = 1; i < argc && argv[i][0] == '-'; i++)
-       {
-               switch (argv[i][1])
-               {
-                 case 't':
-                       taginfo = 1;
-                       break;
-
-                 case 'f':
-                       if (argv[i][2])
-                       {
-                               def_file = &argv[i][2];
-                       }
-                       else if (++i < argc)
-                       {
-                               def_file = argv[i];
-                       }
-                       else
-                       {
-                               usage();
-                       }
-                       break;
-
-                 case 'c':
-                       if (argv[i][2])
-                       {
-                               def_class = &argv[i][2];
-                       }
-                       else if (++i < argc)
-                       {
-                               def_class = argv[i];
-                       }
-                       else
-                       {
-                               usage();
-                       }
-                       break;
-
-                 default:
-                       usage();
-               }
-       }
-
-       /* if no tag was given, complain */
-       if (i + 1 != argc)
-       {
-               usage();
-       }
-
-       /* does the tag have an explicit class or file? */
-       colons = countcolons(argv[i]);
-
-       /* if not, then maybe try some defaults */
-       if (colons == 0)
-       {
-               /* try a static function in the file first */
-               if (def_file)
-               {
-                       sprintf(def_tag, "%s:%s", def_file, argv[i]);
-                       colons = 1;
-                       if (find(def_tag))
-                       {
-                               exit(0);
-                       }
-               }
-
-               /* try a member function for a class */
-               if (def_class)
-               {
-                       sprintf(def_tag, "%s::%s", def_class, argv[i]);
-                       colons = 2;
-                       if (find(def_tag))
-                       {
-                               exit(0);
-                       }
-               }
-
-               /* oh, well */
-               colons = 0;
-       }
-
-       /* find the tag */
-       if (find(argv[i]))
-       {
-               exit(0);
-       }
-
-       exit(1);
-       /*NOTREACHED*/
-}
diff --git a/commands/elvis/regexp.c b/commands/elvis/regexp.c
deleted file mode 100644 (file)
index 91db71a..0000000
+++ /dev/null
@@ -1,934 +0,0 @@
-/* regexp.c */
-
-/* This file contains the code that compiles regular expressions and executes
- * them.  It supports the same syntax and features as vi's regular expression
- * code.  Specifically, the meta characters are:
- *     ^       matches the beginning of a line
- *     $       matches the end of a line
- *     \<      matches the beginning of a word
- *     \>      matches the end of a word
- *     .       matches any single character
- *     []      matches any character in a character class
- *     \(      delimits the start of a subexpression
- *     \)      delimits the end of a subexpression
- *     *       repeats the preceding 0 or more times
- * NOTE: You cannot follow a \) with a *.
- *
- * The physical structure of a compiled RE is as follows:
- *     - First, there is a one-byte value that says how many character classes
- *       are used in this regular expression
- *     - Next, each character class is stored as a bitmap that is 256 bits
- *       (32 bytes) long.
- *     - A mixture of literal characters and compiled meta characters follows.
- *       This begins with M_BEGIN(0) and ends with M_END(0).  All meta chars
- *       are stored as a \n followed by a one-byte code, so they take up two
- *       bytes apiece.  Literal characters take up one byte apiece.  \n can't
- *       be used as a literal character.
- *
- * If NO_MAGIC is defined, then a different set of functions is used instead.
- * That right, this file contains TWO versions of the code.
- */
-
-#include <setjmp.h>
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-#include "regexp.h"
-
-
-
-static char    *previous;      /* the previous regexp, used when null regexp is given */
-
-
-#ifndef NO_MAGIC
-/* THE REAL REGEXP PACKAGE IS USED UNLESS "NO_MAGIC" IS DEFINED */
-
-/* These are used to classify or recognize meta-characters */
-#define META           '\0'
-#define BASE_META(m)   ((m) - 256)
-#define INT_META(c)    ((c) + 256)
-#define IS_META(m)     ((m) >= 256)
-#define IS_CLASS(m)    ((m) >= M_CLASS(0) && (m) <= M_CLASS(9))
-#define IS_START(m)    ((m) >= M_START(0) && (m) <= M_START(9))
-#define IS_END(m)      ((m) >= M_END(0) && (m) <= M_END(9))
-#define IS_CLOSURE(m)  ((m) >= M_SPLAT && (m) <= M_RANGE)
-#define ADD_META(s,m)  (*(s)++ = META, *(s)++ = BASE_META(m))
-#define GET_META(s)    (*(s) == META ? INT_META(*++(s)) : *s)
-
-/* These are the internal codes used for each type of meta-character */
-#define M_BEGLINE      256             /* internal code for ^ */
-#define M_ENDLINE      257             /* internal code for $ */
-#define M_BEGWORD      258             /* internal code for \< */
-#define M_ENDWORD      259             /* internal code for \> */
-#define M_ANY          260             /* internal code for . */
-#define M_SPLAT                261             /* internal code for * */
-#define M_PLUS         262             /* internal code for \+ */
-#define M_QMARK                263             /* internal code for \? */
-#define M_RANGE                264             /* internal code for \{ */
-#define M_CLASS(n)     (265+(n))       /* internal code for [] */
-#define M_START(n)     (275+(n))       /* internal code for \( */
-#define M_END(n)       (285+(n))       /* internal code for \) */
-
-/* These are used during compilation */
-static int     class_cnt;      /* used to assign class IDs */
-static int     start_cnt;      /* used to assign start IDs */
-static int     end_stk[NSUBEXP];/* used to assign end IDs */
-static int     end_sp;
-static char    *retext;        /* points to the text being compiled */
-
-/* error-handling stuff */
-jmp_buf        errorhandler;
-#define FAIL(why)      regerror(why); longjmp(errorhandler, 1)
-
-
-
-
-
-/* This function builds a bitmap for a particular class */
-static char *makeclass(text, bmap)
-       REG char        *text;  /* start of the class */
-       REG char        *bmap;  /* the bitmap */
-{
-       REG int         i;
-       int             complement = 0;
-
-
-       /* zero the bitmap */
-       for (i = 0; bmap && i < 32; i++)
-       {
-               bmap[i] = 0;
-       }
-
-       /* see if we're going to complement this class */
-       if (*text == '^')
-       {
-               text++;
-               complement = 1;
-       }
-
-       /* add in the characters */
-       while (*text && *text != ']')
-       {
-               /* is this a span of characters? */
-               if (text[1] == '-' && text[2])
-               {
-                       /* spans can't be backwards */
-                       if (text[0] > text[2])
-                       {
-                               FAIL("Backwards span in []");
-                       }
-
-                       /* add each character in the span to the bitmap */
-                       for (i = text[0]; bmap && i <= text[2]; i++)
-                       {
-                               bmap[i >> 3] |= (1 << (i & 7));
-                       }
-
-                       /* move past this span */
-                       text += 3;
-               }
-               else
-               {
-                       /* add this single character to the span */
-                       i = *text++;
-                       if (bmap)
-                       {
-                               bmap[i >> 3] |= (1 << (i & 7));
-                       }
-               }
-       }
-
-       /* make sure the closing ] is missing */
-       if (*text++ != ']')
-       {
-               FAIL("] missing");
-       }
-
-       /* if we're supposed to complement this class, then do so */
-       if (complement && bmap)
-       {
-               for (i = 0; i < 32; i++)
-               {
-                       bmap[i] = ~bmap[i];
-               }
-       }
-
-       return text;
-}
-
-
-
-
-/* This function gets the next character or meta character from a string.
- * The pointer is incremented by 1, or by 2 for \-quoted characters.  For [],
- * a bitmap is generated via makeclass() (if re is given), and the
- * character-class text is skipped.
- */
-static int gettoken(sptr, re)
-       char    **sptr;
-       regexp  *re;
-{
-       int     c;
-
-       c = **sptr;
-       ++*sptr;
-       if (c == '\\')
-       {
-               c = **sptr;
-               ++*sptr;
-               switch (c)
-               {
-                 case '<':
-                       return M_BEGWORD;
-
-                 case '>':
-                       return M_ENDWORD;
-
-                 case '(':
-                       if (start_cnt >= NSUBEXP)
-                       {
-                               FAIL("Too many \\(s");
-                       }
-                       end_stk[end_sp++] = start_cnt;
-                       return M_START(start_cnt++);
-
-                 case ')':
-                       if (end_sp <= 0)
-                       {
-                               FAIL("Mismatched \\)");
-                       }
-                       return M_END(end_stk[--end_sp]);
-
-                 case '*':
-                       return (*o_magic ? c : M_SPLAT);
-
-                 case '.':
-                       return (*o_magic ? c : M_ANY);
-
-                 case '+':
-                       return M_PLUS;
-
-                 case '?':
-                       return M_QMARK;
-#ifndef CRUNCH
-                 case '{':
-                       return M_RANGE;
-#endif
-                 default:
-                       return c;
-               }
-       }
-       else if (*o_magic)
-       {
-               switch (c)
-               {
-                 case '^':
-                       if (*sptr == retext + 1)
-                       {
-                               return M_BEGLINE;
-                       }
-                       return c;
-
-                 case '$':
-                       if (!**sptr)
-                       {
-                               return M_ENDLINE;
-                       }
-                       return c;
-
-                 case '.':
-                       return M_ANY;
-
-                 case '*':
-                       return M_SPLAT;
-
-                 case '[':
-                       /* make sure we don't have too many classes */
-                       if (class_cnt >= 10)
-                       {
-                               FAIL("Too many []s");
-                       }
-
-                       /* process the character list for this class */
-                       if (re)
-                       {
-                               /* generate the bitmap for this class */
-                               *sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt);
-                       }
-                       else
-                       {
-                               /* skip to end of the class */
-                               *sptr = makeclass(*sptr, (char *)0);
-                       }
-                       return M_CLASS(class_cnt++);
-
-                 default:
-                       return c;
-               }
-       }
-       else    /* unquoted nomagic */
-       {
-               switch (c)
-               {
-                 case '^':
-                       if (*sptr == retext + 1)
-                       {
-                               return M_BEGLINE;
-                       }
-                       return c;
-
-                 case '$':
-                       if (!**sptr)
-                       {
-                               return M_ENDLINE;
-                       }
-                       return c;
-
-                 default:
-                       return c;
-               }
-       }
-       /*NOTREACHED*/
-}
-
-
-
-
-/* This function calculates the number of bytes that will be needed for a
- * compiled RE.  Its argument is the uncompiled version.  It is not clever
- * about catching syntax errors; that is done in a later pass.
- */
-static unsigned calcsize(text)
-       char            *text;
-{
-       unsigned        size;
-       int             token;
-
-       retext = text;
-       class_cnt = 0;
-       start_cnt = 1;
-       end_sp = 0;
-       size = 5;
-       while ((token = gettoken(&text, (regexp *)0)) != 0)
-       {
-               if (IS_CLASS(token))
-               {
-                       size += 34;
-               }
-#ifndef CRUNCH
-               else if (token == M_RANGE)
-               {
-                       size += 4;
-                       while ((token = gettoken(&text, (regexp *)0)) != 0
-                           && token != '}')
-                       {
-                       }
-                       if (!token)
-                       {
-                               return size;
-                       }
-               }
-#endif
-               else if (IS_META(token))
-               {
-                       size += 2;
-               }
-               else
-               {
-                       size++;
-               }
-       }
-
-       return size;
-}
-
-
-
-/* This function compiles a regexp. */
-regexp *regcomp(exp)
-       char            *exp;
-{
-       int             needfirst;
-       unsigned        size;
-       int             token;
-       int             peek;
-       char            *build;
-       regexp          *re;
-#ifndef CRUNCH
-       int             from;
-       int             to;
-       int             digit;
-#endif
-
-
-       /* prepare for error handling */
-       re = (regexp *)0;
-       if (setjmp(errorhandler))
-       {
-               if (re)
-               {
-                       free(re);
-               }
-               return (regexp *)0;
-       }
-
-       /* if an empty regexp string was given, use the previous one */
-       if (*exp == 0)
-       {
-               if (!previous)
-               {
-                       FAIL("No previous RE");
-               }
-               exp = previous;
-       }
-       else /* non-empty regexp given, so remember it */
-       {
-               if (previous)
-                       free(previous);
-               previous = (char *)malloc((unsigned)(strlen(exp) + 1));
-               if (previous)
-                       strcpy(previous, exp);
-       }
-
-       /* allocate memory */
-       class_cnt = 0;
-       start_cnt = 1;
-       end_sp = 0;
-       retext = exp;
-       size = calcsize(exp) + sizeof(regexp) + 10; /* !!! 10 bytes for slop */
-#ifdef lint
-       re = ((regexp *)0) + size;
-#else
-       re = (regexp *)malloc((unsigned)size);
-#endif
-       if (!re)
-       {
-               FAIL("Not enough memory for this RE");
-       }
-
-       /* compile it */
-       build = &re->program[1 + 32 * class_cnt];
-       re->program[0] = class_cnt;
-       for (token = 0; token < NSUBEXP; token++)
-       {
-               re->startp[token] = re->endp[token] = (char *)0;
-       }
-       re->first = 0;
-       re->bol = 0;
-       re->minlen = 0;
-       needfirst = 1;
-       class_cnt = 0;
-       start_cnt = 1;
-       end_sp = 0;
-       retext = exp;
-       for (token = M_START(0), peek = gettoken(&exp, re);
-            token;
-            token = peek, peek = gettoken(&exp, re))
-       {
-               /* special processing for the closure operator */
-               if (IS_CLOSURE(peek))
-               {
-                       /* detect misuse of closure operator */
-                       if (IS_START(token))
-                       {
-                               FAIL("Closure operator follows nothing");
-                       }
-                       else if (IS_META(token) && token != M_ANY && !IS_CLASS(token))
-                       {
-                               FAIL("Closure operators can only follow a normal character or . or []");
-                       }
-
-#ifndef CRUNCH
-                       /* if \{ \} then read the range */
-                       if (peek == M_RANGE)
-                       {
-                               from = 0;
-                               for (digit = gettoken(&exp, re);
-                                    !IS_META(digit) && isdigit(digit);
-                                    digit = gettoken(&exp, re))
-                               {
-                                       from = from * 10 + digit - '0';
-                               }
-                               if (digit == '}')
-                               {
-                                       to = from;
-                               }
-                               else if (digit == ',')
-                               {
-                                       to = 0;
-                                       for (digit = gettoken(&exp, re);
-                                            !IS_META(digit) && isdigit(digit);
-                                            digit = gettoken(&exp, re))
-                                       {
-                                               to = to * 10 + digit - '0';
-                                       }
-                                       if (to == 0)
-                                       {
-                                               to = 255;
-                                       }
-                               }
-                               if (digit != '}')
-                               {
-                                       FAIL("Bad characters after \\{");
-                               }
-                               else if (to < from || to == 0 || from >= 255)
-                               {
-                                       FAIL("Invalid range for \\{ \\}");
-                               }
-                               re->minlen += from;
-                       }
-                       else
-#endif
-                       if (peek != M_SPLAT)
-                       {
-                               re->minlen++;
-                       }
-
-                       /* it is okay -- make it prefix instead of postfix */
-                       ADD_META(build, peek);
-#ifndef CRUNCH
-                       if (peek == M_RANGE)
-                       {
-                               *build++ = from;
-                               *build++ = (to < 255 ? to : 255);
-                       }
-#endif
-                       
-
-                       /* take care of "needfirst" - is this the first char? */
-                       if (needfirst && peek == M_PLUS && !IS_META(token))
-                       {
-                               re->first = token;
-                       }
-                       needfirst = 0;
-
-                       /* we used "peek" -- need to refill it */
-                       peek = gettoken(&exp, re);
-                       if (IS_CLOSURE(peek))
-                       {
-                               FAIL("* or \\+ or \\? doubled up");
-                       }
-               }
-               else if (!IS_META(token))
-               {
-                       /* normal char is NOT argument of closure */
-                       if (needfirst)
-                       {
-                               re->first = token;
-                               needfirst = 0;
-                       }
-                       re->minlen++;
-               }
-               else if (token == M_ANY || IS_CLASS(token))
-               {
-                       /* . or [] is NOT argument of closure */
-                       needfirst = 0;
-                       re->minlen++;
-               }
-
-               /* the "token" character is not closure -- process it normally */
-               if (token == M_BEGLINE)
-               {
-                       /* set the BOL flag instead of storing M_BEGLINE */
-                       re->bol = 1;
-               }
-               else if (IS_META(token))
-               {
-                       ADD_META(build, token);
-               }
-               else
-               {
-                       *build++ = token;
-               }
-       }
-
-       /* end it with a \) which MUST MATCH the opening \( */
-       ADD_META(build, M_END(0));
-       if (end_sp > 0)
-       {
-               FAIL("Not enough \\)s");
-       }
-
-       return re;
-}
-
-
-
-/*---------------------------------------------------------------------------*/
-
-
-/* This function checks for a match between a character and a token which is
- * known to represent a single character.  It returns 0 if they match, or
- * 1 if they don't.
- */
-int match1(re, ch, token)
-       regexp          *re;
-       REG char        ch;
-       REG int         token;
-{
-       if (!ch)
-       {
-               /* the end of a line can't match any RE of width 1 */
-               return 1;
-       }
-       if (token == M_ANY)
-       {
-               return 0;
-       }
-       else if (IS_CLASS(token))
-       {
-               if (re->program[1 + 32 * (token - M_CLASS(0)) + (ch >> 3)] & (1 << (ch & 7)))
-                       return 0;
-       }
-       else if (ch == token || *o_ignorecase && tolower(ch) == tolower(token))
-       {
-               return 0;
-       }
-       return 1;
-}
-
-
-
-/* This function checks characters up to and including the next closure, at
- * which point it does a recursive call to check the rest of it.  This function
- * returns 0 if everything matches, or 1 if something doesn't match.
- */
-int match(re, str, prog, here)
-       regexp          *re;    /* the regular expression */
-       char            *str;   /* the string */
-       REG char        *prog;  /* a portion of re->program, an compiled RE */
-       REG char        *here;  /* a portion of str, the string to compare it to */
-{
-       REG int         token;  /* the roken pointed to by prog */
-       REG int         nmatched;/* counter, used during closure matching */ 
-       REG int         closure;/* the token denoting the type of closure */
-       int             from;   /* minimum number of matches in closure */
-       int             to;     /* maximum number of matches in closure */
-
-       for (token = GET_META(prog); !IS_CLOSURE(token); prog++, token = GET_META(prog))
-       {
-               switch (token)
-               {
-               /*case M_BEGLINE: can't happen; re->bol is used instead */
-                 case M_ENDLINE:
-                       if (*here)
-                               return 1;
-                       break;
-
-                 case M_BEGWORD:
-                       if (here != str &&
-                          (here[-1] == '_' || isalnum(here[-1])))
-                               return 1;
-                       break;
-
-                 case M_ENDWORD:
-                       if (here[0] == '_' || isalnum(here[0]))
-                               return 1;
-                       break;
-
-                 case M_START(0):
-                 case M_START(1):
-                 case M_START(2):
-                 case M_START(3):
-                 case M_START(4):
-                 case M_START(5):
-                 case M_START(6):
-                 case M_START(7):
-                 case M_START(8):
-                 case M_START(9):
-                       re->startp[token - M_START(0)] = (char *)here;
-                       break;
-
-                 case M_END(0):
-                 case M_END(1):
-                 case M_END(2):
-                 case M_END(3):
-                 case M_END(4):
-                 case M_END(5):
-                 case M_END(6):
-                 case M_END(7):
-                 case M_END(8):
-                 case M_END(9):
-                       re->endp[token - M_END(0)] = (char *)here;
-                       if (token == M_END(0))
-                       {
-                               return 0;
-                       }
-                       break;
-
-                 default: /* literal, M_CLASS(n), or M_ANY */
-                       if (match1(re, *here, token) != 0)
-                               return 1;
-                       here++;
-               }
-       }
-
-       /* C L O S U R E */
-
-       /* step 1: see what we have to match against, and move "prog" to point
-        * to the remainder of the compiled RE.
-        */
-       closure = token;
-       prog++;
-       switch (closure)
-       {
-         case M_SPLAT:
-               from = 0;
-               to = strlen(str);       /* infinity */
-               break;
-
-         case M_PLUS:
-               from = 1;
-               to = strlen(str);       /* infinity */
-               break;
-
-         case M_QMARK:
-               from = 0;
-               to = 1;
-               break;
-
-#ifndef CRUNCH
-         case M_RANGE:
-               from = UCHAR(*prog++);
-               to = UCHAR(*prog++);
-               if (to == 255)
-               {
-                       to = strlen(str); /* infinity */
-               }
-               break;
-#endif
-       }
-       token = GET_META(prog);
-       prog++;
-
-       /* step 2: see how many times we can match that token against the string */
-       for (nmatched = 0;
-            nmatched < to && *here && match1(re, *here, token) == 0;
-            nmatched++, here++)
-       {
-       }
-
-       /* step 3: try to match the remainder, and back off if it doesn't */
-       while (nmatched >= from && match(re, str, prog, here) != 0)
-       {
-               nmatched--;
-               here--;
-       }
-
-       /* so how did it work out? */
-       if (nmatched >= from)
-               return 0;
-       return 1;
-}
-
-
-
-/* This function searches through a string for text that matches an RE. */
-int regexec(re, str, bol)
-       regexp  *re;    /* the compiled regexp to search for */
-       char    *str;   /* the string to search through */
-       int     bol;    /* boolean: does str start at the beginning of a line? */
-{
-       char    *prog;  /* the entry point of re->program */
-       int     len;    /* length of the string */
-       REG char        *here;
-
-       /* if must start at the beginning of a line, and this isn't, then fail */
-       if (re->bol && !bol)
-       {
-               return 0;
-       }
-
-       len = strlen(str);
-       prog = re->program + 1 + 32 * re->program[0];
-
-       /* search for the RE in the string */
-       if (re->bol)
-       {
-               /* must occur at BOL */
-               if ((re->first
-                       && match1(re, *(char *)str, re->first))/* wrong first letter? */
-                || len < re->minlen                    /* not long enough? */
-                || match(re, (char *)str, prog, str))  /* doesn't match? */
-                       return 0;                       /* THEN FAIL! */
-       }
-#ifndef CRUNCH
-       else if (!*o_ignorecase)
-       {
-               /* can occur anywhere in the line, noignorecase */
-               for (here = (char *)str;
-                    (re->first && re->first != *here)
-                       || match(re, (char *)str, prog, here);
-                    here++, len--)
-               {
-                       if (len < re->minlen)
-                               return 0;
-               }
-       }
-#endif
-       else
-       {
-               /* can occur anywhere in the line, ignorecase */
-               for (here = (char *)str;
-                    (re->first && match1(re, *here, (int)re->first))
-                       || match(re, (char *)str, prog, here);
-                    here++, len--)
-               {
-                       if (len < re->minlen)
-                               return 0;
-               }
-       }
-
-       /* if we didn't fail, then we must have succeeded */
-       return 1;
-}
-
-/*============================================================================*/
-#else /* NO_MAGIC */
-
-regexp *regcomp(exp)
-       char    *exp;
-{
-       char    *src;
-       char    *dest;
-       regexp  *re;
-       int     i;
-
-       /* allocate a big enough regexp structure */
-#ifdef lint
-       re = (regexp *)0;
-#else
-       re = (regexp *)malloc((unsigned)(strlen(exp) + 1 + sizeof(struct regexp)));
-#endif
-       if (!re)
-       {
-               regerror("Could not malloc a regexp structure");
-               return (regexp *)0;
-       }
-
-       /* initialize all fields of the structure */
-       for (i = 0; i < NSUBEXP; i++)
-       {
-               re->startp[i] = re->endp[i] = (char *)0;
-       }
-       re->minlen = 0;
-       re->first = 0;
-       re->bol = 0;
-
-       /* copy the string into it, translating ^ and $ as needed */
-       for (src = exp, dest = re->program + 1; *src; src++)
-       {
-               switch (*src)
-               {
-                 case '^':
-                       if (src == exp)
-                       {
-                               re->bol += 1;
-                       }
-                       else
-                       {
-                               *dest++ = '^';
-                               re->minlen++;
-                       }
-                       break;
-
-                 case '$':
-                       if (!src[1])
-                       {
-                               re->bol += 2;
-                       }
-                       else
-                       {
-                               *dest++ = '$';
-                               re->minlen++;
-                       }
-                       break;
-
-                 case '\\':
-                       if (src[1])
-                       {
-                               *dest++ = *++src;
-                               re->minlen++;
-                       }
-                       else
-                       {
-                               regerror("extra \\ at end of regular expression");
-                       }
-                       break;
-
-                 default:
-                       *dest++ = *src;
-                       re->minlen++;
-               }
-       }
-       *dest = '\0';
-
-       return re;
-}
-
-
-/* This "helper" function checks for a match at a given location.  It returns
- * 1 if it matches, 0 if it doesn't match here but might match later on in the
- * string, or -1 if it could not possibly match
- */
-static int reghelp(prog, string, bolflag)
-       struct regexp   *prog;
-       char            *string;
-       int             bolflag;
-{
-       char            *scan;
-       char            *str;
-
-       /* if ^, then require bolflag */
-       if ((prog->bol & 1) && !bolflag)
-       {
-               return -1;
-       }
-
-       /* if it matches, then it will start here */
-       prog->startp[0] = string;
-
-       /* compare, possibly ignoring case */
-       if (*o_ignorecase)
-       {
-               for (scan = &prog->program[1]; *scan; scan++, string++)
-                       if (tolower(*scan) != tolower(*string))
-                               return *string ? 0 : -1;
-       }
-       else
-       {
-               for (scan = &prog->program[1]; *scan; scan++, string++)
-                       if (*scan != *string)
-                               return *string ? 0 : -1;
-       }
-
-       /* if $, then require string to end here, too */
-       if ((prog->bol & 2) && *string)
-       {
-               return 0;
-       }
-
-       /* if we get to here, it matches */
-       prog->endp[0] = string;
-       return 1;
-}
-
-
-
-int regexec(prog, string, bolflag)
-       struct regexp   *prog;
-       char            *string;
-       int             bolflag;
-{
-       int             rc;
-
-       /* keep trying to match it */
-       for (rc = reghelp(prog, string, bolflag); rc == 0; rc = reghelp(prog, string, 0))
-       {
-               string++;
-       }
-
-       /* did we match? */
-       return rc == 1;
-}
-#endif
diff --git a/commands/elvis/regexp.h b/commands/elvis/regexp.h
deleted file mode 100644 (file)
index 6d043b0..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Definitions etc. for regexp(3) routines.
- *
- * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
- * not the System V one.
- */
-#define NSUBEXP  10
-
-typedef struct regexp {
-       char    *startp[NSUBEXP];
-       char    *endp[NSUBEXP];
-       int     minlen;         /* length of shortest possible match */
-       char    first;          /* first character, if known; else \0 */
-       char    bol;            /* boolean: must start at beginning of line? */
-       char    program[1];     /* Unwarranted chumminess with compiler. */
-} regexp;
-
-extern regexp *regcomp();
-extern int regexec();
-extern void regsub();
-extern void regerror();
diff --git a/commands/elvis/regsub.c b/commands/elvis/regsub.c
deleted file mode 100644 (file)
index d9ea1a1..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* regsub.c */
-
-/* This file contains the regsub() function, which performs substitutions
- * after a regexp match has been found.
- */
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-#include "regexp.h"
-
-
-/* perform substitutions after a regexp match */
-void regsub(re, src, dst)
-       regexp          *re;    /* the regexp with pointers into matched text */
-       REG char        *src;   /* the replacement string */
-       REG char        *dst;   /* where to put the result of the subst */
-{
-       REG char        *cpy;   /* pointer to start of text to copy */
-       REG char        *end;   /* pointer to end of text to copy */
-       REG char        c;
-       char            *start;
-#ifndef CRUNCH
-       int             mod = 0;/* used to track \U, \L, \u, \l, and \E */
-       int             len;    /* used to calculate length of subst string */
-       static char     *prev;  /* a copy of the text from the previous subst */
-
-       /* replace \~ (or maybe ~) by previous substitution text */
-
-       /* step 1: calculate the length of the new substitution text */
-       for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
-       {
-# ifdef NO_MAGIC
-               if (c == '\\' && *cpy == '~')
-# else
-               if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
-# endif
-               {
-                       if (!prev)
-                       {
-                               regerror("No prev text to substitute for ~");
-                               return;
-                       }
-                       len += strlen(prev) - 1;
-# ifndef NO_MAGIC
-                       if (!*o_magic)
-# endif
-                               len -= 1; /* because we lose the \ too */
-               }
-
-               /* watch backslash quoting */
-               if (c != '\\' && *cpy == '\\')
-                       c = '\\';
-               else
-                       c = '\0';
-       }
-
-       /* allocate memory for the ~ed version of src */
-       start = cpy = (char *)malloc((unsigned)(len + 1));
-       if (!cpy)
-       {
-               regerror("Not enough memory for ~ expansion");
-               return;
-       }
-
-       /* copy src into start, replacing the ~s by the previous text */
-       while (*src)
-       {
-# ifndef NO_MAGIC
-               if (*o_magic && *src == '~')
-               {
-                       strcpy(cpy, prev);
-                       cpy += strlen(prev);
-                       src++;
-               }
-               else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
-# else /* NO_MAGIC */
-               if (*src == '\\' && *(src + 1) == '~')
-# endif /* NO_MAGIC */
-               {
-                       strcpy(cpy, prev);
-                       cpy += strlen(prev);
-                       src += 2;
-               }
-               else
-               {
-                       *cpy++ = *src++;
-               }
-       }
-       *cpy = '\0';
-#ifdef DEBUG
-       if ((int)(cpy - start) != len)
-       {
-               msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
-       }
-#endif
-
-       /* remember this as the "previous" for next time */
-       if (prev)
-               free(prev);
-       prev = src = start;
-
-#endif /* undef CRUNCH */
-
-       start = src;
-       while ((c = *src++) != '\0')
-       {
-#ifndef NO_MAGIC
-               /* recognize any meta characters */
-               if (c == '&' && *o_magic)
-               {
-                       cpy = re->startp[0];
-                       end = re->endp[0];
-               }
-               else
-#endif /* not NO_MAGIC */
-               if (c == '\\')
-               {
-                       c = *src++;
-                       switch (c)
-                       {
-#ifndef NO_MAGIC
-                         case '0':
-                         case '1':
-                         case '2':
-                         case '3':
-                         case '4':
-                         case '5':
-                         case '6':
-                         case '7':
-                         case '8':
-                         case '9':
-                               /* \0 thru \9 mean "copy subexpression" */
-                               c -= '0';
-                               cpy = re->startp[c];
-                               end = re->endp[c];
-                               break;
-# ifndef CRUNCH
-                         case 'U':
-                         case 'u':
-                         case 'L':
-                         case 'l':
-                               /* \U and \L mean "convert to upper/lowercase" */
-                               mod = c;
-                               continue;
-
-                         case 'E':
-                         case 'e':
-                               /* \E ends the \U or \L */
-                               mod = 0;
-                               continue;
-# endif /* not CRUNCH */
-                         case '&':
-                               /* "\&" means "original text" */
-                               if (*o_magic)
-                               {
-                                       *dst++ = c;
-                                       continue;
-                               }
-                               cpy = re->startp[0];
-                               end = re->endp[0];
-                               break;
-
-#else /* NO_MAGIC */
-                         case '&':
-                               /* "\&" means "original text" */
-                               cpy = re->startp[0];
-                               end = re->endp[0];
-                               break;
-#endif /* NO_MAGIC */
-                         default:
-                               /* ordinary char preceded by backslash */
-                               *dst++ = c;
-                               continue;
-                       }
-               }
-#ifndef CRUNCH
-# if OSK
-               else if (c == '\l')
-# else
-               else if (c == '\r')
-# endif
-               {
-                       /* transliterate ^M into newline */
-                       *dst++ = '\n';
-                       continue;
-               }
-#endif /* !CRUNCH */
-               else
-               {
-                       /* ordinary character, so just copy it */
-                       *dst++ = c;
-                       continue;
-               }
-
-               /* Note: to reach this point in the code, we must have evaded
-                * all "continue" statements.  To do that, we must have hit
-                * a metacharacter that involves copying.
-                */
-
-               /* if there is nothing to copy, loop */
-               if (!cpy)
-                       continue;
-
-               /* copy over a portion of the original */
-               while (cpy < end)
-               {
-#ifndef NO_MAGIC
-# ifndef CRUNCH
-                       switch (mod)
-                       {
-                         case 'U':
-                         case 'u':
-                               /* convert to uppercase */
-                               *dst++ = toupper(*cpy++);
-                               break;
-
-                         case 'L':
-                         case 'l':
-                               /* convert to lowercase */
-                               *dst++ = tolower(*cpy++);
-                               break;
-
-                         default:
-                               /* copy without any conversion */
-                               *dst++ = *cpy++;
-                       }
-
-                       /* \u and \l end automatically after the first char */
-                       if (mod && (mod == 'u' || mod == 'l'))
-                       {
-                               mod = 0;
-                       }
-# else /* CRUNCH */
-                       *dst++ = *cpy++;
-# endif /* CRUNCH */
-#else /* NO_MAGIC */
-                       *dst++ = *cpy++;
-#endif /* NO_MAGIC */
-               }
-       }
-       *dst = '\0';
-}
diff --git a/commands/elvis/system.c b/commands/elvis/system.c
deleted file mode 100644 (file)
index e73bc5a..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/* system.c  -- UNIX version */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains a new version of the system() function and related stuff.
- *
- * Entry points are:
- *     system(cmd)             - run a single shell command
- *     wildcard(names)         - expand wildcard characters in filanames
- *     filter(m,n,cmd,back)    - run text lines through a filter program
- *
- * This is probably the single least portable file in the program.  The code
- * shown here should work correctly if it links at all; it will work on UNIX
- * and any O.S./Compiler combination which adheres to UNIX forking conventions.
- */
-
-#include "config.h"
-#include "vi.h"
-extern char    **environ;
-
-#if ANY_UNIX
-
-/* This is a new version of the system() function.  The only difference
- * between this one and the library one is: this one uses the o_shell option.
- */
-int system(cmd)
-       char    *cmd;   /* a command to run */
-{
-       int     pid;    /* process ID of child */
-       int     died;
-       int     status; /* exit status of the command */
-
-
-       signal(SIGINT, SIG_IGN);
-       pid = fork();
-       switch (pid)
-       {
-         case -1:                                              /* error */
-               msg("fork() failed");
-               status = -1;
-               break;
-
-         case 0:                                               /* child */
-               /* for the child, close all files except stdin/out/err */
-               for (status = 3; status < 60 && (close(status), errno != EINVAL); status++)
-               {
-               }
-
-               signal(SIGINT, SIG_DFL);
-               if (cmd == o_shell)
-               {
-                       execle(o_shell, o_shell, (char *)0, environ);
-               }
-               else
-               {
-                       execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
-               }
-               msg("execle(\"%s\", ...) failed", o_shell);
-               exit(1); /* if we get here, the exec failed */
-
-         default:                                              /* parent */
-               do
-               {
-                       died = wait(&status);
-               } while (died >= 0 && died != pid);
-               if (died < 0)
-               {
-                       status = -1;
-               }
-               signal(SIGINT, (void (*)()) trapint);
-       }
-
-       return status;
-}
-
-/* This private function opens a pipe from a filter.  It is similar to the
- * system() function above, and to popen(cmd, "r").
- */
-int rpipe(cmd, in)
-       char    *cmd;   /* the filter command to use */
-       int     in;     /* the fd to use for stdin */
-{
-       int     r0w1[2];/* the pipe fd's */
-
-       /* make the pipe */
-       if (pipe(r0w1) < 0)
-       {
-               return -1;      /* pipe failed */
-       }
-
-       /* The parent process (elvis) ignores signals while the filter runs.
-        * The child (the filter program) will reset this, so that it can
-        * catch the signal.
-        */
-       signal(SIGINT, SIG_IGN);
-
-       switch (fork())
-       {
-         case -1:                                              /* error */
-               return -1;
-
-         case 0:                                               /* child */
-               /* close the "read" end of the pipe */
-               close(r0w1[0]);
-
-               /* redirect stdout to go to the "write" end of the pipe */
-               close(1);
-               dup(r0w1[1]);
-               close(2);
-               dup(r0w1[1]);
-               close(r0w1[1]);
-
-               /* redirect stdin */
-               if (in != 0)
-               {
-                       close(0);
-                       dup(in);
-                       close(in);
-               }
-
-               /* the filter should accept SIGINT signals */
-               signal(SIGINT, SIG_DFL);
-
-               /* exec the shell to run the command */
-               execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
-               exit(1); /* if we get here, exec failed */
-
-         default:                                              /* parent */
-               /* close the "write" end of the pipe */ 
-               close(r0w1[1]);
-
-               return r0w1[0];
-       }
-}
-
-#endif /* non-DOS */
-
-#if OSK
-
-/* This private function opens a pipe from a filter.  It is similar to the
- * system() function above, and to popen(cmd, "r").
- */
-int rpipe(cmd, in)
-       char    *cmd;   /* the filter command to use */
-       int     in;     /* the fd to use for stdin */
-{
-       return osk_popen(cmd, "r", in, 0);
-}      
-#endif
-
-#if ANY_UNIX || OSK
-
-/* This function closes the pipe opened by rpipe(), and returns 0 for success */
-int rpclose(fd)
-       int     fd;
-{
-       int     status;
-
-       close(fd);
-       wait(&status);
-       signal(SIGINT, (void (*)()) trapint);
-       return status;
-}
-
-#endif /* non-DOS */
-
-/* This function expands wildcards in a filename or filenames.  It does this
- * by running the "echo" command on the filenames via the shell; it is assumed
- * that the shell will expand the names for you.  If for any reason it can't
- * run echo, then it returns the names unmodified.
- */
-
-#if MSDOS || TOS
-#define        PROG    "wildcard "
-#define        PROGLEN 9
-#include <string.h>
-#else
-#define        PROG    "echo "
-#define        PROGLEN 5
-#endif
-
-#if !AMIGA
-char *wildcard(names)
-       char    *names;
-{
-
-# if VMS
-/* 
-   We could use expand() [vmswild.c], but what's the point on VMS? 
-   Anyway, echo is the wrong thing to do, it takes too long to build
-   a subprocess on VMS and any "echo" program would have to be supplied
-   by elvis.  More importantly, many VMS utilities expand names 
-   themselves (the shell doesn't do any expansion) so the concept is
-   non-native.  jdc
-*/
-       return names;
-# else
-
-       int     i, j, fd;
-       REG char *s, *d;
-
-
-       /* build the echo command */
-       if (names != tmpblk.c)
-       {
-               /* the names aren't in tmpblk.c, so we can do it the easy way */
-               strcpy(tmpblk.c, PROG);
-               strcat(tmpblk.c, names);
-       }
-       else
-       {
-               /* the names are already in tmpblk.c, so shift them to make
-                * room for the word "echo "
-                */
-               for (s = names + strlen(names) + 1, d = s + PROGLEN; s > names; )
-               {
-                       *--d = *--s;
-               }
-               strncpy(names, PROG, PROGLEN);
-       }
-
-       /* run the command & read the resulting names */
-       fd = rpipe(tmpblk.c, 0);
-       if (fd < 0) return names;
-       i = 0;
-       do
-       {
-               j = tread(fd, tmpblk.c + i, BLKSIZE - i);
-               i += j;
-       } while (j > 0);
-
-       /* successful? */
-       if (rpclose(fd) == 0 && j == 0 && i < BLKSIZE && i > 0)
-       {
-               tmpblk.c[i-1] = '\0'; /* "i-1" so we clip off the newline */
-               return tmpblk.c;
-       }
-       else
-       {
-               return names;
-       }
-# endif
-}
-#endif
-
-/* This function runs a range of lines through a filter program, and replaces
- * the original text with the filtered version.  As a special case, if "to"
- * is MARK_UNSET, then it runs the filter program with stdin coming from
- * /dev/null, and inserts any output lines.
- */
-int filter(from, to, cmd, back)
-       MARK    from, to;       /* the range of lines to filter */
-       char    *cmd;           /* the filter command */
-       int     back;           /* boolean: will we read lines back? */
-{
-       int     scratch;        /* fd of the scratch file */
-       int     fd;             /* fd of the pipe from the filter */
-       char    scrout[50];     /* name of the scratch out file */
-       MARK    new;            /* place where new text should go */
-       long    sent, rcvd;     /* number of lines sent/received */
-       int     i, j;
-
-       /* write the lines (if specified) to a temp file */
-       if (to)
-       {
-               /* we have lines */
-#if MSDOS || TOS
-               strcpy(scrout, o_directory);
-               if ((i=strlen(scrout)) && !strchr("\\/:", scrout[i-1]))
-                       scrout[i++]=SLASH;
-               strcpy(scrout+i, SCRATCHOUT+3);
-#else
-               sprintf(scrout, SCRATCHOUT, o_directory);
-#endif
-               mktemp(scrout);
-               cmd_write(from, to, CMD_BANG, FALSE, scrout);
-               sent = markline(to) - markline(from) + 1L;
-
-               /* use those lines as stdin */
-               scratch = open(scrout, O_RDONLY);
-               if (scratch < 0)
-               {
-                       unlink(scrout);
-                       return -1;
-               }
-       }
-       else
-       {
-               scratch = 0;
-               sent = 0L;
-       }
-
-       /* start the filter program */
-#if VMS
-       /* 
-          VMS doesn't know a thing about file descriptor 0.  The rpipe
-          concept is non-portable.  Hence we need a file name argument.
-       */
-       fd = rpipe(cmd, scratch, scrout);
-#else
-       fd = rpipe(cmd, scratch);
-#endif
-       if (fd < 0)
-       {
-               if (to)
-               {
-                       close(scratch);
-                       unlink(scrout);
-               }
-               return -1;
-       }
-
-       if (back)
-       {
-               ChangeText
-               {
-                       /* adjust MARKs for whole lines, and set "new" */
-                       from &= ~(BLKSIZE - 1);
-                       if (to)
-                       {
-                               to &= ~(BLKSIZE - 1);
-                               to += BLKSIZE;
-                               new = to;
-                       }
-                       else
-                       {
-                               new = from + BLKSIZE;
-                       }
-
-#if VMS
-/* Reading from a VMS mailbox (pipe) is record oriented... */
-# define tread vms_pread
-#endif
-
-                       /* repeatedly read in new text and add it */
-                       rcvd = 0L;
-                       while ((i = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
-                       {
-                               tmpblk.c[i] = '\0';
-                               add(new, tmpblk.c);
-#if VMS
-                               /* What!  An advantage to record oriented reads? */
-                               new += (i - 1);
-                               new = (new & ~(BLKSIZE - 1)) + BLKSIZE;
-                               rcvd++;
-#else
-                               for (i = 0; tmpblk.c[i]; i++)
-                               {
-                                       if (tmpblk.c[i] == '\n')
-                                       {
-                                               new = (new & ~(BLKSIZE - 1)) + BLKSIZE;
-                                               rcvd++;
-                                       }
-                                       else
-                                       {
-                                               new++;
-                                       }
-                               }
-#endif
-                       }
-               }
-
-               /* delete old text, if any */
-               if (to)
-               {
-                       cut(from, to);
-                       delete(from, to);
-               }
-       }
-       else
-       {
-               /* read the command's output, and copy it to the screen */
-               while ((i = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
-               {
-                       for (j = 0; j < i; j++)
-                       {
-                               addch(tmpblk.c[j]);
-                       }
-               }
-               rcvd = 0;
-       }
-
-       /* Reporting... */
-       if (sent >= *o_report || rcvd >= *o_report)
-       {
-               if (sent > 0L && rcvd > 0L)
-               {
-                       msg("%ld lines out, %ld lines back", sent, rcvd);
-               }
-               else if (sent > 0)
-               {
-                       msg("%ld lines written to filter", sent);
-               }
-               else
-               {
-                       msg("%ld lines read from filter", rcvd);
-               }
-       }
-       rptlines = 0L;
-
-       /* cleanup */
-       rpclose(fd);
-       if (to)
-       {
-               close(scratch);
-               unlink(scrout);
-       }
-       return 0;
-}
diff --git a/commands/elvis/tinyprnt.c b/commands/elvis/tinyprnt.c
deleted file mode 100644 (file)
index c67add6..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/* tinyprnt.c */
-
-#if OSK
-#define sprintf Sprintf
-#endif
-
-/* This is a limited version of sprintf().  It is useful for Minix-PC and
- * Coherent-286 because those systems are both limited to 64k+64k and the
- * standard sprintf() is just too damn big.
- *
- * It should also be useful for OS-9 because OS-9's sprintf() doesn't
- * understand the true meaning of asterisks in a format string.  This one
- * does.
- */
-
-/* Place-holders in format strings look like "%<pad><clip><type>".
- *
- * The <pad> adds space to the front (or, if negative, to the back) of the
- * output value, to pad it to a given width.  If <pad> is absent, then 0 is
- * assumed.  If <pad> is an asterisk, then the next argument is assumed to
- * be an (int) which used as the pad width.
- *
- * The <clip> string can be absent, in which case no clipping is done.
- * However, if it is present, then it should be either a "." followed by
- * a number, or a "." followed by an asterisk.  The asterisk means that the
- * next argument is an (int) which should be used as the pad width.  Clipping
- * only affects strings; for other data types it is ignored.
- *
- * The <type> is one of "s" for strings, "c" for characters (really ints that
- * are assumed to be legal char values), "d" for ints, "ld" for long ints, or
- * "%" to output a percent sign.
- */
-
-/* NOTE: Variable argument lists are handled by direct stack-twiddling. Sorry! */
-
-static void cvtnum(buf, num, base)
-       char            *buf;   /* where to store the number */
-       unsigned long   num;    /* the number to convert */
-       int             base;   /* either 8, 10, or 16 */
-{
-       static char     digits[] = "0123456789abcdef";
-       unsigned long   tmp;
-
-       /* if the number is 0, then just stuff a "0" into the buffer */
-       if (num == 0L)
-       {
-               buf[0] = '0';
-               buf[1] = '\0';
-               return;
-       }
-
-       /* use tmp to figure out how many digits we'll need */
-       for (tmp = num; tmp > 0; tmp /= base)
-       {
-               buf++;
-       }
-
-       /* mark the spot that will be the end of the string */
-       *buf = '\0';
-
-       /* generate all digits, as needed */
-       for (tmp = num; tmp > 0; tmp /= base)
-       {
-               *--buf = digits[tmp % base];
-       }
-}
-
-int sprintf(buf, fmt, argref)
-       char    *buf;   /* where to deposit the formatted output */
-       char    *fmt;   /* the format string */
-       int     argref; /* the first argument is located at &argref */
-{
-       char    *argptr;/* pointer to next argument on the stack */
-       int     pad;    /* value of the pad string */
-       int     clip;   /* value of the clip string */
-       long    num;    /* a binary number being converted to ASCII digits */
-       long    digit;  /* used during conversion */
-       char    *src, *dst;
-
-       /* make argptr point to the first argument after the format string */
-       argptr = (char *)&argref;
-
-       /* loop through the whole format string */
-       while (*fmt)
-       {
-               /* if not part of a place-holder, then copy it literally */
-               if (*fmt != '%')
-               {
-                       *buf++ = *fmt++;
-                       continue;
-               }
-
-               /* found a place-holder!  Get <pad> value */
-               fmt++;
-               if ('*' == *fmt)
-               {
-                       pad = *((int *)argptr)++;
-                       fmt++;
-               }
-               else if (*fmt == '-' || (*fmt >= '0' && *fmt <= '9'))
-               {
-                       pad = atol(fmt);
-                       do
-                       {
-                               fmt++;
-                       } while (*fmt >= '0' && *fmt <= '9');
-               }
-               else
-               {
-                       pad = 0;
-               }
-
-               /* get a <clip> value */
-               if (*fmt == '.')
-               {
-                       fmt++;
-                       if ('*' == *fmt)
-                       {
-                               clip = *((int *)argptr)++;
-                               fmt++;
-                       }
-                       else if (*fmt >= '0' && *fmt <= '9')
-                       {
-                               clip = atol(fmt);
-                               do
-                               {
-                                       fmt++;
-                               } while (*fmt >= '0' && *fmt <= '9');
-                       }
-               }
-               else
-               {
-                       clip = 0;
-               }
-
-               /* handle <type>, possibly noticing <clip> */
-               switch (*fmt++)
-               {
-                 case 'c':
-                       buf[0] = *((int *)argptr)++;
-                       buf[1] = '\0';
-                       break;
-
-                 case 's':
-                       src = *((char **)argptr)++;
-                       if (!src)
-                       {
-                               src = "(null)";
-                       }
-                       if (clip)
-                       {
-                               strncpy(buf, src, clip);
-                               buf[clip] = '\0';
-                       }
-                       else
-                       {
-                               strcpy(buf, src);
-                       }
-                       break;
-
-                 case 'l':
-                       fmt++; /* to skip the "d" in "%ld" */
-                       num = *((long *)argptr)++;
-                       dst = buf;
-                       if (num < 0)
-                       {
-                               *dst++ = '-';
-                               num = -num;
-                       }
-                       cvtnum(dst, num, 10);
-                       break;
-
-                 case 'x':
-                       num = *((int *)argptr)++;
-                       cvtnum(buf, num, 16);
-                       break;
-
-                 case 'd':
-                       num = *((int *)argptr)++;
-                       dst = buf;
-                       if (num < 0)
-                       {
-                               *dst++ = '-';
-                               num = -num;
-                       }
-                       cvtnum(dst, num, 10);
-                       break;
-
-                 default:
-                       buf[0] = fmt[-1];
-                       buf[1] = '\0';
-               }
-
-               /* now fix the padding, if the value is too short */
-               clip = strlen(buf);
-               if (pad < 0)
-               {
-                       /* add spaces after the value */
-                       pad = -pad - clip;
-                       for (buf += clip; pad > 0; pad--)
-                       {
-                               *buf++ = ' ';
-                       }
-                       *buf = '\0';
-               }
-               else
-               {
-                       /* add spaces before the value */
-                       pad -= clip;
-                       if (pad > 0)
-                       {
-                               src = buf + clip;
-                               dst = src + pad;
-                               *dst = '\0';
-                               while (src > buf)
-                               {
-                                       *--dst = *--src;
-                               }
-                               while (dst > buf)
-                               {
-                                       *--dst = ' ';
-                               }
-                       }
-                       buf += strlen(buf);
-               }
-       }
-
-       /* mark the end of the output string */
-       *buf = '\0';
-}
diff --git a/commands/elvis/tinytcap.c b/commands/elvis/tinytcap.c
deleted file mode 100644 (file)
index 922260f..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/* tinytcap.c */
-
-/* This file contains functions which simulate the termcap functions.
- *
- * It doesn't access a "termcap" file.  Instead, it uses an initialized array
- * of strings to store the entries.  Any string that doesn't start with a ':'
- * is taken to be the name of a type of terminal.  Any string that does start
- * with a ':' is interpretted as the list of fields describing all of the
- * terminal types that precede it.
- *
- * Note: since these are C strings, you can't use special sequences like
- * ^M or \E in the fields; your C compiler won't understand them.  Also,
- * at run time there is no way to tell the difference between ':' and '\072'
- * so I sure hope your terminal definition doesn't require a ':' character.
- *
- * getenv(TERM) on VMS checks the SET TERM device setting.  To implement
- * non-standard terminals set the logical ELVIS_TERM in VMS. (jdc)
- *
- * Other possible terminal types are...
- *     TERM_WYSE925    - "wyse925", a Wyse 50 terminal emulating Televideo 925
- * ... or you could set $TERMCAP to the terminal's description string, which
- * $TERM set up to match it.
- *
- * Note that you can include several terminal types at the same time.  Elvis
- * chooses which entry to use at runtime, based primarily on the value of $TERM.
- */
-
-
-#include "config.h"
-extern char *getenv();
-
-/* decide which terminal descriptions should *always* be included. */
-#if MSDOS
-# define       TERM_NANSI
-# define       TERM_DOSANSI
-# if RAINBOW
-#  define      TERM_RAINBOW
-# endif
-#endif
-
-#if VMS
-# define       TERM_VT100
-# define       TERM_VT100W
-# define       TERM_VT52
-#endif
-
-#if AMIGA
-# define       TERM_AMIGA      /* Internal Amiga termcap entry */
-/* # define    TERM_VT52       /* The rest of these are here for those */
-# define       TERM_VT100      /* people who want to use elvis over an */
-/* # define    TERM_NANSI      /* AUX: port (serial.device). */
-/* # define    TERM_DOSANSI    /* Take out all but AMIGA to save memory. */
-/* # define    TERM_MINIX      /* Vanilla ANSI? */
-/* # define    TERM_925        /* Hang a terminal off your Amiga */
-#endif
-
-#if MINIX || UNIXV
-# define       TERM_MINIX
-#endif
-
-#if COHERENT
-# define       TERM_COHERENT
-#endif
-
-#if TOS
-# define       TERM_ATARI
-#endif
-
-static char *termcap[] =
-{
-#ifdef TERM_AMIGA
-"AA",
-"amiga",
-"Amiga ANSI",
-/* Amiga termcap modified from version 1.3 by Kent Polk */
-":co#80:li#24:am:bs:bw:xn:\
-:AL=\233%dL:DC=\233%dP:DL=\233%dM:DO=\233%dB:\
-:LE=\233%dD:RI=\233%dC:SF=\233%dS:SR=\233%dT:UP=\233%dA:IC=\233%d@:\
-:ae=\2330m:al=\233L:as=\2333m:bl=\007:bt=\233Z:cd=\233J:\
-:ce=\233K:cl=\013:cm=\233%i%d;%dH:dc=\233P:dl=\233M:do=\233B:\
-:kb=^H:ho=\233H:ic=\233@:is=\23320l:\
-:mb=\2337;2m:md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:nd=\233C:\
-:rs=\033c:se=\2330m:sf=\233S:so=\2337m:sb=\233T:sr=\233T:ue=\23323m:\
-:up=\233A:us=\2334m:vb=\007:ve=\233\040p:vi=\2330\040p:\
-:k1=\2330~:k2=\2331~:k3=\2332~:k4=\2333~:k5=\2334~:\
-:k6=\2335~:k7=\2336~:k8=\2337~:k9=\2338~:k0=\2339~:\
-:s1=\23310~:s2=\23311~:s3=\23312~:s4=\23313~:s5=\23314~:\
-:s6=\23315~:s7=\23316~:s8=\23317~:s9=\23318~:s0=\23319~:\
-:kd=\233B:kl=\233D:kn#10:kr=\233C:ku=\233A:le=\233D:\
-:kP=\233T:kN=\233S:kh=\233\040A:kH=\233\040@:",
-#endif
-
-#ifdef TERM_NANSI
-"fansi",
-"nnansi",
-"nansi",
-"pcbios",
-":al=\033[L:dl=\033[M:am:bs:ce=\033[K:cl=\033[2J:\
-:cm=\033[%i%d;%dH:co#80:do=\033[B:\
-:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
-:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
-:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
-:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
-:kd=#P:kh=#G:kH=#O:kI=#R:kl=#K:kN=#Q:kP=#I:kr=#M:ku=#H:\
-:li#25:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
-:ue=\033[m:up=\033[A:us=\033[4m:",
-#endif
-
-#ifdef TERM_DOSANSI
-#if !ANY_UNIX
-"ansi",
-#endif
-"dosansi",
-":am:bs:ce=\033[K:cl=\033[2J:\
-:cm=\033[%i%d;%dH:co#80:do=\033[B:\
-:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
-:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
-:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
-:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
-:kd=#P:kh=#G:kH=#O:kI=#R:kl=#K:kN=#Q:kP=#I:kr=#M:ku=#H:\
-:li#25:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
-:ue=\033[m:up=\033[A:us=\033[4m:",
-#endif
-
-#ifdef TERM_RAINBOW
-"vt220",
-"rainbow",
-":al=\033[L:dl=\033[M:am:bs:ce=\033[K:cl=\033[2J:\
-:cm=\033[%i%d;%dH:co#80:do=\033[B:kd=\033[B:kl=\033[D:\
-:kr=\033[C:ku=\033[A:kP=\033[5~:kN=\033[6~:kI=\033[2~:\
-:li#24:md=\033[1m:me=\033[m:nd=\033[C:se=\033[m:so=\033[7m:\
-:ue=\033[m:up=\033[A:us=\033[4m:xn:",
-#endif
-
-#ifdef TERM_VT100
-"vt100-80",
-"vt200-80",
-"vt300-80",
-"vt101-80",
-"vt102-80",
-":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
-:co#80:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
-:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
-:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
-:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
-:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:nd=\033[C:\
-:se=\033[m:so=\033[7m:ti=\033[1;24r\033[24;1H:\
-:ue=\033[m:up=\033[A:us=\033[4m:xn:",
-#endif
-
-#ifdef TERM_VT100W
-"vt100-w",
-"vt200-w",
-"vt300-w",
-"vt101-w",
-"vt102-w",
-"vt100-132",
-"vt200-132",
-"vt300-132",
-"vt101-132",
-"vt102-132",
-":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
-:co#132:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
-:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
-:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
-:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
-:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:nd=\033[C:\
-:se=\033[m:so=\033[7m:ti=\033[1;24r\033[24;1H:\
-:ue=\033[m:up=\033[A:us=\033[4m:xn:",
-#endif
-
-#ifdef TERM_VT52
-"vt52",
-":do=\n:le=\b:up=\033A:nd=\033C:cm=\033Y%+ %+ :ti=\033e\033v:\
-:sr=\033I:cd=\033J:ce=\033K:cl=\033H\033J:co#80:li#24:\
-:ku=\033A:kd=\033B:kr=\033C:kl=\033D:kb=\b:pt:am:xn:bs:",
-#endif
-
-#ifdef TERM_MINIX
-"minix",
-"ansi",
-"AT386",
-":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
-:co#80:dl=\033[M:do=\033[B:k0=\033[20~:k1=\033[1~:\
-:k2=\033[2~:k3=\033[3~:k4=\033[4~:k5=\033[5~:k6=\033[6~:\
-:k7=\033[17~:k8=\033[18~:k9=\033[19~:kd=\033[B:kh=\033[H:\
-:kH=\033[Y:kI=\033[I:kl=\033[D:kN=\033[U:kP=\033[V:\
-:kr=\033[C:ku=\033[A:li#25:md=\033[1m:me=\033[m:nd=\033[C:\
-:se=\033[m:so=\033[7m:ue=\033[m:up=\033[A:us=\033[4m:",
-#endif /* MINIX */
-
-#ifdef TERM_COHERENT
-"coherent",
-"ansipc",
-":al=\033[L:am:bs:ce=\033[K:cl=\033[2J:cm=\033[%i%d;%dH:\
-:co#80:dl=\033[M:do=\033[B:k0=\033[0x:k1=\033[1x:k2=\033[2x:\
-:k3=\033[3x:k4=\033[4x:k5=\033[5x:k6=\033[6x:\
-:k7=\033[7x:k8=\033[8x:k9=\033[9x:kd=\033[B:kh=\033[H:\
-:kH=\033[24H:kI=\033[@:kl=\033[D:kN=\033[U:kP=\033[V:\
-:kr=\033[C:ku=\033[A:li#24:md=\033[1m:me=\033[m:\
-:nd=\033[C:se=\033[m:so=\033[7m:ue=\033[m:up=\033[A:\
-:us=\033[4m:",
-#endif /* COHERENT */
-
-#ifdef TERM_ATARI
-"atari-st",
-"vt52",
-":al=\033L:am:bs:ce=\033K:cl=\033E:cm=\033Y%i%+ %+ :\
-:co#80:dl=\033M:do=\033B:\
-:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\
-:s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\
-:c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\
-:a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\
-kd=#P:kh=#G:kI=#R:kl=#K:kr=#M:ku=#H:li#25:nd=\033C:se=\033q:\
-:so=\033p:te=:ti=\033e\033v:up=\033A:",
-#endif
-
-#ifdef TERM_925
-"wyse925",
-":xn@:\
-:hs:am:bs:co#80:li#24:cm=\033=%+ %+ :cl=\033*:cd=\033y:\
-:ce=\033t:is=\033l\033\":\
-:al=\033E:dl=\033R:im=:ei=:ic=\033Q:dc=\033W:\
-:ho=\036:nd=\014:bt=\033I:pt:so=\033G4:se=\033G0:sg#1:us=\033G8:ue=\033G0:ug#1:\
-:up=\013:do=\026:kb=\010:ku=\013:kd=\026:kl=\010:kr=\014:\
-:kh=\036:ma=\026\012\014 :\
-:k1=\001@\r:k2=\001A\r:k3=\001B\r:k4=\001C\r:k5=\001D\r:k6=\001E\r:k7=\001F\r:\
-:k8=\001G\r:k9=\001H\r:k0=\001I\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\
-:ts=\033f:fs=\033g:ds=\033h:sr=\033j:",  /* was :xn: for tvi925 alone*/
-#endif
-
-(char *)0
-};
-
-
-static char *fields;
-
-
-/*ARGSUSED*/
-int tgetent(bp, name)
-       char    *bp;    /* buffer for storing the entry -- ignored */
-       char    *name;  /* name of the entry */
-{
-       int     i;
-
-       /* if TERMCAP is defined, and seems to match, then use it */
-       fields = getenv("TERMCAP");
-       if (fields)
-       {
-               for (i = 0; fields[i] && fields[i] != ':'; i++)
-               {
-                       if (!strncmp(fields + i, name, strlen(name)))
-                       {
-                               return 1;
-                       }
-               }
-       }
-
-       /* locate the entry in termcap[] */
-       for (i = 0; termcap[i] && strcmp(termcap[i], name); i++)
-       {
-       }
-       if (!termcap[i])
-       {
-               return 0;
-       }
-
-       /* search forward for fields */
-       while (termcap[i][0] != ':')
-       {
-               i++;
-       }
-       fields = termcap[i];
-       return 1;
-}
-
-
-static char *find(id, vtype)
-       char    *id;    /* name of a value to locate */
-       int     vtype;  /* '=' for strings, '#' for numbers, or 0 for bools */
-{
-       int     i;
-
-       /* search for a ':' followed by the two-letter id */
-       for (i = 0; fields[i]; i++)
-       {
-               if (fields[i] == ':'
-                && fields[i + 1] == id[0]
-                && fields[i + 2] == id[1])
-               {
-                       /* if correct type, then return its value */
-                       if (fields[i + 3] == vtype)
-                               return &fields[i + 4];
-                       else
-                               return (char *)0;
-               }
-       }
-       return (char *)0;
-}
-
-int tgetnum(id)
-       char    *id;
-{
-       id = find(id, '#');
-       if (id)
-       {
-               return atoi(id);
-       }
-       return -1;
-}
-
-int tgetflag(id)
-       char    *id;
-{
-       if (find(id, ':'))
-       {
-               return 1;
-       }
-       return 0;
-}
-
-/*ARGSUSED*/
-char *tgetstr(id, bp)
-       char    *id;
-       char    **bp;   /* pointer to pointer to buffer - ignored */
-{
-       char    *cpy;
-
-       /* find the string */
-       id = find(id, '=');
-       if (!id)
-       {
-               return (char *)0;
-       }
-
-       /* copy it into the buffer, and terminate it with NUL */
-       for (cpy = *bp; *id != ':'; )
-       {
-               if (id[0] == '\\' && id[1] == 'E')
-                       *cpy++ = '\033', id += 2;
-               else
-                       *cpy++ = *id++;
-       }
-       *cpy++ = '\0';
-
-       /* update the bp pointer */
-       id = *bp;
-       *bp = cpy;
-
-       /* return a pointer to the copy of the string */
-       return id;
-}
-
-/*ARGSUSED*/
-char *tgoto(cm, destcol, destrow)
-       char    *cm;    /* cursor movement string -- ignored */
-       int     destcol;/* destination column, 0 - 79 */
-       int     destrow;/* destination row, 0 - 24 */
-{
-       static char buf[30];
-
-#ifdef CRUNCH
-# if TOS
-       sprintf(buf, "\033Y%c%c", ' ' + destrow, ' ' + destcol);
-# else
-       sprintf(buf, "\033[%d;%dH", destrow + 1, destcol + 1);
-# endif
-#else
-       if (cm[1] == 'Y' || cm[1] == '=')
-               sprintf(buf, "\033%c%c%c", cm[1], ' ' + destrow, ' ' + destcol);
-       else
-               sprintf(buf, "\033[%d;%dH", destrow + 1, destcol + 1);
-#endif
-       return buf;
-}
-
-/*ARGSUSED*/
-void tputs(cp, affcnt, outfn)
-       char    *cp;            /* the string to output */
-       int     affcnt;         /* number of affected lines -- ignored */
-       int     (*outfn)();     /* the output function */
-{
-       while (*cp)
-       {
-               (*outfn)(*cp);
-               cp++;
-       }
-}
diff --git a/commands/elvis/tio.c b/commands/elvis/tio.c
deleted file mode 100644 (file)
index 66bd261..0000000
+++ /dev/null
@@ -1,1026 +0,0 @@
-/* tio.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains terminal I/O functions */
-
-#include "config.h"
-#include "vi.h"
-#include "ctype.h"
-
-
-/* This function reads in a line from the terminal. */
-int vgets(prompt, buf, bsize)
-       char    prompt; /* the prompt character, or '\0' for none */
-       char    *buf;   /* buffer into which the string is read */
-       int     bsize;  /* size of the buffer */
-{
-       int     len;    /* how much we've read so far */
-       int     ch;     /* a character from the user */
-       int     quoted; /* is the next char quoted? */
-       int     tab;    /* column position of cursor */
-       char    widths[132];    /* widths of characters */
-       int     word;   /* index of first letter of word */
-#ifndef NO_DIGRAPH
-       int     erased; /* 0, or first char of a digraph */
-#endif
-
-       /* show the prompt */
-       move(LINES - 1, 0);
-       tab = 0;
-       if (prompt)
-       {
-               addch(prompt);
-               tab = 1;
-       }
-       clrtoeol();
-       refresh();
-
-       /* read in the line */
-#ifndef NO_DIGRAPH
-       erased =
-#endif
-       quoted = len = 0;
-       for (;;)
-       {
-#ifndef NO_ABBR
-               if (quoted || mode == MODE_EX)
-               {
-                       ch = getkey(0);
-               }
-               else
-               {
-                       /* maybe expand an abbreviation while getting key */
-                       for (word = len; --word >= 0 && isalnum(buf[word]); )
-                       {
-                       }
-                       word++;
-                       ch = getabkey(WHEN_EX, &buf[word], len - word);
-               }
-#else
-               ch = getkey(0);
-#endif
-#ifndef NO_EXTENSIONS
-               if (ch == ctrl('O'))
-               {
-                       ch = getkey(quoted ? 0 : WHEN_EX);
-               }
-#endif
-
-               /* some special conversions */
-               if (ch == ctrl('D') && len == 0)
-                       ch = ctrl('[');
-#ifndef NO_DIGRAPH
-               if (*o_digraph && erased != 0 && ch != '\b')
-               {
-                       ch = digraph(erased, ch);
-                       erased = 0;
-               }
-#endif
-
-               /* inhibit detection of special chars (except ^J) after a ^V */
-               if (quoted && ch != '\n')
-               {
-                       ch |= 256;
-               }
-
-               /* process the character */
-               switch(ch)
-               {
-                 case ctrl('V'):
-                       qaddch('^');
-                       qaddch('\b');
-                       quoted = TRUE;
-                       break;
-
-                 case ctrl('['):
-                       return -1;
-
-                 case '\n':
-#if OSK
-                 case '\l':
-#else
-                 case '\r':
-#endif
-                       clrtoeol();
-                       goto BreakBreak;
-
-                 case '\b':
-                       if (len > 0)
-                       {
-                               len--;
-#ifndef NO_DIGRAPH
-                               erased = buf[len];
-#endif
-                               for (ch = widths[len]; ch > 0; ch--)
-                                       addch('\b');
-                               if (mode == MODE_EX)
-                               {
-                                       clrtoeol();
-                               }
-                               tab -= widths[len];
-                       }
-                       else
-                       {
-                               return -1;
-                       }
-                       break;
-
-                 default:
-                       /* strip off quotation bit */
-                       if (ch & 256)
-                       {
-                               ch &= ~256;
-                               qaddch(' ');
-                               qaddch('\b');
-                       }
-
-                       /* add & echo the char */
-                       if (len < bsize - 1)
-                       {
-                               if (ch == '\t' && !quoted)
-                               {
-                                       widths[len] = *o_tabstop - (tab % *o_tabstop);
-                                       addstr("        " + 8 - widths[len]);
-                                       tab += widths[len];
-                               }
-                               else if (ch > 0 && ch < ' ') /* > 0 by GB */
-                               {
-                                       addch('^');
-                                       addch(ch + '@');
-                                       widths[len] = 2;
-                                       tab += 2;
-                               }
-                               else if (ch == '\177')
-                               {
-                                       addch('^');
-                                       addch('?');
-                                       widths[len] = 2;
-                                       tab += 2;
-                               }
-                               else
-                               {
-                                       addch(ch);
-                                       widths[len] = 1;
-                                       tab++;
-                               }
-                               buf[len++] = ch;
-                       }
-                       else
-                       {
-                               beep();
-                       }
-                       quoted = FALSE;
-               }
-       }
-BreakBreak:
-       refresh();
-       buf[len] = '\0';
-       return len;
-}
-
-
-static int     manymsgs; /* This variable keeps msgs from overwriting each other */
-static char    pmsg[80]; /* previous message (waiting to be displayed) */
-
-
-static int showmsg()
-{
-       /* if there is no message to show, then don't */
-       if (!manymsgs)
-               return FALSE;
-
-       /* display the message */
-       move(LINES - 1, 0);
-       if (*pmsg)
-       {
-               standout();
-               qaddch(' ');
-               qaddstr(pmsg);
-               qaddch(' ');
-               standend();
-       }
-       clrtoeol();
-
-       manymsgs = FALSE;
-       return TRUE;
-}
-
-
-void endmsgs()
-{
-       if (manymsgs)
-       {
-               showmsg();
-               addch('\n');
-       }
-}
-
-/* Write a message in an appropriate way.  This should really be a varargs
- * function, but there is no such thing as vwprintw.  Hack!!!
- *
- * In MODE_EX or MODE_COLON, the message is written immediately, with a
- * newline at the end.
- *
- * In MODE_VI, the message is stored in a character buffer.  It is not
- * displayed until getkey() is called.  msg() will call getkey() itself,
- * if necessary, to prevent messages from being lost.
- *
- * msg("")             - clears the message line
- * msg("%s %d", ...)   - does a printf onto the message line
- */
-/*VARARGS1*/
-void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
-       char    *fmt;
-       long    arg1, arg2, arg3, arg4, arg5, arg6, arg7;
-{
-       if (mode != MODE_VI)
-       {
-               sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-               qaddstr(pmsg);
-               addch('\n');
-               exrefresh();
-       }
-       else
-       {
-               /* wait for keypress between consecutive msgs */
-               if (manymsgs)
-               {
-                       getkey(WHEN_MSG);
-               }
-
-               /* real message */
-               sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-               if (*fmt)
-               {
-                       manymsgs = TRUE;
-               }
-       }
-}
-
-
-/* This function calls refresh() if the option exrefresh is set */
-void exrefresh()
-{
-       char    *scan;
-
-       /* If this ex command wrote ANYTHING set exwrote so vi's  :  command
-        * can tell that it must wait for a user keystroke before redrawing.
-        */
-       for (scan=kbuf; scan<stdscr; scan++)
-               if (*scan == '\n')
-                       exwrote = TRUE;
-
-       /* now we do the refresh thing */
-       if (*o_exrefresh)
-       {
-               refresh();
-       }
-       else
-       {
-               wqrefresh();
-       }
-       if (mode != MODE_VI)
-       {
-               manymsgs = FALSE;
-       }
-}
-
-
-/* This structure is used to store maps and abbreviations.  The distinction
- * between them is that maps are stored in the list referenced by the "maps"
- * pointer, while abbreviations are referenced by the "abbrs" pointer.
- */
-typedef struct _map
-{
-       struct _map     *next;  /* another abbreviation */
-       short           len;    /* length of the "rawin" characters */
-       short           flags;  /* various flags */
-       char            *label; /* label of the map/abbr, or NULL */
-       char            *rawin; /* the "rawin" characters */
-       char            *cooked;/* the "cooked" characters */
-} MAP;
-
-static char    keybuf[KEYBUFSIZE];
-static int     cend;   /* end of input characters */
-static int     user;   /* from user through end are chars typed by user */
-static int     next;   /* index of the next character to be returned */
-static MAP     *match; /* the matching map, found by countmatch() */
-static MAP     *maps;  /* the map table */
-#ifndef NO_ABBR
-static MAP     *abbrs; /* the abbreviation table */
-#endif
-
-
-
-/* ring the terminal's bell */
-void beep()
-{
-       /* do a visible/audible bell */
-       if (*o_flash)
-       {
-               do_VB();
-               refresh();
-       }
-       else if (*o_errorbells)
-       {
-               ttywrite("\007", 1);
-       }
-
-       /* discard any buffered input, and abort macros */
-       next = user = cend;
-}
-
-
-
-/* This function replaces a "rawin" character sequence with the "cooked" version,
- * by modifying the internal type-ahead buffer.
- */
-void execmap(rawlen, cookedstr, visual)
-       int     rawlen;         /* length of rawin text -- string to delete */
-       char    *cookedstr;     /* the cooked text -- string to insert */
-       int     visual;         /* boolean -- chars to be executed in visual mode? */
-{
-       int     cookedlen;
-       char    *src, *dst;
-       int     i;
-
-       /* find the length of the cooked string */
-       cookedlen = strlen(cookedstr);
-#ifndef NO_EXTENSIONS
-       if (visual)
-       {
-               cookedlen *= 2;
-       }
-#endif
-
-       /* if too big to fit in type-ahead buffer, then don't do it */
-       if (cookedlen + (cend - next) - rawlen > KEYBUFSIZE)
-       {
-               return;
-       }
-
-       /* shift to make room for cookedstr at the front of keybuf */
-       src = &keybuf[next + rawlen];
-       dst = &keybuf[cookedlen];
-       i = cend - (next + rawlen);
-       if (src >= dst)
-       {
-               while (i-- > 0)
-               {
-                       *dst++ = *src++;
-               }
-       }
-       else
-       {
-               src += i;
-               dst += i;
-               while (i-- > 0)
-               {
-                       *--dst = *--src;
-               }
-       }
-
-       /* insert cookedstr, and adjust offsets */
-       cend += cookedlen - rawlen - next;
-       user += cookedlen - rawlen - next;
-       next = 0;
-       for (dst = keybuf, src = cookedstr; *src; )
-       {
-#ifndef NO_EXTENSIONS
-               if (visual)
-               {
-                       *dst++ = ctrl('O');
-                       cookedlen--;
-               }
-#endif
-               *dst++ = *src++;
-       }
-
-#ifdef DEBUG2
-       {
-#include <stdio.h>
-               FILE    *debout;
-               int             i;
-
-               debout = fopen("debug.out", "a");
-               fprintf(debout, "After execmap(%d, \"%s\", %d)...\n", rawlen, cookedstr, visual);
-               for (i = 0; i < cend; i++)
-               {
-                       if (i == next) fprintf(debout, "(next)");
-                       if (i == user) fprintf(debout, "(user)");
-                       if (UCHAR(keybuf[i]) < ' ')
-                               fprintf(debout, "^%c", keybuf[i] ^ '@');
-                       else
-                               fprintf(debout, "%c", keybuf[i]);
-               }
-               fprintf(debout, "(end)\n");
-               fclose(debout);
-       }
-#endif
-}
-
-/* This function calls ttyread().  If necessary, it will also redraw the screen,
- * change the cursor shape, display the mode, and update the ruler.  If the
- * number of characters read is 0, and we didn't time-out, then it exits because
- * we've apparently reached the end of an EX script.
- */
-static int fillkeybuf(when, timeout)
-       int     when;   /* mixture of WHEN_XXX flags */
-       int     timeout;/* timeout in 1/10 second increments, or 0 */
-{
-       int     nkeys;
-#ifndef NO_SHOWMODE
-       static int      oldwhen;        /* "when" from last time */
-       static int      oldleft;
-       static long     oldtop;
-       static long     oldnlines;
-       char            *str;
-#endif
-#ifndef NO_CURSORSHAPE
-       static int      oldcurs;
-#endif
-
-#ifdef DEBUG
-       watch();
-#endif
-
-
-#ifndef NO_CURSORSHAPE
-       /* make sure the cursor is the right shape */
-       if (has_CQ)
-       {
-               if (when != oldcurs)
-               {
-                       switch (when)
-                       {
-                         case WHEN_EX:         do_CX();        break;
-                         case WHEN_VICMD:      do_CV();        break;
-                         case WHEN_VIINP:      do_CI();        break;
-                         case WHEN_VIREP:      do_CR();        break;
-                       }
-                       oldcurs = when;
-               }
-       }
-#endif
-
-#ifndef NO_SHOWMODE
-       /* if "showmode" then say which mode we're in */
-       if (*o_smd && (when & WHENMASK))
-       {
-               /* redraw the screen before we check to see whether the
-                * "showmode" message needs to be redrawn.
-                */
-               redraw(cursor, !(when & WHEN_VICMD));
-
-               /* now the "topline" test should be valid */
-               if (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines)
-               {
-                       oldwhen = when;
-                       oldtop = topline;
-                       oldleft = leftcol;
-                       oldnlines = nlines;
-
-                       if (when & WHEN_VICMD)      str = "Command";
-                       else if (when & WHEN_VIINP) str = " Input ";
-                       else if (when & WHEN_VIREP) str = "Replace";
-                       else if (when & WHEN_REP1)  str = " Rep 1 ";
-                       else if (when & WHEN_CUT)   str = "BufName";
-                       else if (when & WHEN_MARK)  str = "Mark AZ";
-                       else if (when & WHEN_CHAR)  str = "Dest Ch";
-                       else                        str = (char *)0;
-
-                       if (str)
-                       {
-                               move(LINES - 1, COLS - 10);
-                               standout();
-                               qaddstr(str);
-                               standend();
-                       }
-               }
-       }
-#endif
-
-#ifndef NO_EXTENSIONS
-       /* maybe display the ruler */
-       if (*o_ruler && (when & (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)))
-       {
-               char    buf[20];
-
-               redraw(cursor, !(when & WHEN_VICMD));
-               pfetch(markline(cursor));
-               sprintf(buf, "%7ld,%-4d", markline(cursor), 1 + idx2col(cursor, ptext, when & (WHEN_VIINP|WHEN_VIREP)));
-               move(LINES - 1, COLS - 22);
-               addstr(buf);
-       }
-#endif
-
-       /* redraw, so the cursor is in the right place */
-       if (when & WHENMASK)
-       {
-               redraw(cursor, !(when & (WHENMASK & ~(WHEN_VIREP|WHEN_VIINP))));
-       }
-
-       /* Okay, now we can finally read the rawin keystrokes */
-       refresh();
-       nkeys = ttyread(keybuf + cend, sizeof keybuf - cend, timeout);
-
-       /* if nkeys == 0 then we've reached EOF of an ex script. */
-       if (nkeys == 0 && timeout == 0)
-       {
-               tmpabort(TRUE);
-               move(LINES - 1, 0);
-               clrtoeol();
-               refresh();
-               endwin();
-               exit(1);
-       }
-
-       cend += nkeys;
-       user += nkeys;
-       return nkeys;
-}
-
-
-/* This function counts the number of maps that could match the characters
- * between &keybuf[next] and &keybuf[cend], including incomplete matches.
- * The longest comlete match is remembered via the "match" variable.
- */
-static int countmatch(when)
-       int     when;   /* mixture of WHEN_XXX flags */
-{
-       MAP     *map;
-       int     count;
-
-       /* clear the "match" variable */
-       match = (MAP *)0;
-
-       /* check every map */
-       for (count = 0, map = maps; map; map = map->next)
-       {
-               /* can't match if wrong mode */
-               if ((map->flags & when) == 0)
-               {
-                       continue;
-               }
-
-               /* would this be a complete match? */
-               if (map->len <= cend - next)
-               {
-                       /* Yes, it would be.  Now does it really match? */
-                       if (!strncmp(map->rawin, &keybuf[next], map->len))
-                       {
-                               count++;
-
-                               /* if this is the longest complete match,
-                                * then remember it.
-                                */
-                               if (!match || match->len < map->len)
-                               {
-                                       match = map;
-                               }
-                       }
-               }
-               else
-               {
-                       /* No, it wouldn't.  But check for partial match */
-                       if (!strncmp(map->rawin, &keybuf[next], cend - next))
-                       {
-                               count++;
-                       }
-               }
-       }
-       return count;
-}
-
-
-#ifndef NO_ABBR
-/* This function checks to see whether a word is an abbreviation.  If it is,
- * then an appropriate number of backspoace characters is inserted into the
- * type-ahead buffer, followed by the expanded form of the abbreviation.
- */
-static void expandabbr(word, wlen)
-       char    *word;
-       int     wlen;
-{
-       MAP     *abbr;
-
-       /* if the next character wouldn't end the word, then don't expand */
-       if (isalnum(keybuf[next]) || keybuf[next] == ctrl('V'))
-       {
-               return;
-       }
-
-       /* find the abbreviation, if any */
-       for (abbr = abbrs;
-            abbr && (abbr->len != wlen || strncmp(abbr->rawin, word, wlen));
-            abbr = abbr->next)
-       {
-       }
-
-       /* If an abbreviation was found, then expand it by inserting the long
-        * version into the type-ahead buffer, and then inserting (in front of
-        * the long version) enough backspaces to erase to the short version.
-        */
-       if (abbr)
-       {
-               execmap(0, abbr->cooked, FALSE);
-               while (wlen > 15)
-               {
-                       execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", FALSE);
-                       wlen -= 15;
-               }
-               if (wlen > 0)
-               {
-                       execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + 15 - wlen, FALSE);
-               }
-       }
-}
-#endif
-
-
-/* This function calls getabkey() without attempting to expand abbreviations */
-int getkey(when)
-       int     when;   /* mixture of WHEN_XXX flags */
-{
-       return getabkey(when, "", 0);
-}
-
-
-/* This is it.  This function returns keystrokes one-at-a-time, after mapping
- * and abbreviations have been taken into account.
- */
-int getabkey(when, word, wlen)
-       int     when;   /* mixture of WHEN_XXX flags */
-       char    *word;  /* a word that may need to be expanded as an abbr */
-       int     wlen;   /* length of "word" -- since "word" might not have \0 */
-{
-       int     matches;
-
-       /* if this key is needed for delay between multiple error messages,
-        * then reset the manymsgs flag and abort any mapped key sequence.
-        */
-       if (showmsg())
-       {
-               if (when == WHEN_MSG)
-               {
-#ifndef CRUNCH
-                       if (!*o_more)
-                       {
-                               refresh();
-                               return ' ';
-                       }
-#endif
-                       qaddstr("[More...]");
-                       refresh();
-                       execmap(user, "", FALSE);
-               }
-       }
-
-#ifdef DEBUG
-       /* periodically check for screwed up internal tables */
-       watch();
-#endif
-
-       /* if buffer empty, read some characters without timeout */
-       if (next >= cend)
-       {
-               next = user = cend = 0;
-               fillkeybuf(when, 0);
-       }
-
-       /* try to map the key, unless already mapped and not ":set noremap" */
-       if (next >= user || *o_remap)
-       {
-               do
-               {
-                       do
-                       {
-                               matches = countmatch(when);
-                       } while (matches > 1 && fillkeybuf(when, *o_keytime) > 0);
-                       if (matches == 1)
-                       {
-                               execmap(match->len, match->cooked,
-                                       (match->flags & WHEN_INMV) != 0 
-                                        && (when & (WHEN_VIINP|WHEN_VIREP)) != 0);
-                       }
-               } while (*o_remap && matches == 1);
-       }
-
-#ifndef NO_ABBR
-       /* try to expand an abbreviation, except in visual command mode */
-       if (wlen > 0 && (mode & (WHEN_EX|WHEN_VIINP|WHEN_VIREP)) != 0)
-       {
-               expandabbr(word, wlen);
-       }
-#endif
-
-       /* ERASEKEY should always be mapped to '\b'. */
-       if (keybuf[next] == ERASEKEY)
-       {
-               keybuf[next] = '\b';
-       }
-
-       /* return the next key */
-       return keybuf[next++];
-}
-
-/* This function maps or unmaps a key */
-void mapkey(rawin, cooked, when, name)
-       char    *rawin; /* the input key sequence, before mapping */
-       char    *cooked;/* after mapping -- or NULL to remove map */
-       short   when;   /* bitmap of when mapping should happen */
-       char    *name;  /* name of the key, NULL for no name, "abbr" for abbr */
-{
-       MAP     **head; /* head of list of maps or abbreviations */
-       MAP     *scan;  /* used for scanning through the list */
-       MAP     *prev;  /* used during deletions */
-
-       /* Is this a map or an abbreviation?  Choose the right list. */
-#ifndef NO_ABBR
-       head = ((!name || strcmp(name, "abbr")) ? &maps : &abbrs);
-#else
-       head = &maps;
-#endif
-
-       /* try to find the map in the list */
-       for (scan = *head, prev = (MAP *)0;
-            scan && (strcmp(rawin, scan->rawin) ||
-               !(scan->flags & when & (WHEN_EX|WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)));
-            prev = scan, scan = scan->next)
-       {
-       }
-
-       /* trying to map? (not unmap) */
-       if (cooked && *cooked)
-       {
-               /* if map starts with "visual ", then mark it as a visual map */
-               if (head == &maps && !strncmp(cooked, "visual ", 7))
-               {
-                       cooked += 7;
-                       when |= WHEN_INMV;
-               }
-
-               /* "visual" maps always work in input mode */
-               if (when & WHEN_INMV)
-               {
-                       when |= WHEN_VIINP|WHEN_VIREP|WHEN_POPUP;
-               }
-
-               /* if not already in the list, then allocate a new structure */
-               if (!scan)
-               {
-                       scan = (MAP *)malloc(sizeof(MAP));
-                       scan->len = strlen(rawin);
-                       scan->rawin = malloc(scan->len + 1);
-                       strcpy(scan->rawin, rawin);
-                       scan->flags = when;
-                       scan->label = name;
-                       if (*head)
-                       {
-                               prev->next = scan;
-                       }
-                       else
-                       {
-                               *head = scan;
-                       }
-                       scan->next = (MAP *)0;
-               }
-               else /* recycle old structure */
-               {
-                       free(scan->cooked);
-               }
-               scan->cooked = malloc(strlen(cooked) + 1);
-               strcpy(scan->cooked, cooked);
-       }
-       else /* unmapping */
-       {
-               /* if nothing to unmap, then exit silently */
-               if (!scan)
-               {
-                       return;
-               }
-
-               /* unlink the structure from the list */
-               if (prev)
-               {
-                       prev->next = scan->next;
-               }
-               else
-               {
-                       *head = scan->next;
-               }
-
-               /* free it, and the strings that it refers to */
-               free(scan->rawin);
-               free(scan->cooked);
-               free(scan);
-       }
-}
-
-
-/* This function returns a printable version of a string.  It uses tmpblk.c */
-char *printable(str)
-       char    *str;   /* the string to convert */
-{
-       char    *build; /* used for building the string */
-
-       for (build = tmpblk.c; *str; str++)
-       {
-#if AMIGA
-               if (*str == '\233')
-               {
-                       *build++ = '<';
-                       *build++ = 'C';
-                       *build++ = 'S';
-                       *build++ = 'I';
-                       *build++ = '>';
-               } else 
-#endif
-               if (UCHAR(*str) < ' ' || *str == '\177')
-               {
-                       *build++ = '^';
-                       *build++ = *str ^ '@';
-               }
-               else
-               {
-                       *build++ = *str;
-               }
-       }
-       *build = '\0';
-       return tmpblk.c;
-}
-
-/* This function displays the contents of either the map table or the
- * abbreviation table.  User commands call this function as follows:
- *     :map    dumpkey(WHEN_VICMD, FALSE);
- *     :map!   dumpkey(WHEN_VIREP|WHEN_VIINP, FALSE);
- *     :abbr   dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE);
- *     :abbr!  dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE);
- */
-void dumpkey(when, abbr)
-       int     when;   /* WHEN_XXXX of mappings to be dumped */
-       int     abbr;   /* boolean: dump abbreviations instead of maps? */
-{
-       MAP     *scan;
-       char    *str;
-       int     len;
-
-#ifndef NO_ABBR
-       for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)
-#else
-       for (scan = maps; scan; scan = scan->next)
-#endif
-       {
-               /* skip entries that don't match "when" */
-               if ((scan->flags & when) == 0)
-               {
-                       continue;
-               }
-
-               /* dump the key label, if any */
-               if (!abbr)
-               {
-                       len = 8;
-                       if (scan->label)
-                       {
-                               qaddstr(scan->label);
-                               len -= strlen(scan->label);
-                       }
-                       do
-                       {
-                               qaddch(' ');
-                       } while (len-- > 0);
-               }
-
-               /* dump the rawin version */
-               str = printable(scan->rawin);
-               qaddstr(str);
-               len = strlen(str);
-               do
-               {
-                       qaddch(' ');
-               } while (len++ < 8);
-                       
-               /* dump the mapped version */
-#ifndef NO_EXTENSIONS
-               if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
-               {
-                       qaddstr("visual ");
-               }
-#endif
-               str = printable(scan->cooked);
-               qaddstr(str);
-               addch('\n');
-               exrefresh();
-       }
-}
-
-#ifndef NO_MKEXRC
-
-static safequote(str)
-       char    *str;
-{
-       char    *build;
-
-       build = tmpblk.c + strlen(tmpblk.c);
-       while (*str)
-       {
-               if (*str <= ' ' && *str >= 1 || *str == '|')
-               {
-                       *build++ = ctrl('V');
-               }
-               *build++ = *str++;
-       }
-       *build = '\0';
-}
-
-/* This function saves the contents of either the map table or the
- * abbreviation table into a file.  Both the "bang" and "no bang" versions
- * are saved.
- *     :map    dumpkey(WHEN_VICMD, FALSE);
- *     :map!   dumpkey(WHEN_VIREP|WHEN_VIINP, FALSE);
- *     :abbr   dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE);
- *     :abbr!  dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE);
- */
-savemaps(fd, abbr)
-       int     fd;     /* file descriptor of an open file to write to */
-       int     abbr;   /* boolean: do abbr table? (else do map table) */
-{
-       MAP     *scan;
-       char    *str;
-       int     bang;
-       int     when;
-       int     len;
-
-# ifndef NO_ABBR
-       for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)
-# else
-       for (scan = maps; scan; scan = scan->next)
-# endif
-       {
-               /* skip maps that have labels, except for function keys */
-               if (scan->label && *scan->label != '#')
-               {
-                       continue;
-               }
-
-               for (bang = 0; bang < 2; bang++)
-               {
-                       /* decide which "when" flags we want */
-# ifndef NO_ABBR
-                       if (abbr)
-                               when = (bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP);
-                       else
-# endif
-                               when = (bang ? WHEN_VIREP|WHEN_VIINP : WHEN_VICMD);
-
-                       /* skip entries that don't match "when" */
-                       if ((scan->flags & when) == 0)
-                       {
-                               continue;
-                       }
-
-                       /* write a "map" or "abbr" command name */
-# ifndef NO_ABBR
-                       if (abbr)
-                               strcpy(tmpblk.c, "abbr");
-                       else
-# endif
-                               strcpy(tmpblk.c, "map");
-
-                       /* maybe write a bang.  Definitely write a space */
-                       if (bang)
-                               strcat(tmpblk.c, "! ");
-                       else
-                               strcat(tmpblk.c, " ");
-
-                       /* write the rawin version */
-# ifndef NO_FKEY
-                       if (scan->label)
-                               strcat(tmpblk.c, scan->label);
-                       else
-# endif
-                               safequote(scan->rawin);
-                       strcat(tmpblk.c, " ");
-                               
-                       /* dump the mapped version */
-# ifndef NO_EXTENSIONS
-                       if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
-                       {
-                               strcat(tmpblk.c, "visual ");
-                       }
-# endif
-                       safequote(scan->cooked);
-                       strcat(tmpblk.c, "\n");
-                       twrite(fd, tmpblk.c, strlen(tmpblk.c));
-               }
-       }
-}
-#endif
diff --git a/commands/elvis/tmp.c b/commands/elvis/tmp.c
deleted file mode 100644 (file)
index 9102169..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-/* tmp.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains functions which create & readback a TMPFILE */
-
-
-#include "config.h"
-#include "vi.h"
-#if TOS
-# include <stat.h>
-#else
-# if OSK
-#  include "osk.h"
-# else
-#  if AMIGA
-#   include "amistat.h"
-#  else
-#   include <sys/stat.h>
-#  endif
-# endif
-#endif
-#if TURBOC
-# include <process.h>
-#endif
-
-#ifndef NO_MODELINES
-static void do_modelines(l, stop)
-       long    l;      /* line number to start at */
-       long    stop;   /* line number to stop at */
-{
-       char    *str;   /* used to scan through the line */
-       char    *start; /* points to the start of the line */
-       char    buf[80];
-
-       /* if modelines are disabled, then do nothing */
-       if (!*o_modelines)
-       {
-               return;
-       }
-
-       /* for each line... */
-       for (; l <= stop; l++)
-       {
-               /* for each position in the line.. */
-               for (str = fetchline(l); *str; str++)
-               {
-                       /* if it is the start of a modeline command... */
-                       if ((str[0] == 'e' && str[1] == 'x'
-                         || str[0] == 'v' && str[1] == 'i')
-                         && str[2] == ':')
-                       {
-                               start = str += 3;
-
-                               /* find the end */
-                               for (str = start + strlen(start); *--str != ':'; )
-                               {
-                               }
-
-                               /* if it is a well-formed modeline, execute it */
-                               if (str > start && str - start < sizeof buf)
-                               {
-                                       strncpy(buf, start, (int)(str - start));
-                                       exstring(buf, str - start, '\\');
-                                       break;
-                               }
-                       }
-               }
-       }
-}
-#endif
-
-
-/* The FAIL() macro prints an error message and then exits. */
-#define FAIL(why,arg)  mode = MODE_EX; msg(why, arg); endwin(); exit(9)
-
-/* This is the name of the temp file */
-static char    tmpname[80];
-
-/* This function creates the temp file and copies the original file into it.
- * Returns if successful, or stops execution if it fails.
- */
-int tmpstart(filename)
-       char            *filename; /* name of the original file */
-{
-       int             origfd; /* fd used for reading the original file */
-       struct stat     statb;  /* stat buffer, used to examine inode */
-       REG BLK         *this;  /* pointer to the current block buffer */
-       REG BLK         *next;  /* pointer to the next block buffer */
-       int             inbuf;  /* number of characters in a buffer */
-       int             nread;  /* number of bytes read */
-       REG int         j, k;
-       int             i;
-       long            nbytes;
-
-       /* switching to a different file certainly counts as a change */
-       changes++;
-       redraw(MARK_UNSET, FALSE);
-
-       /* open the original file for reading */
-       *origname = '\0';
-       if (filename && *filename)
-       {
-               strcpy(origname, filename);
-               origfd = open(origname, O_RDONLY);
-               if (origfd < 0 && errno != ENOENT)
-               {
-                       msg("Can't open \"%s\"", origname);
-                       return tmpstart("");
-               }
-               if (origfd >= 0)
-               {
-                       if (stat(origname, &statb) < 0)
-                       {
-                               FAIL("Can't stat \"%s\"", origname);
-                       }
-#if TOS
-                       if (origfd >= 0 && (statb.st_mode & S_IJDIR))
-#else
-# if OSK
-                       if (origfd >= 0 && (statb.st_mode & S_IFDIR))
-# else
-                       if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)
-# endif
-#endif
-                       {
-                               msg("\"%s\" is not a regular file", origname);
-                               return tmpstart("");
-                       }
-               }
-               else
-               {
-                       stat(".", &statb);
-               }
-               if (origfd >= 0)
-               {
-                       origtime = statb.st_mtime;
-#if OSK
-                       if (*o_readonly || !(statb.st_mode &
-                                 ((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
-                                 ((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
-#endif
-#if AMIGA || MSDOS || (TOS && defined(__GNUC__))
-                       if (*o_readonly || !(statb.st_mode & S_IWRITE))
-#endif
-#if TOS && !defined(__GNUC__)
-                       if (*o_readonly || (statb.st_mode & S_IJRON))
-#endif
-#if ANY_UNIX
-                       if (*o_readonly || !(statb.st_mode &
-                                 ((geteuid() == 0) ? 0222 :
-                                 ((statb.st_uid != geteuid() ? 0022 : 0200)))))
-#endif
-#if VMS
-                       if (*o_readonly)
-#endif
-                       {
-                               setflag(file, READONLY);
-                       }
-               }
-               else
-               {
-                       origtime = 0L;
-               }
-       }
-       else
-       {
-               setflag(file, NOFILE);
-               origfd = -1;
-               origtime = 0L;
-               stat(".", &statb);
-       }
-
-       /* make a name for the tmp file */
-       tmpnum++;
-#if MSDOS || TOS
-       /* MS-Dos doesn't allow multiple slashes, but supports drives
-        * with current directories.
-        * This relies on TMPNAME beginning with "%s\\"!!!!
-        */
-       strcpy(tmpname, o_directory);
-       if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
-               tmpname[i++]=SLASH;
-       sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
-#else
-       sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
-#endif
-
-       /* make sure nobody else is editing the same file */
-       if (access(tmpname, 0) == 0)
-       {
-               FAIL("Temp file \"%s\" already exists?", tmpname);
-       }
-
-       /* create the temp file */
-#if ANY_UNIX
-       close(creat(tmpname, 0600));            /* only we can read it */
-#else
-       close(creat(tmpname, FILEPERMS));       /* anybody body can read it, alas */
-#endif
-       tmpfd = open(tmpname, O_RDWR | O_BINARY);
-       if (tmpfd < 0)
-       {
-               FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory);
-               return 1;
-       }
-
-       /* allocate space for the header in the file */
-       write(tmpfd, hdr.c, (unsigned)BLKSIZE);
-       write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);
-
-#ifndef NO_RECYCLE
-       /* initialize the block allocator */
-       /* This must already be done here, before the first attempt
-        * to write to the new file! GB */
-       garbage();
-#endif
-
-       /* initialize lnum[] */
-       for (i = 1; i < MAXBLKS; i++)
-       {
-               lnum[i] = INFINITY;
-       }
-       lnum[0] = 0;
-
-       /* if there is no original file, then create a 1-line file */
-       if (origfd < 0)
-       {
-               hdr.n[0] = 0;   /* invalid inode# denotes new file */
-
-               this = blkget(1);       /* get the new text block */
-               strcpy(this->c, "\n");  /* put a line in it */
-
-               lnum[1] = 1L;   /* block 1 ends with line 1 */
-               nlines = 1L;    /* there is 1 line in the file */
-               nbytes = 1L;
-
-               if (*origname)
-               {
-                       msg("\"%s\" [NEW FILE]  1 line, 1 char", origname);
-               }
-               else
-               {
-                       msg("\"[NO FILE]\"  1 line, 1 char");
-               }
-       }
-       else /* there is an original file -- read it in */
-       {
-               nbytes = nlines = 0;
-
-               /* preallocate 1 "next" buffer */
-               i = 1;
-               next = blkget(i);
-               inbuf = 0;
-
-               /* loop, moving blocks from orig to tmp */
-               for (;;)
-               {
-                       /* "next" buffer becomes "this" buffer */
-                       this = next;
-
-                       /* read [more] text into this block */
-                       nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
-                       if (nread < 0)
-                       {
-                               close(origfd);
-                               close(tmpfd);
-                               tmpfd = -1;
-                               unlink(tmpname);
-                               FAIL("Error reading \"%s\"", origname);
-                       }
-
-                       /* convert NUL characters to something else */
-                       for (j = k = inbuf; k < inbuf + nread; k++)
-                       {
-                               if (!this->c[k])
-                               {
-                                       setflag(file, HADNUL);
-                                       this->c[j++] = 0x80;
-                               }
-#ifndef CRUNCH
-                               else if (*o_beautify && this->c[k] < ' ' && this->c[k] > 0)
-                               {
-                                       if (this->c[k] == '\t'
-                                        || this->c[k] == '\n'
-                                        || this->c[k] == '\f')
-                                       {
-                                               this->c[j++] = this->c[k];
-                                       }
-                                       else if (this->c[k] == '\b')
-                                       {
-                                               /* delete '\b', but complain */
-                                               setflag(file, HADBS);
-                                       }
-                                       /* else silently delete control char */
-                               }
-#endif
-                               else
-                               {
-                                       this->c[j++] = this->c[k];
-                               }
-                       }
-                       inbuf = j;
-
-                       /* if the buffer is empty, quit */
-                       if (inbuf == 0)
-                       {
-                               goto FoundEOF;
-                       }
-
-#if MSDOS || TOS
-/* BAH! MS text mode read fills inbuf, then compresses eliminating \r
-   but leaving garbage at end of buf. The same is true for TURBOC. GB. */
-
-                       memset(this->c + inbuf, '\0', BLKSIZE - inbuf);
-#endif
-
-                       /* search backward for last newline */
-                       for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
-                       {
-                       }
-                       if (k++ < 0)
-                       {
-                               if (inbuf >= BLKSIZE - 1)
-                               {
-                                       k = 80;
-                               }
-                               else
-                               {
-                                       k = inbuf;
-                               }
-                       }
-
-                       /* allocate next buffer */
-                       next = blkget(++i);
-
-                       /* move fragmentary last line to next buffer */
-                       inbuf -= k;
-                       for (j = 0; k < BLKSIZE; j++, k++)
-                       {
-                               next->c[j] = this->c[k];
-                               this->c[k] = 0;
-                       }
-
-                       /* if necessary, add a newline to this buf */
-                       for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
-                       {
-                       }
-                       if (this->c[k] != '\n')
-                       {
-                               setflag(file, ADDEDNL);
-                               this->c[k + 1] = '\n';
-                       }
-
-                       /* count the lines in this block */
-                       for (k = 0; k < BLKSIZE && this->c[k]; k++)
-                       {
-                               if (this->c[k] == '\n')
-                               {
-                                       nlines++;
-                               }
-                               nbytes++;
-                       }
-                       if(i >= MAXBLKS) {
-                               FAIL("Too many blocks: %d.", i);
-                       }
-                       lnum[i - 1] = nlines;
-               }
-FoundEOF:
-
-               /* if this is a zero-length file, add 1 line */
-               if (nlines == 0)
-               {
-                       this = blkget(1);       /* get the new text block */
-                       strcpy(this->c, "\n");  /* put a line in it */
-
-                       lnum[1] = 1;    /* block 1 ends with line 1 */
-                       nlines = 1;     /* there is 1 line in the file */
-                       nbytes = 1;
-               }
-
-#if MSDOS || TOS
-               /* each line has an extra CR that we didn't count yet */
-               nbytes += nlines;
-#endif
-
-               /* report the number of lines in the file */
-               msg("\"%s\" %s %ld line%s, %ld char%s",
-                       origname,
-                       (tstflag(file, READONLY) ? "[READONLY]" : ""),
-                       nlines,
-                       nlines == 1 ? "" : "s",
-                       nbytes,
-                       nbytes == 1 ? "" : "s");
-       }
-
-       /* initialize the cursor to start of line 1 */
-       cursor = MARK_FIRST;
-
-       /* close the original file */
-       close(origfd);
-
-       /* any other messages? */
-       if (tstflag(file, HADNUL))
-       {
-               msg("This file contained NULs.  They've been changed to \\x80 chars");
-       }
-       if (tstflag(file, ADDEDNL))
-       {
-               msg("Newline characters have been inserted to break up long lines");
-       }
-#ifndef CRUNCH
-       if (tstflag(file, HADBS))
-       {
-               msg("Backspace characters deleted due to ':set beautify'");
-       }
-#endif
-
-       storename(origname);
-
-#ifndef NO_MODELINES
-       if (nlines > 10)
-       {
-               do_modelines(1L, 5L);
-               do_modelines(nlines - 4L, nlines);
-       }
-       else
-       {
-               do_modelines(1L, nlines);
-       }
-#endif
-
-       /* force all blocks out onto the disk, to support file recovery */
-       blksync();
-
-       return 0;
-}
-
-
-
-/* This function copies the temp file back onto an original file.
- * Returns TRUE if successful, or FALSE if the file could NOT be saved.
- */
-int tmpsave(filename, bang)
-       char    *filename;      /* the name to save it to */
-       int     bang;           /* forced write? */
-{
-       int             fd;     /* fd of the file we're writing to */
-       REG int         len;    /* length of a text block */
-       REG BLK         *this;  /* a text block */
-       long            bytes;  /* byte counter */
-       REG int         i;
-
-       /* if no filename is given, assume the original file name */
-       if (!filename || !*filename)
-       {
-               filename = origname;
-       }
-
-       /* if still no file name, then fail */
-       if (!*filename)
-       {
-               msg("Don't know a name for this file -- NOT WRITTEN");
-               return FALSE;
-       }
-
-       /* can't rewrite a READONLY file */
-#if AMIGA
-       if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
-#else
-       if (!strcmp(filename, origname) && *o_readonly && !bang)
-#endif
-       {
-               msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
-               return FALSE;
-       }
-
-       /* open the file */
-       if (*filename == '>' && filename[1] == '>')
-       {
-               filename += 2;
-               while (*filename == ' ' || *filename == '\t')
-               {
-                       filename++;
-               }
-#ifdef O_APPEND
-               fd = open(filename, O_WRONLY|O_APPEND);
-#else
-               fd = open(filename, O_WRONLY);
-               lseek(fd, 0L, 2);
-#endif
-       }
-       else
-       {
-               /* either the file must not exist, or it must be the original
-                * file, or we must have a bang, or "writeany" must be set.
-                */
-               if (strcmp(filename, origname) && access(filename, 0) == 0 && !bang
-#ifndef CRUNCH
-                   && !*o_writeany
-#endif
-                                  )
-               {
-                       msg("File already exists - Use :w! to overwrite");
-                       return FALSE;
-               }
-#if VMS
-               /* Create a new VMS version of this file. */
-               { 
-               char *strrchr(), *ptr = strrchr(filename,';');
-               if (ptr) *ptr = '\0';  /* Snip off any ;number in the name */
-               }
-#endif
-               fd = creat(filename, FILEPERMS);
-       }
-       if (fd < 0)
-       {
-               msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
-               return FALSE;
-       }
-
-       /* write each text block to the file */
-       bytes = 0L;
-       for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
-       {
-               for (len = 0; len < BLKSIZE && this->c[len]; len++)
-               {
-               }
-               if (twrite(fd, this->c, len) < len)
-               {
-                       msg("Trouble writing to \"%s\"", filename);
-                       if (!strcmp(filename, origname))
-                       {
-                               setflag(file, MODIFIED);
-                       }
-                       close(fd);
-                       return FALSE;
-               }
-               bytes += len;
-       }
-
-       /* reset the "modified" flag, but not the "undoable" flag */
-       clrflag(file, MODIFIED);
-       significant = FALSE;
-
-       /* report lines & characters */
-#if MSDOS || TOS
-       bytes += nlines; /* for the inserted carriage returns */
-#endif
-       msg("Wrote \"%s\"  %ld lines, %ld characters", filename, nlines, bytes);
-
-       /* close the file */
-       close(fd);
-
-       return TRUE;
-}
-
-
-/* This function deletes the temporary file.  If the file has been modified
- * and "bang" is FALSE, then it returns FALSE without doing anything; else
- * it returns TRUE.
- *
- * If the "autowrite" option is set, then instead of returning FALSE when
- * the file has been modified and "bang" is false, it will call tmpend().
- */
-int tmpabort(bang)
-       int     bang;
-{
-       /* if there is no file, return successfully */
-       if (tmpfd < 0)
-       {
-               return TRUE;
-       }
-
-       /* see if we must return FALSE -- can't quit */
-       if (!bang && tstflag(file, MODIFIED))
-       {
-               /* if "autowrite" is set, then act like tmpend() */
-               if (*o_autowrite)
-                       return tmpend(bang);
-               else
-                       return FALSE;
-       }
-
-       /* delete the tmp file */
-       cutswitch();
-       strcpy(prevorig, origname);
-       prevline = markline(cursor);
-       *origname = '\0';
-       origtime = 0L;
-       blkinit();
-       nlines = 0;
-       initflags();
-       return TRUE;
-}
-
-/* This function saves the file if it has been modified, and then deletes
- * the temporary file. Returns TRUE if successful, or FALSE if the file
- * needs to be saved but can't be.  When it returns FALSE, it will not have
- * deleted the tmp file, either.
- */
-int tmpend(bang)
-       int     bang;
-{
-       /* save the file if it has been modified */
-       if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang)
-       {
-               return FALSE;
-       }
-
-       /* delete the tmp file */
-       tmpabort(TRUE);
-
-       return TRUE;
-}
-
-
-/* If the tmp file has been changed, then this function will force those
- * changes to be written to the disk, so that the tmp file will survive a
- * system crash or power failure.
- */
-#if AMIGA || MSDOS || TOS
-sync()
-{
-       /* MS-DOS and TOS don't flush their buffers until the file is closed,
-        * so here we close the tmp file and then immediately reopen it.
-        */
-       close(tmpfd);
-       tmpfd = open(tmpname, O_RDWR | O_BINARY);
-       return 0;
-}
-#endif
-
-
-/* This function stores the file's name in the second block of the temp file.
- * SLEAZE ALERT!  SLEAZE ALERT!  The "tmpblk" buffer is probably being used
- * to store the arguments to a command, so we can't use it here.  Instead,
- * we'll borrow the buffer that is used for "shift-U".
- */
-storename(name)
-       char    *name;  /* the name of the file - normally origname */
-{
-#ifndef CRUNCH
-       int     len;
-       char    *ptr;
-#endif
-
-       /* we're going to clobber the U_text buffer, so reset U_line */
-       U_line = 0L;
-
-       if (!name)
-       {
-               strncpy(U_text, "", BLKSIZE);
-               U_text[1] = 127;
-       }
-#ifndef CRUNCH
-       else if (*name != SLASH)
-       {
-               /* get the directory name */
-               ptr = getcwd(U_text, BLKSIZE);
-               if (ptr != U_text)
-               {
-                       strcpy(U_text, ptr);
-               }
-
-               /* append a slash to the directory name */
-               len = strlen(U_text);
-               U_text[len++] = SLASH;
-
-               /* append the filename, padded with heaps o' NULs */
-               strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len);
-       }
-#endif
-       else
-       {
-               /* copy the filename into U_text */
-               strncpy(U_text, *name ? name : "foo", BLKSIZE);
-       }
-
-       if (tmpfd >= 0)
-       {
-               /* write the name out to second block of the temp file */
-               lseek(tmpfd, (long)BLKSIZE, 0);
-               write(tmpfd, U_text, (unsigned)BLKSIZE);
-       }
-       return 0;
-}
-
-
-
-/* This function handles deadly signals.  It restores sanity to the terminal
- * preserves the current temp file, and deletes any old temp files.
- */
-int deathtrap(sig)
-       int     sig;    /* the deadly signal that we caught */
-{
-       char    *why;
-
-       /* restore the terminal's sanity */
-       endwin();
-
-#ifdef CRUNCH
-       why = "-Elvis died";
-#else
-       /* give a more specific description of how Elvis died */
-       switch (sig)
-       {
-# ifdef SIGHUP
-         case SIGHUP:  why = "-the modem lost its carrier";            break;
-# endif
-# ifndef DEBUG
-#  ifdef SIGILL
-         case SIGILL:  why = "-Elvis hit an illegal instruction";      break;
-#  endif
-#  ifdef SIGBUS
-         case SIGBUS:  why = "-Elvis had a bus error";                 break;
-#  endif
-#  if defined(SIGSEGV) && !defined(TOS)
-         case SIGSEGV: why = "-Elvis had a segmentation violation";    break;
-#  endif
-#  ifdef SIGSYS
-         case SIGSYS:  why = "-Elvis munged a system call";            break;
-#  endif
-# endif /* !DEBUG */
-# ifdef SIGPIPE
-         case SIGPIPE: why = "-the pipe reader died";                  break;
-# endif
-# ifdef SIGTERM
-         case SIGTERM: why = "-Elvis was terminated";                  break;
-# endif
-# if !MINIX
-#  ifdef SIGUSR1
-         case SIGUSR1: why = "-Elvis was killed via SIGUSR1";          break;
-#  endif
-#  ifdef SIGUSR2
-         case SIGUSR2: why = "-Elvis was killed via SIGUSR2";          break;
-#  endif
-# endif
-         default:      why = "-Elvis died";                            break;
-       }
-#endif
-
-       /* if we had a temp file going, then preserve it */
-       if (tmpnum > 0 && tmpfd >= 0)
-       {
-               close(tmpfd);
-               sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname);
-               system(tmpblk.c);
-       }
-
-       /* delete any old temp files */
-       cutend();
-
-       /* exit with the proper exit status */
-       exit(sig);
-}
diff --git a/commands/elvis/unix.c b/commands/elvis/unix.c
deleted file mode 100644 (file)
index f366d26..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/* unix.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the unix-specific versions the ttyread() functions.
- * There are actually three versions of ttyread() defined here, because
- * BSD, SysV, and V7 all need quite different implementations.
- */
-
-#include "config.h"
-#if ANY_UNIX
-# include "vi.h"
-
-# if BSD
-/* For BSD, we use select() to wait for characters to become available,
- * and then do a read() to actually get the characters.  We also try to
- * handle SIGWINCH -- if the signal arrives during the select() call, then
- * we adjust the o_columns and o_lines variables, and fake a control-L.
- */
-#  include <sys/types.h>
-#  include <sys/time.h>
-int ttyread(buf, len, time)
-       char    *buf;   /* where to store the gotten characters */
-       int     len;    /* maximum number of characters to read */
-       int     time;   /* maximum time to allow for reading */
-{
-       fd_set  rd;     /* the file descriptors that we want to read from */
-       static  tty;    /* 'y' if reading from tty, or 'n' if not a tty */
-       int     i;
-       struct timeval t;
-       struct timeval *tp;
-
-
-       /* do we know whether this is a tty or not? */
-       if (!tty)
-       {
-               tty = (isatty(0) ? 'y' : 'n');
-       }
-
-       /* compute the timeout value */
-       if (time)
-       {
-               t.tv_sec = time / 10;
-               t.tv_usec = (time % 10) * 100000L;
-               tp = &t;
-       }
-       else
-       {
-               tp = (struct timeval *)0;
-       }
-
-       /* loop until we get characters or a definite EOF */
-       for (;;)
-       {
-               if (tty == 'y')
-               {
-                       /* wait until timeout or characters are available */
-                       FD_ZERO(&rd);
-                       FD_SET(0, &rd);
-                       i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp);
-               }
-               else
-               {
-                       /* if reading from a file or pipe, never timeout!
-                        * (This also affects the way that EOF is detected)
-                        */
-                       i = 1;
-               }
-       
-               /* react accordingly... */
-               switch (i)
-               {
-                 case -1:      /* assume we got an EINTR because of SIGWINCH */
-                       if (*o_lines != LINES || *o_columns != COLS)
-                       {
-                               *o_lines = LINES;
-                               *o_columns = COLS;
-#ifndef CRUNCH
-                               if (!wset)
-                               {
-                                       *o_window = LINES - 1;
-                               }
-#endif
-                               if (mode != MODE_EX)
-                               {
-                                       /* pretend the user hit ^L */
-                                       *buf = ctrl('L');
-                                       return 1;
-                               }
-                       }
-                       break;
-       
-                 case 0:       /* timeout */
-                       return 0;
-       
-                 default:      /* characters available */
-                       return read(0, buf, len);
-               }
-       }
-}
-# else
-
-# if M_SYSV
-/* For System-V or Coherent, we use VMIN/VTIME to implement the timeout.
- * For no timeout, VMIN should be 1 and VTIME should be 0; for timeout,
- * VMIN should be 0 and VTIME should be the timeout value.
- */
-#  include <termio.h>
-int ttyread(buf, len, time)
-       char    *buf;   /* where to store the gotten characters */
-       int     len;    /* maximum number of characters to read */
-       int     time;   /* maximum time to allow for reading */
-{
-       struct termio tio;
-       int     bytes;  /* number of bytes actually read */
-
-       /* arrange for timeout */
-       ioctl(0, TCGETA, &tio);
-       if (time)
-       {
-               tio.c_cc[VMIN] = 0;
-               tio.c_cc[VTIME] = time;
-       }
-       else
-       {
-               tio.c_cc[VMIN] = 1;
-               tio.c_cc[VTIME] = 0;
-       }
-       ioctl(0, TCSETA, &tio);
-
-       /* Perform the read.  Loop if EINTR error happens */
-       while ((bytes = read(0, buf, len)) < 0)
-       {
-               /* probably EINTR error because a SIGWINCH was received */
-               if (*o_lines != LINES || *o_columns != COLS)
-               {
-                       *o_lines = LINES;
-                       *o_columns = COLS;
-#ifndef CRUNCH
-                       if (!wset)
-                       {
-                               *o_window = LINES - 1;
-                       }
-#endif
-                       if (mode != MODE_EX)
-                       {
-                               /* pretend the user hit ^L */
-                               *buf = ctrl('L');
-                               return 1;
-                       }
-               }
-       }
-
-       /* return the number of bytes read */
-       return bytes;
-
-       /* NOTE: The terminal may be left in a timeout-mode after this function
-        * returns.  This shouldn't be a problem since Elvis *NEVER* tries to
-        * read from the keyboard except through this function.
-        */
-}
-
-# else /* any other version of UNIX, assume it is V7 compatible */
-
-/* For V7 UNIX (including Minix) we set an alarm() before doing a blocking
- * read(), and assume that the SIGALRM signal will cause the read() function
- * to give up.
- */
-
-#include <setjmp.h>
-
-static jmp_buf env;
-
-/*ARGSUSED*/
-int dummy(signo)
-       int     signo;
-{
-       longjmp(env, 1);
-}
-int ttyread(buf, len, time)
-       char    *buf;   /* where to store the gotten characters */
-       int     len;    /* maximum number of characters to read */
-       int     time;   /* maximum time to allow for reading */
-{
-       /* arrange for timeout */
-       signal(SIGALRM, (void (*)()) dummy);
-       alarm(time);
-
-       /* perform the blocking read */
-       if (setjmp(env) == 0)
-       {
-               len = read(0, buf, len);
-       }
-       else /* I guess we timed out */
-       {
-               len = 0;
-       }
-
-       /* cancel the alarm */
-       signal(SIGALRM, (void (*)())dummy); /* work around a bug in Minix */
-       alarm(0);
-
-       /* return the number of bytes read */
-       if (len < 0)
-               len = 0;
-       return len;
-}
-
-# endif /* !(M_SYSV || COHERENT) */
-# endif /* !BSD */
-
-#endif /* ANY_UNIX */
diff --git a/commands/elvis/vars.c b/commands/elvis/vars.c
deleted file mode 100644 (file)
index 19b5d19..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* vars.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains variables which weren't happy anyplace else */
-
-#include "config.h"
-#include "vi.h"
-
-/*------------------------------------------------------------------------*/
-
-/* used to remember whether the file has been modified */
-struct _viflags        viflags;
-
-/* used to access the tmp file */
-long           lnum[MAXBLKS];
-long           nlines;
-int            tmpfd = -1;
-int            tmpnum;
-#ifndef CRUNCH
-int            wset = FALSE;
-#endif
-
-/* used to keep track of the current file & alternate file */
-long           origtime;
-char           origname[256];
-char           prevorig[256];
-long           prevline = 1;
-
-/* used to track various places in the text */
-MARK           mark[NMARKS];   /* marks 'a through 'z, plus mark '' */
-MARK           cursor;         /* the cursor position within the file */
-
-/* which mode of the editor we're in */
-int            mode;           /* vi mode? ex mode? quitting? */
-
-/* used to manage the args list */
-char           args[BLKSIZE];  /* list of filenames to edit */
-int            argno;          /* index of current file in args list */
-int            nargs;          /* number of filenames in args[] */
-
-/* dummy var, never explicitly referenced */
-int            bavar;          /* used only in BeforeAfter macros */
-
-/* used to detect changes that invalidate cached text/blocks */
-long           changes;        /* incremented when file is changed */
-int            significant;    /* boolean: was a *REAL* change made? */
-
-/* used to support the pfetch() macro */
-int            plen;           /* length of the line */
-long           pline;          /* line number that len refers to */
-long           pchgs;          /* "changes" level that len refers to */
-char           *ptext;         /* text of previous line, if valid */
-
-/* misc temporary storage - mostly for strings */
-BLK            tmpblk;         /* a block used to accumulate changes */
-
-/* screen oriented stuff */
-long           topline;        /* file line number of top line */
-int            leftcol;        /* column number of left col */
-int            physcol;        /* physical column number that cursor is on */
-int            physrow;        /* physical row number that cursor is on */
-
-/* used to help minimize that "[Hit a key to continue]" message */
-int            exwrote;        /* Boolean: was the last ex command wordy? */
-
-/* This variable affects the behaviour of certain functions -- most importantly
- * the input function.
- */
-int            doingdot;       /* boolean: are we doing the "." command? */
-
-/* This variable affects the behaviour of the ":s" command, and it is also
- * used to detect & prohibit nesting of ":g" commands
- */
-int            doingglobal;    /* boolean: are doing a ":g" command? */
-
-/* This variable is zeroed before a command executes, and later ORed with the
- * command's flags after the command has been executed.  It is used to force
- * certain flags to be TRUE for *some* invocations of a particular command.
- * For example, "/regexp/+offset" forces the LNMD flag, and sometimes a "p"
- * or "P" command will force FRNT.
- */
-int            force_flags;
-
-/* These are used for reporting multi-line changes to the user */
-long           rptlines;       /* number of lines affected by a command */
-char           *rptlabel;      /* description of how lines were affected */
-
-/* These store info that pertains to the shift-U command */
-long   U_line;                 /* line# of the undoable line, or 0l for none */
-char   U_text[BLKSIZE];        /* contents of the undoable line */
-
-
-#ifndef NO_VISIBLE
-/* These are used to implement the 'v' and 'V' commands */
-MARK   V_from;                 /* starting point for v or V */
-int    V_linemd;               /* boolean: doing line-mode version? (V, not v) */
-#endif
-
-/* Bigger stack req'ed for TOS and TURBOC */
-
-#if TOS
-long   _stksize = 16384;
-#endif
-
-#if TURBOC
-#include <dos.h>
-extern unsigned _stklen = 16384U;
-#endif
diff --git a/commands/elvis/vcmd.c b/commands/elvis/vcmd.c
deleted file mode 100644 (file)
index 494f7e1..0000000
+++ /dev/null
@@ -1,975 +0,0 @@
-/* vcmd.c */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-/* This file contains the functions that handle VI commands */
-
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-#if MSDOS
-# include <process.h>
-# include <string.h>
-#endif
-#if TOS
-# include <osbind.h>
-# include <string.h>
-#endif
-#if OSK
-# include <stdio.h>
-#endif
-
-
-/* This function puts the editor in EX mode */
-MARK v_quit()
-{
-       move(LINES - 1, 0);
-       mode = MODE_EX;
-       return cursor;
-}
-
-/* This function causes the screen to be redrawn */
-MARK v_redraw()
-{
-       redraw(MARK_UNSET, FALSE);
-       return cursor;
-}
-
-/* This function executes a string of EX commands, and waits for a user keystroke
- * before returning to the VI screen.  If that keystroke is another ':', then
- * another EX command is read and executed.
- */
-/*ARGSUSED*/
-MARK v_1ex(m, text)
-       MARK    m;      /* the current line */
-       char    *text;  /* the first command to execute */
-{
-       /* run the command.  be careful about modes & output */
-       exwrote = (mode == MODE_COLON);
-       doexcmd(text);
-       exrefresh();
-
-       /* if mode is no longer MODE_VI, then we should quit right away! */
-       if (mode != MODE_VI && mode != MODE_COLON)
-               return cursor;
-
-       /* The command did some output.  Wait for a keystoke. */
-       if (exwrote)
-       {
-               mode = MODE_VI; 
-               msg("[Hit <RETURN> to continue]");
-               if (getkey(0) == ':')
-               {       mode = MODE_COLON;
-                       addch('\n');
-               }
-               else
-                       redraw(MARK_UNSET, FALSE);
-       }
-
-       return cursor;
-}
-
-/* This function undoes the last change */
-/*ARGSUSED*/
-MARK v_undo(m)
-       MARK    m;      /* (ignored) */
-{
-       if (undo())
-       {
-               redraw(MARK_UNSET, FALSE);
-       }
-       return cursor;
-}
-
-/* This function deletes the character(s) that the cursor is on */
-MARK v_xchar(m, cnt, cmd)
-       MARK    m;      /* where to start deletions */
-       long    cnt;    /* number of chars to delete */
-       int     cmd;    /* either 'x' or 'X' */
-{
-       DEFAULT(1);
-
-       /* for 'X', adjust so chars are deleted *BEFORE* cursor */
-       if (cmd == 'X')
-       {
-               if (markidx(m) < cnt)
-                       return MARK_UNSET;
-               m -= cnt;
-       }
-
-       /* make sure we don't try to delete more thars than there are */
-       pfetch(markline(m));
-       if (markidx(m + cnt) > plen)
-       {
-               cnt = plen - markidx(m);
-       }
-       if (cnt == 0L)
-       {
-               return MARK_UNSET;
-       }
-
-       /* do it */
-       ChangeText
-       {
-               cut(m, m + cnt);
-               delete(m, m + cnt);
-       }
-       return m;
-}
-
-/* This function defines a mark */
-/*ARGSUSED*/
-MARK v_mark(m, count, key)
-       MARK    m;      /* where the mark will be */
-       long    count;  /* (ignored) */
-       int     key;    /* the ASCII label of the mark */
-{
-       if (key < 'a' || key > 'z')
-       {
-               msg("Marks must be from a to z");
-       }
-       else
-       {
-               mark[key - 'a'] = m;
-       }
-       return m;
-}
-
-/* This function toggles upper & lower case letters */
-MARK v_ulcase(m, cnt)
-       MARK    m;      /* where to make the change */
-       long    cnt;    /* number of chars to flip */
-{
-       REG char        *pos;
-       REG int         j;
-
-       DEFAULT(1);
-
-       /* fetch the current version of the line */
-       pfetch(markline(m));
-
-       /* for each position in the line */
-       for (j = 0, pos = &ptext[markidx(m)]; j < cnt && *pos; j++, pos++)
-       {
-               if (isupper(*pos))
-               {
-                       tmpblk.c[j] = tolower(*pos);
-               }
-               else
-               {
-                       tmpblk.c[j] = toupper(*pos);
-               }
-       }
-
-       /* if the new text is different from the old, then change it */
-       if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
-       {
-               ChangeText
-               {
-                       tmpblk.c[j] = '\0';
-                       change(m, m + j, tmpblk.c);
-               }
-       }
-
-       return m + j;
-}
-
-
-MARK v_replace(m, cnt, key)
-       MARK    m;      /* first char to be replaced */
-       long    cnt;    /* number of chars to replace */
-       int     key;    /* what to replace them with */
-{
-       REG char        *text;
-       REG int         i;
-
-       DEFAULT(1);
-
-       /* map ^M to '\n' */
-       if (key == '\r')
-       {
-               key = '\n';
-       }
-
-       /* make sure the resulting line isn't too long */
-       if (cnt > BLKSIZE - 2 - markidx(m))
-       {
-               cnt = BLKSIZE - 2 - markidx(m);
-       }
-
-       /* build a string of the desired character with the desired length */
-       for (text = tmpblk.c, i = cnt; i > 0; i--)
-       {
-               *text++ = key;
-       }
-       *text = '\0';
-
-       /* make sure cnt doesn't extend past EOL */
-       pfetch(markline(m));
-       key = markidx(m);
-       if (key + cnt > plen)
-       {
-               cnt = plen - key;
-       }
-
-       /* do the replacement */
-       ChangeText
-       {
-               change(m, m + cnt, tmpblk.c);
-       }
-
-       if (*tmpblk.c == '\n')
-       {
-               return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
-       }
-       else
-       {
-               return m + cnt - 1;
-       }
-}
-
-MARK v_overtype(m)
-       MARK            m;      /* where to start overtyping */
-{
-       MARK            end;    /* end of a substitution */
-       static long     width;  /* width of a single-line replace */
-
-       /* the "doingdot" version of replace is really a substitution */
-       if (doingdot)
-       {
-               /* was the last one really repeatable? */
-               if (width < 0)
-               {
-                       msg("Can't repeat a multi-line overtype command");
-                       return MARK_UNSET;
-               }
-
-               /* replacing nothing by nothing?  Don't bother */
-               if (width == 0)
-               {
-                       return m;
-               }
-
-               /* replace some chars by repeated text */
-               return v_subst(m, width);
-       }
-
-       /* Normally, we input starting here, in replace mode */
-       ChangeText
-       {
-               end = input(m, m, WHEN_VIREP, FALSE);
-       }
-
-       /* if we ended on the same line we started on, then this
-        * overtype is repeatable via the dot key.
-        */
-       if (markline(end) == markline(m) && end >= m - 1L)
-       {
-               width = end - m + 1L;
-       }
-       else /* it isn't repeatable */
-       {
-               width = -1L;
-       }
-
-       return end;
-}
-
-
-/* This function selects which cut buffer to use */
-/*ARGSUSED*/
-MARK v_selcut(m, cnt, key)
-       MARK    m;
-       long    cnt;
-       int     key;
-{
-       cutname(key);
-       return m;
-}
-
-/* This function pastes text from a cut buffer */
-/*ARGSUSED*/
-MARK v_paste(m, cnt, cmd)
-       MARK    m;      /* where to paste the text */
-       long    cnt;    /* (ignored) */
-       int     cmd;    /* either 'p' or 'P' */
-{
-       MARK    dest;
-
-       ChangeText
-       {
-               /* paste the text, and find out where it ends */
-               dest = paste(m, cmd == 'p', TRUE);
-
-               /* was that a line-mode paste? */
-               if (dest && markline(dest) != markline(m))
-               {
-                       /* line-mode pastes leave the cursor at the front
-                        * of the first pasted line.
-                        */
-                       dest = m;
-                       if (cmd == 'p')
-                       {
-                               dest += BLKSIZE;
-                       }
-                       force_flags |= FRNT;
-               }
-       }
-       return dest;
-}
-
-/* This function yanks text into a cut buffer */
-MARK v_yank(m, n)
-       MARK    m, n;   /* range of text to yank */
-{
-       cut(m, n);
-       return m;
-}
-
-/* This function deletes a range of text */
-MARK v_delete(m, n)
-       MARK    m, n;   /* range of text to delete */
-{
-       /* illegal to try and delete nothing */
-       if (n <= m)
-       {
-               return MARK_UNSET;
-       }
-
-       /* Do it */
-       ChangeText
-       {
-               cut(m, n);
-               delete(m, n);
-       }
-       return m;
-}
-
-
-/* This starts input mode without deleting anything */
-MARK v_insert(m, cnt, key)
-       MARK    m;      /* where to start (sort of) */
-       long    cnt;    /* repeat how many times? */
-       int     key;    /* what command is this for? {a,A,i,I,o,O} */
-{
-       int     wasdot;
-       long    reps;
-       int     above;  /* boolean: new line going above old line? */
-
-       DEFAULT(1);
-
-       ChangeText
-       {
-               /* tweak the insertion point, based on command key */
-               above = FALSE;
-               switch (key)
-               {
-                 case 'i':
-                       break;
-
-                 case 'a':
-                       pfetch(markline(m));
-                       if (plen > 0)
-                       {
-                               m++;
-                       }
-                       break;
-
-                 case 'I':
-                       m = m_front(m, 1L);
-                       break;
-
-                 case 'A':
-                       pfetch(markline(m));
-                       m = (m & ~(BLKSIZE - 1)) + plen;
-                       break;
-
-                 case 'O':
-                       m &= ~(BLKSIZE - 1);
-                       add(m, "\n");
-                       above = TRUE;
-                       break;
-
-                 case 'o':
-                       m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
-                       add(m, "\n");
-                       break;
-               }
-
-               /* insert the same text once or more */
-               for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
-               {
-                       m = input(m, m, WHEN_VIINP, above) + 1;
-               }
-               if (markidx(m) > 0)
-               {
-                       m--;
-               }
-
-               doingdot = wasdot;
-       }
-
-#ifndef CRUNCH
-# ifndef NO_EXTENSIONS
-       if (key == 'i' && *o_inputmode && mode == MODE_VI)
-       {
-               msg("Now in command mode!  To return to input mode, hit <i>");
-       }
-# endif
-#endif
-
-       return m;
-}
-
-/* This starts input mode with some text deleted */
-MARK v_change(m, n)
-       MARK    m, n;   /* the range of text to change */
-{
-       int     lnmode; /* is this a line-mode change? */
-
-       /* swap them if they're in reverse order */
-       if (m > n)
-       {
-               MARK    tmp;
-               tmp = m;
-               m = n;
-               n = tmp;
-       }
-
-       /* for line mode, retain the last newline char */
-       lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
-       if (lnmode)
-       {
-               n -= BLKSIZE;
-               pfetch(markline(n));
-               n = (n & ~(BLKSIZE - 1)) + plen;
-       }
-
-       ChangeText
-       {
-               cut(m, n);
-               m = input(m, n, WHEN_VIINP, FALSE);
-       }
-
-       return m;
-}
-
-/* This function replaces a given number of characters with input */
-MARK v_subst(m, cnt)
-       MARK    m;      /* where substitutions start */
-       long    cnt;    /* number of chars to replace */
-{
-       DEFAULT(1);
-
-       /* make sure we don't try replacing past EOL */
-       pfetch(markline(m));
-       if (markidx(m) + cnt > plen)
-       {
-               cnt = plen - markidx(m);
-       }
-
-       /* Go for it! */
-       ChangeText
-       {
-               cut(m, m + cnt);
-               m = input(m, m + cnt, WHEN_VIINP, FALSE);
-       }
-       return m;
-}
-
-/* This calls the ex "join" command to join some lines together */
-MARK v_join(m, cnt)
-       MARK    m;      /* the first line to be joined */
-       long    cnt;    /* number of other lines to join */
-{
-       MARK    joint;  /* where the lines were joined */
-
-       DEFAULT(1);
-
-       /* figure out where the joint will be */
-       pfetch(markline(m));
-       joint = (m & ~(BLKSIZE - 1)) + plen;
-
-       /* join the lines */
-       cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
-
-       /* the cursor should be left at the joint */
-       return joint;
-}
-
-
-/* This calls the ex "<" command to shift some lines left */
-MARK v_lshift(m, n)
-       MARK    m, n;   /* range of lines to shift */
-{
-       /* adjust for inclusive endmarks in ex */
-       n -= BLKSIZE;
-
-       cmd_shift(m, n, CMD_SHIFTL, FALSE, (char *)0);
-
-       return m;
-}
-
-/* This calls the ex ">" command to shift some lines right */
-MARK v_rshift(m, n)
-       MARK    m, n;   /* range of lines to shift */
-{
-       /* adjust for inclusive endmarks in ex */
-       n -= BLKSIZE;
-
-       cmd_shift(m, n, CMD_SHIFTR, FALSE, (char *)0);
-
-       return m;
-}
-
-/* This filters some lines through a preset program, to reformat them */
-MARK v_reformat(m, n)
-       MARK    m, n;   /* range of lines to shift */
-{
-       /* adjust for inclusive endmarks in ex */
-       n -= BLKSIZE;
-
-       /* run the filter command */
-       filter(m, n, o_equalprg, TRUE);
-
-       redraw(MARK_UNSET, FALSE);
-       return m;
-}
-
-
-/* This runs some lines through a filter program */
-MARK v_filter(m, n)
-       MARK    m, n;   /* range of lines to shift */
-{
-       char    cmdln[150];     /* a shell command line */
-
-       /* adjust for inclusive endmarks in ex */
-       n -= BLKSIZE;
-
-       if (vgets('!', cmdln, sizeof(cmdln)) > 0)
-       {
-               filter(m, n, cmdln, TRUE);
-       }
-
-       redraw(MARK_UNSET, FALSE);
-       return m;
-}
-
-
-/* This function runs the ex "file" command to show the file's status */
-MARK v_status()
-{
-       cmd_file(cursor, cursor, CMD_FILE, 0, "");
-       return cursor;
-}
-
-
-/* This function runs the ":&" command to repeat the previous :s// */
-MARK v_again(m, n)
-       MARK    m, n;
-{
-       cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
-       return cursor;
-}
-
-
-
-/* This function switches to the previous file, if possible */
-MARK v_switch()
-{
-       if (!*prevorig)
-               msg("No previous file");
-       else
-       {       strcpy(tmpblk.c, prevorig);
-               cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
-       }
-       return cursor;
-}
-
-/* This function does a tag search on a keyword */
-/*ARGSUSED*/
-MARK v_tag(keyword, m, cnt)
-       char    *keyword;
-       MARK    m;
-       long    cnt;
-{
-       /* move the cursor to the start of the tag name, where m is */
-       cursor = m;
-
-       /* perform the tag search */
-       cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
-
-       return cursor;
-}
-
-#ifndef NO_EXTENSIONS
-/* This function looks up a keyword by calling the helpprog program */
-/*ARGSUSED*/
-MARK v_keyword(keyword, m, cnt)
-       char    *keyword;
-       MARK    m;
-       long    cnt;
-{
-       int     waswarn;
-       char    cmdline[130];
-
-       move(LINES - 1, 0);
-       addstr("---------------------------------------------------------\n");
-       clrtoeol();
-       refresh();
-       sprintf(cmdline, "%s %s", o_keywordprg, keyword);
-       waswarn = *o_warn;
-       *o_warn = FALSE;
-       suspend_curses();
-       if (system(cmdline))
-       {
-               addstr("<<< failed >>>\n");
-       }
-       resume_curses(FALSE);
-       mode = MODE_VI;
-       redraw(MARK_UNSET, FALSE);
-       *o_warn = waswarn;
-
-       return m;
-}
-
-
-
-MARK v_increment(keyword, m, cnt)
-       char    *keyword;
-       MARK    m;
-       long    cnt;
-{
-       static  sign;
-       char    newval[12];
-       long    atol();
-
-       DEFAULT(1);
-
-       /* get one more keystroke, unless doingdot */
-       if (!doingdot)
-       {
-               sign = getkey(0);
-       }
-
-       /* adjust the number, based on that second keystroke */
-       switch (sign)
-       {
-         case '+':
-         case '#':
-               cnt = atol(keyword) + cnt;
-               break;
-
-         case '-':
-               cnt = atol(keyword) - cnt;
-               break;
-
-         case '=':
-               break;
-
-         default:
-               return MARK_UNSET;
-       }
-       sprintf(newval, "%ld", cnt);
-
-       ChangeText
-       {
-               change(m, m + strlen(keyword), newval);
-       }
-
-       return m;
-}
-#endif
-
-
-/* This function acts like the EX command "xit" */
-/*ARGSUSED*/
-MARK v_xit(m, cnt, key)
-       MARK    m;      /* ignored */
-       long    cnt;    /* ignored */
-       int     key;    /* must be a second 'Z' */
-{
-       /* if second char wasn't 'Z', fail */
-       if (key != 'Z')
-       {
-               return MARK_UNSET;
-       }
-
-       /* move the cursor to the bottom of the screen */
-       move(LINES - 1, 0);
-       clrtoeol();
-
-       /* do the xit command */
-       cmd_xit(m, m, CMD_XIT, FALSE, "");
-
-       /* return the cursor */
-       return m;
-}
-
-
-/* This function undoes changes to a single line, if possible */
-MARK v_undoline(m)
-       MARK    m;      /* where we hope to undo the change */
-{
-       /* make sure we have the right line in the buffer */
-       if (markline(m) != U_line)
-       {
-               return MARK_UNSET;
-       }
-
-       /* fix it */
-       ChangeText
-       {
-               strcat(U_text, "\n");
-               change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
-       }
-
-       /* nothing in the buffer anymore */
-       U_line = -1L;
-
-       /* return, with the cursor at the front of the line */
-       return m & ~(BLKSIZE - 1);
-}
-
-
-#ifndef NO_ERRLIST
-MARK v_errlist(m)
-       MARK    m;
-{
-       cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
-       return cursor;
-}
-#endif
-
-
-#ifndef NO_AT
-/*ARGSUSED*/
-MARK v_at(m, cnt, key)
-       MARK    m;
-       long    cnt;
-       int     key;
-{
-       int     size;
-
-       size = cb2str(key, tmpblk.c, BLKSIZE);
-       if (size <= 0 || size == BLKSIZE)
-       {
-               return MARK_UNSET;
-       }
-
-       execmap(0, tmpblk.c, FALSE);
-       return cursor;
-}
-#endif
-
-
-#ifdef SIGTSTP
-MARK v_suspend()
-{
-       cmd_suspend(MARK_UNSET, MARK_UNSET, CMD_SUSPEND, FALSE, "");
-       return MARK_UNSET;
-}
-#endif
-
-
-#ifndef NO_VISIBLE
-/*ARGSUSED*/
-MARK v_start(m, cnt, cmd)
-       MARK    m;      /* starting point for a v or V command */
-       long    cnt;    /* ignored */
-       int     cmd;    /* either 'v' or 'V' */
-{
-       if (V_from)
-       {
-               V_from = MARK_UNSET;
-       }
-       else
-       {
-               V_from = m;
-               V_linemd = isupper(cmd);
-       }
-       return m;
-}
-#endif
-
-#ifndef NO_POPUP
-# define MENU_HEIGHT 11
-# define MENU_WIDTH  23
-MARK v_popup(m, n)
-       MARK            m, n;   /* the range of text to change */
-{
-       int             i;
-       int             y, x;   /* position where the window will pop up at */
-       int             key;    /* keystroke from the user */
-       int             sel;    /* index of the selected operation */
-       static int      dfltsel;/* default value of sel */
-       static char     *labels[11] =
-       {
-               "ESC cancel!         ",
-               " d  delete (cut)    ",
-               " y  yank (copy)     ",
-               " p  paste after     ",
-               " P  paste before    ",
-               " >  more indented   ",
-               " <  less indented   ",
-               " =  reformat        ",
-               " !  external filter ",
-               " ZZ save & exit     ",
-               " u  undo previous   "
-       };
-
-       /* try to position the menu near the cursor */
-       x = physcol - (MENU_WIDTH / 2);
-       if (x < 0)
-               x = 0;
-       else if (x + MENU_WIDTH + 2 > COLS)
-               x = COLS - MENU_WIDTH - 2;
-       if (markline(cursor) < topline || markline(cursor) > botline)
-               y = 0;
-       else if (markline(cursor) + 1L + MENU_HEIGHT > botline)
-               y = (int)(markline(cursor) - topline) - MENU_HEIGHT;
-       else
-               y = (int)(markline(cursor) - topline) + 1L;
-
-       /* draw the menu */
-       for (sel = 0; sel < MENU_HEIGHT; sel++)
-       {
-               move(y + sel, x);
-               do_POPUP();
-               if (sel == dfltsel)
-                       qaddstr("-->");
-               else
-                       qaddstr("   ");
-               qaddstr(labels[sel]);
-               do_SE();
-       }
-
-       /* get a selection */
-       move(y + dfltsel, x + 4);
-       for (sel = dfltsel; (key = getkey(WHEN_POPUP)) != '\\' && key != '\r'; )
-       {
-               /* erase the selection arrow */
-               move(y + sel, x);
-               do_POPUP();
-               qaddstr("   ");
-               qaddstr(labels[sel]);
-               do_SE();
-
-               /* process the user's keystroke */
-               if (key == 'j' && sel < MENU_HEIGHT - 1)
-               {
-                       sel++;
-               }
-               else if (key == 'k' && sel > 0)
-               {
-                       sel--;
-               }
-               else if (key == '\033')
-               {
-                       sel = 0;
-                       break;
-               }
-               else
-               {
-                       for (i = 1; i < MENU_HEIGHT && labels[i][1] != key; i++)
-                       {
-                       }
-                       if (i < MENU_HEIGHT)
-                       {
-                               sel = i;
-                               break;
-                       }
-               }
-
-               /* redraw the arrow, possibly in a new place */
-               move(y + sel, x);
-               do_POPUP();
-               qaddstr("-->");
-               qaddstr(labels[sel]);
-               do_SE();
-               move(y + sel, x + 4);
-       }
-
-       /* in most cases, the default selection is "paste after" */
-       dfltsel = 3;
-
-       /* perform the appropriate action */
-       switch (sel)
-       {
-         case 0:
-               m = cursor;
-               dfltsel = 0;
-               break;
-
-         case 1: /* delete (cut) */
-               m = v_delete(m, n);
-               break;
-
-         case 2: /* yank (copy) */
-               m = v_yank(m, n);
-               break;
-
-         case 3: /* paste after */
-               m = v_paste(n, 1L, 'P');
-               break;
-
-         case 4: /* paste before */
-               m = v_paste(m, 1L, 'P');
-               dfltsel = 4;
-               break;
-
-         case 5: /* more indented */
-               m = v_rshift(m, n);
-               dfltsel = 5;
-               break;
-
-         case 6: /* less indented */
-               m = v_lshift(m, n);
-               dfltsel = 6;
-               break;
-
-         case 7: /* reformat */
-               m = v_reformat(m, n);
-               dfltsel = 7;
-               break;
-
-         case 8: /* external filter */
-               m = v_filter(m, n);
-               dfltsel = 0;
-               break;
-
-         case 9: /* save & exit */
-               /* get confirmation first */
-               do
-               {
-                       key = getkey(0);
-               } while (key != '\\' && key != 'Z' && key != '\r'    /* good */
-                     && key != '\033');                             /* bad  */
-               if (key != '\033')
-               {
-                       m = v_xit(m, 0L, 'Z');
-               }
-               break;
-
-         case 10: /* undo previous */
-               m = v_undo(m);
-               dfltsel = 9;
-               break;
-       }
-
-       /* arrange for the menu to be erased (except that "chg from kbd"
-        * already erased it, and "save & exit" doesn't care)
-        */
-       if (sel != 5 && sel != 9)
-               redraw(MARK_UNSET, FALSE);
-
-       return m;
-}
-#endif /* undef NO_POPUP */
diff --git a/commands/elvis/vi.c b/commands/elvis/vi.c
deleted file mode 100644 (file)
index 24c46dc..0000000
+++ /dev/null
@@ -1,815 +0,0 @@
-/* vi.c */
-
-/* Author:
- *     Steve Kirkendall
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-
-#include "config.h"
-#include "ctype.h"
-#include "vi.h"
-
-
-
-/* This array describes what each key does */
-#define NO_FUNC                (MARK (*)())0
-
-#define NO_ARGS                0
-#define CURSOR         1
-#define CURSOR_CNT_KEY 2
-#define CURSOR_MOVED   3
-#define CURSOR_EOL     4
-#define ZERO           5
-#define DIGIT          6
-#define CURSOR_TEXT    7
-#define KEYWORD                8
-#define ARGSMASK       0x0f
-#define        C_C_K_REP1      (CURSOR_CNT_KEY | 0x10)
-#define C_C_K_CUT      (CURSOR_CNT_KEY | 0x20)
-#define C_C_K_MARK     (CURSOR_CNT_KEY | 0x30)
-#define C_C_K_CHAR     (CURSOR_CNT_KEY | 0x40)
-#ifndef NO_SHOWMODE
-static int keymodes[] = {0, WHEN_REP1, WHEN_CUT, WHEN_MARK, WHEN_CHAR};
-# define KEYMODE(args) (keymodes[(args) >> 4])
-#else
-# define KEYMODE(args) 0
-#endif
-
-static struct keystru
-{
-       MARK    (*func)();      /* the function to run */
-       uchar   args;           /* description of the args needed */
-#ifndef NO_VISIBLE
-       short   flags;
-#else
-       uchar   flags;          /* other stuff */
-#endif
-}
-       vikeys[] =
-{
-/* NUL not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#ifndef NO_EXTENSIONS
-/* ^A  find cursor word */     {m_wsrch,       KEYWORD,        MVMT|NREL|VIZ},
-#else
-/* ^A  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/* ^B  page backward   */      {m_scroll,      CURSOR,         FRNT|VIZ},
-/* ^C  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^D  scroll dn 1/2page*/     {m_scroll,      CURSOR,         NCOL|VIZ},
-/* ^E  scroll up       */      {m_scroll,      CURSOR,         NCOL|VIZ},
-/* ^F  page forward    */      {m_scroll,      CURSOR,         FRNT|VIZ},
-/* ^G  show file status        */      {v_status,      NO_ARGS,        NO_FLAGS},
-/* ^H  move left, like h*/     {m_left,        CURSOR,         MVMT|VIZ},
-/* ^I  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^J  move down       */      {m_updnto,      CURSOR,         MVMT|LNMD|VIZ|INCL},
-/* ^K  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^L  redraw screen   */      {v_redraw,      NO_ARGS,        NO_FLAGS|VIZ},
-/* ^M  mv front next ln */     {m_updnto,      CURSOR,         MVMT|FRNT|LNMD|VIZ|INCL},
-/* ^N  move down       */      {m_updnto,      CURSOR,         MVMT|LNMD|VIZ|INCL|NCOL},
-/* ^O  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^P  move up         */      {m_updnto,      CURSOR,         MVMT|LNMD|VIZ|INCL|NCOL},
-/* ^Q  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^R  redraw screen   */      {v_redraw,      NO_ARGS,        NO_FLAGS|VIZ},
-/* ^S  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^T  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^U  scroll up 1/2page*/     {m_scroll,      CURSOR,         NCOL|VIZ},
-/* ^V  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^W  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^X  move to phys col        */      {m_tocol,       CURSOR,         MVMT|NREL|VIZ},
-/* ^Y  scroll down     */      {m_scroll,      CURSOR,         NCOL|VIZ},
-#ifdef SIGTSTP
-/* ^Z  suspend elvis   */      {v_suspend,     NO_ARGS,        NO_FLAGS},
-#else
-/* ^Z  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/* ESC not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^\  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* ^]  keyword is tag  */      {v_tag,         KEYWORD,        NO_FLAGS},
-/* ^^  previous file   */      {v_switch,      CURSOR,         NO_FLAGS},
-/* ^_  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/* SPC move right,like l*/     {m_right,       CURSOR,         MVMT|INCL|VIZ},
-/*  !  run thru filter */      {v_filter,      CURSOR_MOVED,   FRNT|LNMD|INCL|VIZ},
-/*  "  select cut buffer*/     {v_selcut,      C_C_K_CUT,      PTMV|VIZ},
-#ifndef NO_EXTENSIONS
-/*  #  increment number        */      {v_increment,   KEYWORD,        SDOT},
-#else
-/*  #  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  $  move to rear    */      {m_rear,        CURSOR,         MVMT|INCL|VIZ},
-/*  %  move to match   */      {m_match,       CURSOR,         MVMT|INCL|VIZ},
-/*  &  repeat subst    */      {v_again,       CURSOR_MOVED,   SDOT|NCOL|LNMD|INCL},
-/*  '  move to a mark  */      {m_tomark,      C_C_K_MARK,     MVMT|FRNT|NREL|LNMD|INCL|VIZ},
-#ifndef NO_SENTENCE
-/*  (  mv back sentence        */      {m_sentence,    CURSOR,         MVMT|VIZ},
-/*  )  mv fwd sentence */      {m_sentence,    CURSOR,         MVMT|VIZ},
-#else
-/*  (  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/*  )  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-#ifndef NO_ERRLIST
-/*  *  errlist         */      {v_errlist,     CURSOR,         FRNT|NREL},
-#else
-/*  *  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  +  mv front next ln */     {m_updnto,      CURSOR,         MVMT|FRNT|LNMD|VIZ|INCL},
-#ifndef NO_CHARSEARCH
-/*  ,  reverse [fFtT] cmd*/    {m__ch,         CURSOR,         MVMT|INCL|VIZ},
-#else
-/*  ,  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  -  mv front prev ln        */      {m_updnto,      CURSOR,         MVMT|FRNT|LNMD|VIZ|INCL},
-/*  .  special...      */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/*  /  forward search  */      {m_fsrch,       CURSOR_TEXT,    MVMT|NREL|VIZ},
-/*  0  part of count?  */      {NO_FUNC,       ZERO,           MVMT|PTMV|VIZ},
-/*  1  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  2  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  3  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  4  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  5  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  6  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  7  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  8  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  9  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
-/*  :  run single EX cmd*/     {v_1ex,         CURSOR_TEXT,    NO_FLAGS},
-#ifndef NO_CHARSEARCH
-/*  ;  repeat [fFtT] cmd*/     {m__ch,         CURSOR,         MVMT|INCL|VIZ},
-#else
-/*  ;  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS|VIZ},
-#endif
-/*  <  shift text left */      {v_lshift,      CURSOR_MOVED,   SDOT|FRNT|LNMD|INCL|VIZ},
-/*  =  preset filter   */      {v_reformat,    CURSOR_MOVED,   SDOT|FRNT|LNMD|INCL|VIZ},
-/*  >  shift text right        */      {v_rshift,      CURSOR_MOVED,   SDOT|FRNT|LNMD|INCL|VIZ},
-/*  ?  backward search */      {m_bsrch,       CURSOR_TEXT,    MVMT|NREL|VIZ},
-#ifndef NO_AT
-/*  @  execute a cutbuf */     {v_at,          C_C_K_CUT,      NO_FLAGS},
-#else
-/*  @  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  A  append at EOL   */      {v_insert,      CURSOR,         SDOT},
-/*  B  move back Word  */      {m_bword,       CURSOR,         MVMT|VIZ},
-/*  C  change to EOL   */      {v_change,      CURSOR_EOL,     SDOT},
-/*  D  delete to EOL   */      {v_delete,      CURSOR_EOL,     SDOT},
-/*  E  move end of Word        */      {m_eword,       CURSOR,         MVMT|INCL|VIZ},
-#ifndef NO_CHARSEARCH
-/*  F  move bk to char */      {m_Fch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
-#else
-/*  F  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  G  move to line #  */      {m_updnto,      CURSOR,         MVMT|NREL|LNMD|FRNT|INCL|VIZ},
-/*  H  move to row     */      {m_row,         CURSOR,         MVMT|LNMD|FRNT|VIZ|INCL},
-/*  I  insert at front */      {v_insert,      CURSOR,         SDOT},
-/*  J  join lines      */      {v_join,        CURSOR,         SDOT},
-#ifndef NO_EXTENSIONS
-/*  K  look up keyword */      {v_keyword,     KEYWORD,        NO_FLAGS},
-#else
-/*  K  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  L  move to last row        */      {m_row,         CURSOR,         MVMT|LNMD|FRNT|VIZ|INCL},
-/*  M  move to mid row */      {m_row,         CURSOR,         MVMT|LNMD|FRNT|VIZ|INCL},
-/*  N  reverse prev srch*/     {m_Nsrch,       CURSOR,         MVMT|NREL|VIZ},
-/*  O  insert above line*/     {v_insert,      CURSOR,         SDOT},
-/*  P  paste before    */      {v_paste,       CURSOR,         SDOT},
-/*  Q  quit to EX mode */      {v_quit,        NO_ARGS,        NO_FLAGS},
-/*  R  overtype                */      {v_overtype,    CURSOR,         SDOT},
-/*  S  change line     */      {v_change,      CURSOR_MOVED,   SDOT},
-#ifndef NO_CHARSEARCH
-/*  T  move bk to char */      {m_Tch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
-#else
-/*  T  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  U  undo whole line */      {v_undoline,    CURSOR,         FRNT},
-#ifndef NO_VISIBLE
-/*  V  start visible   */      {v_start,       CURSOR,         INCL|LNMD|VIZ},
-#else
-/*  V  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  W  move forward Word*/     {m_fword,       CURSOR,         MVMT|INCL|VIZ},
-/*  X  delete to left  */      {v_xchar,       CURSOR,         SDOT},
-/*  Y  yank text       */      {v_yank,        CURSOR_MOVED,   NCOL},
-/*  Z  save file & exit        */      {v_xit,         CURSOR_CNT_KEY, NO_FLAGS},
-/*  [  move back section*/     {m_paragraph,   CURSOR,         MVMT|LNMD|NREL|VIZ},
-#ifndef NO_POPUP
-/*  \  pop-up menu     */      {v_popup,       CURSOR_MOVED,   VIZ},
-#else
-/*  \  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  ]  move fwd section */     {m_paragraph,   CURSOR,         MVMT|LNMD|NREL|VIZ},
-/*  ^  move to front   */      {m_front,       CURSOR,         MVMT|VIZ},
-/*  _  current line    */      {m_updnto,      CURSOR,         MVMT|LNMD|FRNT|INCL},
-/*  `  move to mark    */      {m_tomark,      C_C_K_MARK,     MVMT|NREL|VIZ},
-/*  a  append at cursor        */      {v_insert,      CURSOR,         SDOT},
-/*  b  move back word  */      {m_bword,       CURSOR,         MVMT|VIZ},
-/*  c  change text     */      {v_change,      CURSOR_MOVED,   SDOT|VIZ},
-/*  d  delete op       */      {v_delete,      CURSOR_MOVED,   SDOT|VIZ},
-/*  e  move end word   */      {m_eword,       CURSOR,         MVMT|INCL|VIZ},
-#ifndef NO_CHARSEARCH
-/*  f  move fwd for char*/     {m_fch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
-#else
-/*  f  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  g  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/*  h  move left       */      {m_left,        CURSOR,         MVMT|VIZ},
-/*  i  insert at cursor        */      {v_insert,      CURSOR,         SDOT},
-/*  j  move down       */      {m_updnto,      CURSOR,         MVMT|NCOL|LNMD|VIZ|INCL},
-/*  k  move up         */      {m_updnto,      CURSOR,         MVMT|NCOL|LNMD|VIZ|INCL},
-/*  l  move right      */      {m_right,       CURSOR,         MVMT|INCL|VIZ},
-/*  m  define a mark   */      {v_mark,        C_C_K_MARK,     NO_FLAGS},
-/*  n  repeat prev srch        */      {m_nsrch,       CURSOR,         MVMT|NREL|VIZ},
-/*  o  insert below line*/     {v_insert,      CURSOR,         SDOT},
-/*  p  paste after     */      {v_paste,       CURSOR,         SDOT},
-/*  q  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-/*  r  replace chars   */      {v_replace,     C_C_K_REP1,     SDOT},
-/*  s  subst N chars   */      {v_subst,       CURSOR,         SDOT},
-#ifndef NO_CHARSEARCH
-/*  t  move fwd to char        */      {m_tch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
-#else
-/*  t  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  u  undo            */      {v_undo,        CURSOR,         NO_FLAGS},
-#ifndef NO_VISIBLE
-/*  v  start visible   */      {v_start,       CURSOR,         INCL|VIZ},
-#else
-/*  v  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
-#endif
-/*  w  move fwd word   */      {m_fword,       CURSOR,         MVMT|INCL|VIZ},
-/*  x  delete character        */      {v_xchar,       CURSOR,         SDOT},
-/*  y  yank text       */      {v_yank,        CURSOR_MOVED,   NCOL|VIZ},
-/*  z  adjust scrn row */      {m_z,           CURSOR_CNT_KEY, NCOL|VIZ},
-/*  {  back paragraph  */      {m_paragraph,   CURSOR,         MVMT|LNMD|VIZ},
-/*  |  move to column  */      {m_tocol,       CURSOR,         MVMT|NREL|VIZ},
-/*  }  fwd paragraph   */      {m_paragraph,   CURSOR,         MVMT|LNMD|VIZ},
-/*  ~  upper/lowercase */      {v_ulcase,      CURSOR,         SDOT},
-/* DEL not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS}
-};
-
-
-
-void vi()
-{
-       REG int                 key;    /* keystroke from user */
-       long                    count;  /* numeric argument to some functions */
-       REG struct keystru      *keyptr;/* pointer to vikeys[] element */
-       MARK                    tcurs;  /* temporary cursor */
-       int                     prevkey;/* previous key, if d/c/y/</>/! */
-       MARK                    range;  /* start of range for d/c/y/</>/! */
-       char                    text[132];
-       int                     dotkey; /* last "key" of a change */
-       int                     dotpkey;/* last "prevkey" of a change */
-       int                     dotkey2;/* last extra "getkey()" of a change */
-       int                     dotcnt; /* last "count" of a change */
-       int                     firstkey;
-       REG int                 i;
-
-       /* tell the redraw() function to start from scratch */
-       redraw(MARK_UNSET, FALSE);
-
-#ifdef lint
-       /* lint says that "range" might be used before it is set.  This
-        * can't really happen due to the way "range" and "prevkey" are used,
-        * but lint doesn't know that.  This line is here ONLY to keep lint
-        * happy.
-        */
-       range = 0L;
-#endif
-
-       /* safeguard against '.' with no previous command */
-       dotkey = dotpkey = dotkey2 = dotcnt = 0;
-
-       /* go immediately into insert mode, if ":set inputmode" */
-       firstkey = 0;
-#ifndef NO_EXTENSIONS
-       if (*o_inputmode)
-       {
-               firstkey = 'i';
-       }
-#endif
-
-       /* Repeatedly handle VI commands */
-       for (count = 0, prevkey = '\0'; mode == MODE_VI; )
-       {
-               /* if we've moved off the undoable line, then we can't undo it at all */
-               if (markline(cursor) != U_line)
-               {
-                       U_line = 0L;
-               }
-
-               /* report any changes from the previous command */
-               if (rptlines >= *o_report)
-               {
-                       redraw(cursor, FALSE);
-                       msg("%ld line%s %s", rptlines, (rptlines==1?"":"s"), rptlabel);
-               }
-               rptlines = 0L;
-
-               /* get the next command key.  It must be ASCII */
-               if (firstkey)
-               {
-                       key = firstkey;
-                       firstkey = 0;
-               }
-               else
-               {
-                       do
-                       {
-                               key = getkey(WHEN_VICMD);
-                       } while (key < 0 || key > 127);
-               }
-
-               /* Convert a doubled-up operator such as "dd" into "d_" */
-               if (prevkey && key == prevkey)
-               {
-                       key = '_';
-               }
-
-               /* look up the structure describing this command */
-               keyptr = &vikeys[key];
-
-               /* '&' and uppercase operators always act like doubled */
-               if (!prevkey && keyptr->args == CURSOR_MOVED
-                       && (key == '&' || isupper(key)))
-               {
-                       range = cursor;
-                       prevkey = key;
-                       key = '_';
-                       keyptr = &vikeys[key];
-               }
-
-#ifndef NO_VISIBLE
-               /* if we're in the middle of a v/V command, reject commands
-                * that aren't operators or movement commands
-                */
-               if (V_from && !(keyptr->flags & VIZ))
-               {
-                       beep();
-                       prevkey = 0;
-                       count = 0;
-                       continue;
-               }
-#endif
-
-               /* if we're in the middle of a d/c/y/</>/! command, reject
-                * anything but movement.
-                */
-               if (prevkey && !(keyptr->flags & (MVMT|PTMV)))
-               {
-                       beep();
-                       prevkey = 0;
-                       count = 0;
-                       continue;
-               }
-
-               /* set the "dot" variables, if we're supposed to */
-               if (((keyptr->flags & SDOT)
-                       || (prevkey && vikeys[prevkey].flags & SDOT))
-#ifndef NO_VISIBLE
-                   && !V_from
-#endif
-               )
-               {
-                       dotkey = key;
-                       dotpkey = prevkey;
-                       dotkey2 = '\0';
-                       dotcnt = count;
-
-                       /* remember the line before any changes are made */
-                       if (U_line != markline(cursor))
-                       {
-                               U_line = markline(cursor);
-                               strcpy(U_text, fetchline(U_line));
-                       }
-               }
-
-               /* if this is "." then set other vars from the "dot" vars */
-               if (key == '.')
-               {
-                       key = dotkey;
-                       keyptr = &vikeys[key];
-                       prevkey = dotpkey;
-                       if (prevkey)
-                       {
-                               range = cursor;
-                       }
-                       if (count == 0)
-                       {
-                               count = dotcnt;
-                       }
-                       doingdot = TRUE;
-
-                       /* remember the line before any changes are made */
-                       if (U_line != markline(cursor))
-                       {
-                               U_line = markline(cursor);
-                               strcpy(U_text, fetchline(U_line));
-                       }
-               }
-               else
-               {
-                       doingdot = FALSE;
-               }
-
-               /* process the key as a command */
-               tcurs = cursor;
-               force_flags = NO_FLAGS;
-               switch (keyptr->args & ARGSMASK)
-               {
-                 case ZERO:
-                       if (count == 0)
-                       {
-                               tcurs = cursor & ~(BLKSIZE - 1);
-                               break;
-                       }
-                       /* else fall through & treat like other digits... */
-
-                 case DIGIT:
-                       count = count * 10 + key - '0';
-                       break;
-
-                 case KEYWORD:
-                       /* if not on a keyword, fail */
-                       pfetch(markline(cursor));
-                       key = markidx(cursor);
-                       if (!isalnum(ptext[key]))
-                       {
-                               tcurs = MARK_UNSET;
-                               break;
-                       }
-
-                       /* find the start of the keyword */
-                       while (key > 0 && isalnum(ptext[key - 1]))
-                       {
-                               key--;
-                       }
-                       tcurs = (cursor & ~(BLKSIZE - 1)) + key;
-
-                       /* copy it into a buffer, and NUL-terminate it */
-                       i = 0;
-                       do
-                       {
-                               text[i++] = ptext[key++];
-                       } while (isalnum(ptext[key]));
-                       text[i] = '\0';
-
-                       /* call the function */
-                       tcurs = (*keyptr->func)(text, tcurs, count);
-                       count = 0L;
-                       break;
-
-                 case NO_ARGS:
-                       if (keyptr->func)
-                       {
-                               (*keyptr->func)();
-                       }
-                       else
-                       {
-                               beep();
-                       }
-                       count = 0L;
-                       break;
-       
-                 case CURSOR:
-                       tcurs = (*keyptr->func)(cursor, count, key, prevkey);
-                       count = 0L;
-                       break;
-
-                 case CURSOR_CNT_KEY:
-                       if (doingdot)
-                       {
-                               tcurs = (*keyptr->func)(cursor, count, dotkey2);
-                       }
-                       else
-                       {
-                               /* get a key */
-                               i = getkey(KEYMODE(keyptr->args));
-                               if (i == '\033') /* ESC */
-                               {
-                                       count = 0;
-                                       tcurs = MARK_UNSET;
-                                       break; /* exit from "case CURSOR_CNT_KEY" */
-                               }
-                               else if (i == ctrl('V'))
-                               {
-                                       i = getkey(0);
-                               }
-
-                               /* if part of an SDOT command, remember it */
-                                if (keyptr->flags & SDOT
-                                || (prevkey && vikeys[prevkey].flags & SDOT))
-                               {
-                                       dotkey2 = i;
-                               }
-
-                               /* do it */
-                               tcurs = (*keyptr->func)(cursor, count, i);
-                       }
-                       count = 0L;
-                       break;
-       
-                 case CURSOR_MOVED:
-#ifndef NO_VISIBLE
-                       if (V_from)
-                       {
-                               range = cursor;
-                               tcurs = V_from;
-                               count = 0L;
-                               prevkey = key;
-                               key = (V_linemd ? 'V' : 'v');
-                               keyptr = &vikeys[key];
-                       }
-                       else
-#endif
-                       {
-                               prevkey = key;
-                               range = cursor;
-                               force_flags = LNMD|INCL;
-                       }
-                       break;
-
-                 case CURSOR_EOL:
-                       prevkey = key;
-                       /* a zero-length line needs special treatment */
-                       pfetch(markline(cursor));
-                       if (plen == 0)
-                       {
-                               /* act on a zero-length section of text */
-                               range = tcurs = cursor;
-                               key = '0';
-                       }
-                       else
-                       {
-                               /* act like CURSOR_MOVED with '$' movement */
-                               range = cursor;
-                               tcurs = m_rear(cursor, 1L);
-                               key = '$';
-                       }
-                       count = 0L;
-                       keyptr = &vikeys[key];
-                       break;
-
-                 case CURSOR_TEXT:
-                       do
-                       {       
-                               text[0] = key;
-                               if (vgets(key, text + 1, sizeof text - 1) >= 0)
-                               {
-                                       /* reassure user that <CR> was hit */
-                                       qaddch('\r');
-                                       refresh();
-
-                                       /* call the function with the text */
-                                       tcurs = (*keyptr->func)(cursor, text);
-                               }
-                               else
-                               {
-                                       if (exwrote || mode == MODE_COLON)
-                                       {
-                                               redraw(MARK_UNSET, FALSE);
-                                       }
-                                       mode = MODE_VI;
-                               }
-                       } while (mode == MODE_COLON);
-                       count = 0L;
-                       break;
-               }
-
-               /* if that command took us out of vi mode, then exit the loop
-                * NOW, without tweaking the cursor or anything.  This is very
-                * important when mode == MODE_QUIT.
-                */
-               if (mode != MODE_VI)
-               {
-                       break;
-               }
-
-               /* now move the cursor, as appropriate */
-               if (keyptr->args == CURSOR_MOVED)
-               {
-                       /* the < and > keys have FRNT,
-                        * but it shouldn't be applied yet
-                        */
-                       tcurs = adjmove(cursor, tcurs, 0);
-               }
-               else
-               {
-                       tcurs = adjmove(cursor, tcurs, (int)keyptr->flags | force_flags);
-               }
-
-               /* was that the end of a d/c/y/</>/! command? */
-               if (prevkey && ((keyptr->flags & MVMT)
-#ifndef NO_VISIBLE
-                                              || V_from
-#endif
-                               ) && count == 0L)
-               {
-#ifndef NO_VISIBLE
-                       /* turn off the hilight */
-                       V_from = 0L;
-#endif
-
-                       /* if the movement command failed, cancel operation */
-                       if (tcurs == MARK_UNSET)
-                       {
-                               prevkey = 0;
-                               count = 0;
-                               continue;
-                       }
-
-                       /* make sure range=front and tcurs=rear.  Either way,
-                        * leave cursor=range since that's where we started.
-                        */
-                       cursor = range;
-                       if (tcurs < range)
-                       {
-                               range = tcurs;
-                               tcurs = cursor;
-                       }
-
-                       /* The 'w' and 'W' destinations should never take us
-                        * to the front of a line.  Instead, they should take
-                        * us only to the end of the preceding line.
-                        */
-                       if ((keyptr->flags & (MVMT|NREL|LNMD|FRNT|INCL)) == MVMT
-                         && markline(range) < markline(tcurs)
-                         && (markline(tcurs) > nlines || tcurs == m_front(tcurs, 0L)))
-                       {
-                               tcurs = (tcurs & ~(BLKSIZE - 1)) - BLKSIZE;
-                               pfetch(markline(tcurs));
-                               tcurs += plen;
-                       }
-
-                       /* adjust for line mode & inclusion of last char/line */
-                       i = (keyptr->flags | vikeys[prevkey].flags);
-                       switch ((i | force_flags) & (INCL|LNMD))
-                       {
-                         case INCL:
-                               tcurs++;
-                               break;
-
-                         case INCL|LNMD:
-                               tcurs += BLKSIZE;
-                               /* fall through... */
-
-                         case LNMD:
-                               range &= ~(BLKSIZE - 1);
-                               tcurs &= ~(BLKSIZE - 1);
-                               break;
-                       }
-
-                       /* run the function */
-                       tcurs = (*vikeys[prevkey].func)(range, tcurs);
-                       if (mode == MODE_VI)
-                       {
-                               (void)adjmove(cursor, cursor, 0);
-                               cursor = adjmove(cursor, tcurs, (int)vikeys[prevkey].flags);
-                       }
-
-                       /* cleanup */
-                       prevkey = 0;
-               }
-               else if (!prevkey)
-               {
-                       if (tcurs != MARK_UNSET)
-                               cursor = tcurs;
-               }
-       }
-}
-
-/* This function adjusts the MARK value that they return; here we make sure
- * it isn't past the end of the line, and that the column hasn't been
- * *accidentally* changed.
- */
-MARK adjmove(old, new, flags)
-       MARK            old;    /* the cursor position before the command */
-       REG MARK        new;    /* the cursor position after the command */
-       int             flags;  /* various flags regarding cursor mvmt */
-{
-       static int      colno;  /* the column number that we want */
-       REG char        *text;  /* used to scan through the line's text */
-       REG int         i;
-
-#ifdef DEBUG
-       watch();
-#endif
-
-       /* if the command failed, bag it! */
-       if (new == MARK_UNSET)
-       {
-               beep();
-               return old;
-       }
-
-       /* if this is a non-relative movement, set the '' mark */
-       if (flags & NREL)
-       {
-               mark[26] = old;
-       }
-
-       /* make sure it isn't past the end of the file */
-       if (markline(new) < 1)
-       {
-               new = MARK_FIRST;
-       }
-       else if (markline(new) > nlines)
-       {
-               new = MARK_LAST;
-       }
-
-       /* fetch the new line */
-       pfetch(markline(new));
-
-       /* move to the front, if we're supposed to */
-       if (flags & FRNT)
-       {
-               new = m_front(new, 1L);
-       }
-
-       /* change the column#, or change the mark to suit the column# */
-       if (!(flags & NCOL))
-       {
-               /* change the column# */
-               i = markidx(new);
-               if (i == BLKSIZE - 1)
-               {
-                       new &= ~(BLKSIZE - 1);
-                       if (plen > 0)
-                       {
-                               new += plen - 1;
-                       }
-                       colno = BLKSIZE * 8; /* one heck of a big colno */
-               }
-               else if (plen > 0)
-               {
-                       if (i >= plen)
-                       {
-                               new = (new & ~(BLKSIZE - 1)) + plen - 1;
-                       }
-                       colno = idx2col(new, ptext, FALSE);
-               }
-               else
-               {
-                       new &= ~(BLKSIZE - 1);
-                       colno = 0;
-               }
-       }
-       else
-       {
-               /* adjust the mark to get as close as possible to column# */
-               for (i = 0, text = ptext; i <= colno && *text; text++)
-               {
-                       if (*text == '\t' && !*o_list)
-                       {
-                               i += *o_tabstop - (i % *o_tabstop);
-                       }
-                       else if (UCHAR(*text) < ' ' || *text == 127)
-                       {
-                               i += 2;
-                       }
-#ifndef NO_CHARATTR
-                       else if (*o_charattr && text[0] == '\\' && text[1] == 'f' && text[2])
-                       {
-                               text += 2; /* plus one more in "for()" stmt */
-                       }
-#endif
-                       else
-                       {
-                               i++;
-                       }
-               }
-               if (text > ptext)
-               {
-                       text--;
-               }
-               new = (new & ~(BLKSIZE - 1)) + (int)(text - ptext);
-       }
-
-       return new;
-}
-
-
-#ifdef DEBUG
-watch()
-{
-       static wasset;
-
-       if (*origname)
-       {
-               wasset = TRUE;
-       }
-       else if (wasset)
-       {
-               mode = MODE_EX;
-               msg("origname was clobbered");
-               endwin();
-               abort();
-       }
-
-       if (wasset && nlines == 0)
-       {
-               mode = MODE_EX;
-               msg("nlines=0");
-               endwin();
-               abort();
-       }
-}
-#endif
diff --git a/commands/elvis/vi.h b/commands/elvis/vi.h
deleted file mode 100644 (file)
index 4c42dd2..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-/* vi.h */
-
-/* Author:
- *     Steve Kirkendall
- *     14407 SW Teal Blvd. #C
- *     Beaverton, OR 97005
- *     kirkenda@cs.pdx.edu
- */
-
-#define VERSION "ELVIS 1.5, by Steve Kirkendall (23 March 1992)"
-#define COPYING        "This version of ELVIS is freely redistributable."
-
-#include <errno.h>
-extern int errno;
-#if TOS && !defined(__GNUC__)
-#define ENOENT (-AEFILNF)
-#endif
-
-#if TOS || VMS
-# include <types.h>
-# define O_RDONLY      0
-# define O_WRONLY      1
-# define O_RDWR                2
-# ifdef __GNUC__
-#  define S_IJDIR      S_IFDIR
-# endif
-#else
-# if OSK
-#  include <modes.h>
-#  define O_RDONLY     S_IREAD
-#  define O_WRONLY     S_IWRITE
-#  define O_RDWR       (S_IREAD | S_IWRITE)
-#  define ENOENT       E_PNNF
-#  define sprintf      Sprintf
-# else
-#  include <sys/types.h>
-#  if COHERENT
-#   include <sys/fcntl.h>
-#  else
-#   include <fcntl.h>
-#  endif
-# endif
-#endif
-
-#ifndef O_BINARY
-# define O_BINARY      0
-#endif
-
-#include "curses.h"
-
-#include <signal.h>
-
-/*------------------------------------------------------------------------*/
-/* Miscellaneous constants.                                              */
-
-#define INFINITY       2000000001L     /* a very large integer */
-#define LONGKEY                10              /* longest possible raw :map key */
-#ifndef MAXRCLEN
-# define MAXRCLEN      1000            /* longest possible :@ command */
-#endif
-
-/*------------------------------------------------------------------------*/
-/* These describe how temporary files are divided into blocks             */
-
-#define MAXBLKS        (BLKSIZE / sizeof(unsigned short))
-typedef union
-{
-       char            c[BLKSIZE];     /* for text blocks */
-       unsigned short  n[MAXBLKS];     /* for the header block */
-}
-       BLK;
-
-/*------------------------------------------------------------------------*/
-/* These are used manipulate BLK buffers.                                 */
-
-extern BLK     hdr;            /* buffer for the header block */
-extern BLK     *blkget();      /* given index into hdr.c[], reads block */
-extern BLK     *blkadd();      /* inserts a new block into hdr.c[] */
-
-/*------------------------------------------------------------------------*/
-/* These are used to keep track of various flags                          */
-extern struct _viflags
-{
-       short   file;           /* file flags */
-}
-       viflags;
-
-/* file flags */
-#define NEWFILE                0x0001  /* the file was just created */
-#define READONLY       0x0002  /* the file is read-only */
-#define HADNUL         0x0004  /* the file contained NUL characters */
-#define MODIFIED       0x0008  /* the file has been modified, but not saved */
-#define NOFILE         0x0010  /* no name is known for the current text */
-#define ADDEDNL                0x0020  /* newlines were added to the file */
-#define HADBS          0x0040  /* backspace chars were lost from the file */
-#define UNDOABLE       0x0080  /* file has been modified */
-#define NOTEDITED      0x0100  /* the :file command has been used */
-
-/* macros used to set/clear/test flags */
-#define setflag(x,y)   viflags.x |= y
-#define clrflag(x,y)   viflags.x &= ~y
-#define tstflag(x,y)   (viflags.x & y)
-#define initflags()    viflags.file = 0;
-
-/* The options */
-extern char    o_autoindent[1];
-extern char    o_autoprint[1];
-extern char    o_autotab[1];
-extern char    o_autowrite[1];
-extern char    o_columns[3];
-extern char    o_directory[30];
-extern char    o_edcompatible[1];
-extern char    o_equalprg[80];
-extern char    o_errorbells[1];
-extern char    o_exrefresh[1];
-extern char    o_ignorecase[1];
-extern char    o_keytime[3];
-extern char    o_keywordprg[80];
-extern char    o_lines[3];
-extern char    o_list[1];
-extern char    o_number[1];
-extern char    o_readonly[1];
-extern char    o_remap[1];
-extern char    o_report[3];
-extern char    o_scroll[3];
-extern char    o_shell[60];
-extern char    o_shiftwidth[3];
-extern char    o_sidescroll[3];
-extern char    o_sync[1];
-extern char    o_tabstop[3];
-extern char    o_term[30];
-extern char    o_flash[1];
-extern char    o_warn[1];
-extern char    o_wrapscan[1];
-
-#ifndef CRUNCH
-extern char    o_beautify[1];
-extern char    o_exrc[1];
-extern char    o_mesg[1];
-extern char    o_more[1];
-extern char    o_novice[1];
-extern char    o_prompt[1];
-extern char    o_taglength[3];
-extern char    o_terse[1];
-extern char    o_window[3];
-extern char    o_wrapmargin[3];
-extern char    o_writeany[1];
-#endif
-
-#ifndef NO_ERRLIST
-extern char    o_cc[30];
-extern char    o_make[30];
-#endif
-
-#ifndef NO_CHARATTR
-extern char    o_charattr[1];
-#endif
-
-#ifndef NO_DIGRAPH
-extern char    o_digraph[1];
-extern char    o_flipcase[80];
-#endif
-
-#ifndef NO_SENTENCE
-extern char    o_hideformat[1];
-#endif
-
-#ifndef NO_EXTENSIONS
-extern char    o_inputmode[1];
-extern char    o_ruler[1];
-#endif
-
-#ifndef NO_MAGIC
-extern char    o_magic[1];
-#endif
-
-#ifndef NO_MODELINES
-extern char    o_modelines[1];
-#endif
-
-#ifndef NO_SENTENCE
-extern char    o_paragraphs[30];
-extern char    o_sections[30];
-#endif
-
-#if MSDOS
-extern char    o_pcbios[1];
-#endif
-
-#ifndef NO_SHOWMATCH
-extern char    o_showmatch[1];
-#endif
-
-#ifndef        NO_SHOWMODE
-extern char    o_smd[1];
-#endif
-
-/*------------------------------------------------------------------------*/
-/* These help support the single-line multi-change "undo" -- shift-U      */
-
-extern char    U_text[BLKSIZE];
-extern long    U_line;
-
-/*------------------------------------------------------------------------*/
-/* These are used to refer to places in the text                         */
-
-typedef long   MARK;
-#define markline(x)    (long)((x) / BLKSIZE)
-#define markidx(x)     (int)((x) & (BLKSIZE - 1))
-#define MARK_UNSET     ((MARK)0)
-#define MARK_FIRST     ((MARK)BLKSIZE)
-#define MARK_LAST      ((MARK)(nlines * BLKSIZE))
-#define MARK_AT_LINE(x)        ((MARK)(x) * BLKSIZE)
-
-#define NMARKS 29
-extern MARK    mark[NMARKS];   /* marks a-z, plus mark ' and two temps */
-extern MARK    cursor;         /* mark where line is */
-
-/*------------------------------------------------------------------------*/
-/* These are used to keep track of the current & previous files.         */
-
-extern long    origtime;       /* modification date&time of the current file */
-extern char    origname[256];  /* name of the current file */
-extern char    prevorig[256];  /* name of the preceding file */
-extern long    prevline;       /* line number from preceding file */
-
-/*------------------------------------------------------------------------*/
-/* misc housekeeping variables & functions                               */
-
-extern int     tmpfd;          /* fd used to access the tmp file */
-extern int     tmpnum;         /* counter used to generate unique filenames */
-extern long    lnum[MAXBLKS];  /* last line# of each block */
-extern long    nlines;         /* number of lines in the file */
-extern char    args[BLKSIZE];  /* file names given on the command line */
-extern int     argno;          /* the current element of args[] */
-extern int     nargs;          /* number of filenames in args */
-extern long    changes;        /* counts changes, to prohibit short-cuts */
-extern int     significant;    /* boolean: was a *REAL* change made? */
-extern BLK     tmpblk;         /* a block used to accumulate changes */
-extern long    topline;        /* file line number of top line */
-extern int     leftcol;        /* column number of left col */
-#define                botline  (topline + LINES - 2)
-#define                rightcol (leftcol + COLS - (*o_number ? 9 : 1))
-extern int     physcol;        /* physical column number that cursor is on */
-extern int     physrow;        /* physical row number that cursor is on */
-extern int     exwrote;        /* used to detect verbose ex commands */
-extern int     doingdot;       /* boolean: are we doing the "." command? */
-extern int     doingglobal;    /* boolean: are doing a ":g" command? */
-extern long    rptlines;       /* number of lines affected by a command */
-extern char    *rptlabel;      /* description of how lines were affected */
-extern char    *fetchline();   /* read a given line from tmp file */
-extern char    *parseptrn();   /* isolate a regexp in a line */
-extern MARK    paste();        /* paste from cut buffer to a given point */
-extern char    *wildcard();    /* expand wildcards in filenames */
-extern MARK    input();        /* inserts characters from keyboard */
-extern char    *linespec();    /* finds the end of a /regexp/ string */
-#define                ctrl(ch) ((ch)&037)
-#ifndef NO_RECYCLE
-extern long    allocate();     /* allocate a free block of the tmp file */
-#endif
-extern int     trapint();      /* trap handler for SIGINT */
-extern int     deathtrap();    /* trap handler for deadly signals */
-extern void    blkdirty();     /* marks a block as being "dirty" */
-extern void    blkflush();     /* writes a single dirty block to the disk */
-extern void    blksync();      /* forces all "dirty" blocks to disk */
-extern void    blkinit();      /* resets the block cache to "empty" state */
-extern void    beep();         /* rings the terminal's bell */
-extern void    exrefresh();    /* writes text to the screen */
-extern void    msg();          /* writes a printf-style message to the screen */
-extern void    endmsgs();      /* if "manymsgs" is set, then scroll up 1 line */
-extern void    garbage();      /* reclaims any garbage blocks */
-extern void    redraw();       /* updates the screen after a change */
-extern void    resume_curses();/* puts the terminal in "cbreak" mode */
-extern void    beforedo();     /* saves current revision before a new change */
-extern void    afterdo();      /* marks end of a beforedo() change */
-extern void    abortdo();      /* like "afterdo()" followed by "undo()" */
-extern int     undo();         /* restores file to previous undo() */
-extern void    dumpkey();      /* lists key mappings to the screen */
-extern void    mapkey();       /* defines a new key mapping */
-extern void    savekeys();     /* lists key mappings to a file */
-extern void    redrawrange();  /* records clues from modify.c */
-extern void    cut();          /* saves text in a cut buffer */
-extern void    delete();       /* deletes text */
-extern void    add();          /* adds text */
-extern void    change();       /* deletes text, and then adds other text */
-extern void    cutswitch();    /* updates cut buffers when we switch files */
-extern void    do_abbr();      /* defines or lists abbreviations */
-extern void    do_digraph();   /* defines or lists digraphs */
-extern void    exstring();     /* execute a string as EX commands */
-extern void    dumpopts();
-extern void    setopts();
-extern void    saveopts();
-extern void    savedigs();
-extern void    saveabbr();
-extern void    savecolor();
-extern void    cutname();
-extern void    cutname();
-extern void    initopts();
-extern void    cutend();
-#ifndef CRUNCH
-extern int     wset;           /* boolean: has the "window" size been set? */
-#endif
-
-/*------------------------------------------------------------------------*/
-/* macros that are used as control structures                             */
-
-#define BeforeAfter(before, after) for((before),bavar=1;bavar;(after),bavar=0)
-#define ChangeText     BeforeAfter(beforedo(FALSE),afterdo())
-
-extern int     bavar;          /* used only in BeforeAfter macros */
-
-/*------------------------------------------------------------------------*/
-/* These are the movement commands.  Each accepts a mark for the starting */
-/* location & number and returns a mark for the destination.             */
-
-extern MARK    m_updnto();             /* k j G */
-extern MARK    m_right();              /* h */
-extern MARK    m_left();               /* l */
-extern MARK    m_tocol();              /* | */
-extern MARK    m_front();              /* ^ */
-extern MARK    m_rear();               /* $ */
-extern MARK    m_fword();              /* w */
-extern MARK    m_bword();              /* b */
-extern MARK    m_eword();              /* e */
-extern MARK    m_paragraph();          /* { } [[ ]] */
-extern MARK    m_match();              /* % */
-#ifndef NO_SENTENCE
- extern MARK   m_sentence();           /* ( ) */
-#endif
-extern MARK    m_tomark();             /* 'm */
-#ifndef NO_EXTENSIONS
-extern MARK    m_wsrch();              /* ^A */
-#endif
-extern MARK    m_nsrch();              /* n */
-extern MARK    m_Nsrch();              /* N */
-extern MARK    m_fsrch();              /* /regexp */
-extern MARK    m_bsrch();              /* ?regexp */
-#ifndef NO_CHARSEARCH
- extern MARK   m__ch();                /* ; , */
- extern MARK   m_fch();                /* f */
- extern MARK   m_tch();                /* t */
- extern MARK   m_Fch();                /* F */
- extern MARK   m_Tch();                /* T */
-#endif
-extern MARK    m_row();                /* H L M */
-extern MARK    m_z();                  /* z */
-extern MARK    m_scroll();             /* ^B ^F ^E ^Y ^U ^D */
-
-/* Some stuff that is used by movement functions... */
-
-extern MARK    adjmove();              /* a helper fn, used by move fns */
-
-/* This macro is used to set the default value of cnt */
-#define DEFAULT(val)   if (cnt < 1) cnt = (val)
-
-/* These are used to minimize calls to fetchline() */
-extern int     plen;   /* length of the line */
-extern long    pline;  /* line number that len refers to */
-extern long    pchgs;  /* "changes" level that len refers to */
-extern char    *ptext; /* text of previous line, if valid */
-extern void    pfetch();
-extern char    digraph();
-
-/* This is used to build a MARK that corresponds to a specific point in the
- * line that was most recently pfetch'ed.
- */
-#define buildmark(text)        (MARK)(BLKSIZE * pline + (int)((text) - ptext))
-
-
-/*------------------------------------------------------------------------*/
-/* These are used to handle EX commands.                                 */
-
-#define  CMD_NULL      0       /* NOT A VALID COMMAND */
-#define  CMD_ABBR      1       /* "define an abbreviation" */
-#define  CMD_ARGS      2       /* "show me the args" */
-#define  CMD_APPEND    3       /* "insert lines after this line" */
-#define  CMD_AT                4       /* "execute a cut buffer's contents via EX" */
-#define  CMD_BANG      5       /* "run a single shell command" */
-#define  CMD_CC                6       /* "run `cc` and then do CMD_ERRLIST" */
-#define  CMD_CD                7       /* "change directories" */
-#define  CMD_CHANGE    8       /* "change some lines" */
-#define         CMD_COLOR      9       /* "change the default colors" */
-#define  CMD_COPY      10      /* "copy the selected text to a given place" */
-#define  CMD_DELETE    11      /* "delete the selected text" */
-#define  CMD_DIGRAPH   12      /* "add a digraph, or display them all" */
-#define  CMD_EDIT      13      /* "switch to a different file" */
-#define  CMD_EQUAL     14      /* "display a line number" */
-#define  CMD_ERRLIST   15      /* "locate the next error in a list" */
-#define  CMD_FILE      16      /* "show the file's status" */
-#define  CMD_GLOBAL    17      /* "globally search & do a command" */
-#define  CMD_INSERT    18      /* "insert lines before the current line" */
-#define  CMD_JOIN      19      /* "join the selected line & the one after" */
-#define  CMD_LIST      20      /* "print lines, making control chars visible" */
-#define  CMD_MAKE      21      /* "run `make` and then do CMD_ERRLIST" */
-#define  CMD_MAP       22      /* "adjust the keyboard map" */
-#define  CMD_MARK      23      /* "mark this line" */
-#define  CMD_MKEXRC    24      /* "make a .exrc file" */
-#define  CMD_MOVE      25      /* "move the selected text to a given place" */
-#define  CMD_NEXT      26      /* "switch to next file in args" */
-#define  CMD_NUMBER    27      /* "print lines from the file w/ line numbers" */
-#define  CMD_PRESERVE  28      /* "act as though vi crashed" */
-#define  CMD_PREVIOUS  29      /* "switch to the previous file in args" */
-#define  CMD_PRINT     30      /* "print the selected text" */
-#define  CMD_PUT       31      /* "insert any cut lines before this line" */
-#define  CMD_QUIT      32      /* "quit without writing the file" */
-#define  CMD_READ      33      /* "append the given file after this line */
-#define  CMD_RECOVER   34      /* "recover file after vi crashes" - USE -r FLAG */
-#define  CMD_REWIND    35      /* "rewind to first file" */
-#define  CMD_SET       36      /* "set a variable's value" */
-#define  CMD_SHELL     37      /* "run some lines through a command" */
-#define  CMD_SHIFTL    38      /* "shift lines left" */
-#define  CMD_SHIFTR    39      /* "shift lines right" */
-#define  CMD_SOURCE    40      /* "interpret a file's contents as ex commands" */
-#define  CMD_STOP      41      /* same as CMD_SUSPEND */
-#define  CMD_SUBAGAIN  42      /* "repeat the previous substitution" */
-#define  CMD_SUBSTITUTE        43      /* "substitute text in this line" */
-#define  CMD_SUSPEND   44      /* "suspend the vi session" */
-#define  CMD_TR                45      /* "transliterate chars in the selected lines" */
-#define  CMD_TAG       46      /* "go to a particular tag" */
-#define  CMD_UNABBR    47      /* "remove an abbreviation definition" */
-#define  CMD_UNDO      48      /* "undo the previous command" */
-#define  CMD_UNMAP     49      /* "remove a key sequence map */
-#define  CMD_VERSION   50      /* "describe which version this is" */
-#define  CMD_VGLOBAL   51      /* "apply a cmd to lines NOT containing an RE" */
-#define  CMD_VISUAL    52      /* "go into visual mode" */
-#define  CMD_WQUIT     53      /* "write this file out (any case) & quit" */
-#define  CMD_WRITE     54      /* "write the selected(?) text to a given file" */
-#define  CMD_XIT       55      /* "write this file out (if modified) & quit" */
-#define  CMD_YANK      56      /* "copy the selected text into the cut buffer" */
-#ifdef DEBUG
-# define CMD_DEBUG     57      /* access to internal data structures */
-# define CMD_VALIDATE  58      /* check for internal consistency */
-#endif
-typedef int CMD;
-
-extern void    ex();
-extern void    vi();
-extern void    doexcmd();
-
-extern void    cmd_append();
-extern void    cmd_args();
-#ifndef NO_AT
-extern void    cmd_at();
-#endif
-extern void    cmd_cd();
-#ifndef NO_COLOR
-extern void    cmd_color();
-#endif
-extern void    cmd_delete();
-#ifndef NO_DIGRAPH
-extern void    cmd_digraph();
-#endif
-extern void    cmd_edit();
-#ifndef NO_ERRLIST
-extern void    cmd_errlist();
-#endif
-extern void    cmd_file();
-extern void    cmd_global();
-extern void    cmd_join();
-extern void    cmd_mark();
-#ifndef NO_ERRLIST
-extern void    cmd_make();
-#endif
-extern void    cmd_map();
-#ifndef NO_MKEXRC
-extern void    cmd_mkexrc();
-#endif
-extern void    cmd_next();
-extern void    cmd_print();
-extern void    cmd_put();
-extern void    cmd_read();
-extern void    cmd_set();
-extern void    cmd_shell();
-extern void    cmd_shift();
-extern void    cmd_source();
-extern void    cmd_substitute();
-extern void    cmd_tag();
-extern void    cmd_undo();
-extern void    cmd_version();
-extern void    cmd_write();
-extern void    cmd_xit();
-extern void    cmd_move();
-#ifdef DEBUG
-extern void    cmd_debug();
-extern void    cmd_validate();
-#endif
-#ifdef SIGTSTP
-extern void    cmd_suspend();
-#endif
-
-/*----------------------------------------------------------------------*/
-/* These are used to handle VI commands                                */
-
-extern MARK    v_1ex();        /* : */
-extern MARK    v_mark();       /* m */
-extern MARK    v_quit();       /* Q */
-extern MARK    v_redraw();     /* ^L ^R */
-extern MARK    v_ulcase();     /* ~ */
-extern MARK    v_undo();       /* u */
-extern MARK    v_xchar();      /* x X */
-extern MARK    v_replace();    /* r */
-extern MARK    v_overtype();   /* R */
-extern MARK    v_selcut();     /* " */
-extern MARK    v_paste();      /* p P */
-extern MARK    v_yank();       /* y Y */
-extern MARK    v_delete();     /* d D */
-extern MARK    v_join();       /* J */
-extern MARK    v_insert();     /* a A i I o O */
-extern MARK    v_change();     /* c C */
-extern MARK    v_subst();      /* s */
-extern MARK    v_lshift();     /* < */
-extern MARK    v_rshift();     /* > */
-extern MARK    v_reformat();   /* = */
-extern MARK    v_filter();     /* ! */
-extern MARK    v_status();     /* ^G */
-extern MARK    v_switch();     /* ^^ */
-extern MARK    v_tag();        /* ^] */
-extern MARK    v_xit();        /* ZZ */
-extern MARK    v_undoline();   /* U */
-extern MARK    v_again();      /* & */
-#ifndef NO_EXTENSIONS
- extern MARK   v_keyword();    /* K */
- extern MARK   v_increment();  /* * */
-#endif
-#ifndef NO_ERRLIST
- extern MARK   v_errlist();    /* * */
-#endif
-#ifndef NO_AT
- extern MARK   v_at();         /* @ */
-#endif
-#ifdef SIGTSTP
- extern MARK   v_suspend();    /* ^Z */
-#endif
-#ifndef NO_POPUP
- extern MARK   v_popup();      /* \ */
-#endif
-
-/*----------------------------------------------------------------------*/
-/* These flags describe the quirks of the individual visual commands */
-#define NO_FLAGS       0x00
-#define        MVMT            0x01    /* this is a movement command */
-#define PTMV           0x02    /* this can be *part* of a movement command */
-#define FRNT           0x04    /* after move, go to front of line */
-#define INCL           0x08    /* include last char when used with c/d/y */
-#define LNMD           0x10    /* use line mode of c/d/y */
-#define NCOL           0x20    /* this command can't change the column# */
-#define NREL           0x40    /* this is "non-relative" -- set the '' mark */
-#define SDOT           0x80    /* set the "dot" variables, for the "." cmd */
-#ifndef NO_VISIBLE
-# define VIZ           0x100   /* commands which can be used with 'v' */
-#else
-# define VIZ           0
-#endif
-
-/* This variable is zeroed before a command executes, and later ORed with the
- * command's flags after the command has been executed.  It is used to force
- * certain flags to be TRUE for *some* invocations of a particular command.
- * For example, "/regexp/+offset" forces the LNMD flag, and sometimes a "p"
- * or "P" command will force FRNT.
- */
-extern int     force_flags;
-
-/*----------------------------------------------------------------------*/
-/* These describe what mode we're in */
-
-#define MODE_EX                1       /* executing ex commands */
-#define        MODE_VI         2       /* executing vi commands */
-#define        MODE_COLON      3       /* executing an ex command from vi mode */
-#define        MODE_QUIT       4
-extern int     mode;
-
-#define WHEN_VICMD     1       /* getkey: we're reading a VI command */
-#define WHEN_VIINP     2       /* getkey: we're in VI's INPUT mode */
-#define WHEN_VIREP     4       /* getkey: we're in VI's REPLACE mode */
-#define WHEN_EX                8       /* getkey: we're in EX mode */
-#define WHEN_MSG       16      /* getkey: we're at a "more" prompt */
-#define WHEN_POPUP     32      /* getkey: we're in the pop-up menu */
-#define WHEN_REP1      64      /* getkey: we're getting a single char for 'r' */
-#define WHEN_CUT       128     /* getkey: we're getting a cut buffer name */
-#define WHEN_MARK      256     /* getkey: we're getting a mark name */
-#define WHEN_CHAR      512     /* getkey: we're getting a destination for f/F/t/T */
-#define WHEN_INMV      4096    /* in input mode, interpret the key in VICMD mode */
-#define WHEN_FREE      8192    /* free the keymap after doing it once */
-#define WHENMASK       (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP|WHEN_REP1|WHEN_CUT|WHEN_MARK|WHEN_CHAR)
-
-#ifndef NO_VISIBLE
-extern MARK    V_from;
-extern int     V_linemd;
-extern MARK    v_start();
-#endif
-
-#ifdef DEBUG
-# define malloc(size)  dbmalloc(size, __FILE__, __LINE__)
-# define free(ptr)     dbfree(ptr, __FILE__, __LINE__)
-extern char *dbmalloc();
-#endif
diff --git a/dist/nvi/Changes b/dist/nvi/Changes
new file mode 100644 (file)
index 0000000..b8329ba
--- /dev/null
@@ -0,0 +1,34 @@
+Changes since 1.81.5
+    * various compilation fixes
+    * support for newer DBs
+    * tcl support compiles again
+Changes since 1.81.4
+    * add Changes document
+    * the preserve command overwrote the edited file; the problem
+      is really in DB; a bandaid was added
+    * configure changes
+       - -rpath now on by default
+       - check for iconv
+    * handle incomplete/invalid input
+    * upgrade libtool and automake
+    * Motif front-end was getting out of sync; fixed
+    * ^T works in presence of wide chars
+    * fix use of OPT_GLOBAL (YAMAMOTO Takashi <takashi.yamamoto@bigfoot.com>)
+    * missing fallback function added
+    * fix use of both leftright and number
+       (problem reported by Dima Dorfman <dima@unixfreak.org>)
+    * install everything 1.79 installed
+    * fix count argument for commands
+       (problem reported by Arfst Ludwig <Arfst.Ludwig@LHSystems.COM>)
+    * perl changes
+       - map no longer assumes its argument is the name of a perl function
+       - EXISTS for marks
+    * documentation changes
+       - vi.ref converted to texinfo
+       - vsplit documented
+Changes since 1.81.3
+    * support for newer ncurses
+    * various other wide character related changes
+    * eliminate spurious cursor movements on split screens
+    * use of gtk-1.2 allowed again
+    * small fix to Motif front-end
diff --git a/dist/nvi/LICENSE b/dist/nvi/LICENSE
new file mode 100644 (file)
index 0000000..64de8c7
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * Id: LICENSE,v 8.17 2000/08/18 14:58:41 bostic Exp (Sleepycat) Date: 2000/08/18 14:58:41
+ */
+
+The following are the copyrights and redistribution conditions that apply
+to this copy of the Vi software.
+
+/*
+ * Copyright (c) 1991, 1992, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *  Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ *     Keith Bostic.  All rights reserved.
+ *  Copyright (c) 1999, 2000
+ *     Sven Verdoolaege.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
diff --git a/dist/nvi/README b/dist/nvi/README
new file mode 100644 (file)
index 0000000..5d83186
--- /dev/null
@@ -0,0 +1,104 @@
+#      Id: README,v 8.153 2001/04/30 09:31:12 skimo Exp (Berkeley) Date: 2001/04/30 09:31:12
+
+This is version 1.81.6 (2007-11-18) of nex/nvi, a reimplementation of the ex/vi
+text editors originally distributed as part of the Fourth Berkeley
+Software Distribution (4BSD), by the University of California, Berkeley.
+
+The directory layout is as follows:
+
+    LICENSE ....... Copyright, use and redistribution information.
+    README ........ This file.
+    build.unix .... UNIX build directory.
+    catalog ....... Message catalogs; see catalog/README.
+    cl ............ Vi interface to the curses(3) library.
+    clib .......... C library replacement source code.
+    common ........ Code shared by ex and vi.
+    db ............ A stripped-down, replacement db(3) library.
+    dist .......... Various files used to build the vi distribution.
+    docs .......... Ex/vi documentation, both current and historic.
+    docs/README ... Documentation overview.
+    docs/edit ..... Edit: A tutorial.
+    docs/exref .... Ex Reference Manual -- Version 3.7.
+    docs/vi.man ... UNIX manual page for nex/nvi.
+    docs/vi.ref ... Nex/nvi reference manual.
+    docs/vitut .... An Introduction to Display Editing with Vi.
+    ex ............ Ex source code.
+    gtk ........... Vi gtk application.
+    include ....... Replacement include files.
+    ip ............ Library interface to vi: vi side.
+    ipc ........... Library interface to vi: application side.
+    motif ......... Vi motif application.
+    motif_l ....... Motif library interface to vi.
+    perl_api ...... Perl scripting language support.
+    perl_scripts .. Perl scripts.
+    regex ......... POSIX 1003.2 regular expression library.
+    tcl_api ....... Tcl scripting language support.
+    tcl_scripts ... Tcl scripts.
+    vi ............ Vi source code.
+
+To build DB for a UNIX platform:
+
+    cd build.unix
+    ../dist/configure
+    make
+
+To build multiple UNIX versions of DB in the same source tree, create
+a new directory then configure and build.
+
+    mkdir build.bsdos3.0
+    cd build.bsdos3.0
+    ../dist/configure
+    make
+
+For additional information about building DB for UNIX platforms, the
+description of possible configuration options and other information
+on DB configuration and build issues, see the file build.unix/README.
+       
+Bug fixes and updated versions of this software will periodically be made
+available.  For more information, as well as a list of Frequently Asked
+Questions, see:
+
+       http://www.bostic.com/vi
+
+To ask questions about vi, report vi problems, request notification of
+future releases and/or bug fixes, or to contact the authors for any
+reason, please send email to:
+
+       bostic@bostic.com
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+o This software is several years old and is the product of many folks' work.  
+
+       This software was originally derived from software contributed to
+       the University of California, Berkeley by Steve Kirkendall, the
+       author of the vi clone elvis.  Without his work, this work would
+       have been far more difficult.
+
+       IEEE POSIX 1003.2 style regular expression support is courtesy of
+       Henry Spencer, for which I am *very* grateful.
+
+       Elan Amir did the original 4BSD curses work that made it possible
+       to support a full-screen editor using curses.
+
+       George Neville-Neil added the Tcl interpreter, and the initial
+       interpreter design was his.
+
+       Sven Verdoolaege added the Perl interpreter.
+
+       Rob Mayoff provided the original Cscope support.
+
+o Many, many people suggested enhancements, and provided bug reports and
+  testing, far too many to individually thank.
+
+o From the original vi acknowledgements, by William Joy and Mark Horton:
+
+       Bruce Englar encouraged the early development of this display
+       editor.  Peter Kessler helped bring sanity to version 2's
+       command layout.  Bill Joy wrote versions 1 and 2.0 through 2.7,
+       and created the framework that users see in the present editor.
+       Mark Horton added macros and other features and made the editor
+       work on a large number of terminals and Unix systems.
+
+o And...
+       The financial support of UUNET Communications Services is gratefully
+       acknowledged.
diff --git a/dist/nvi/README.1st b/dist/nvi/README.1st
new file mode 100644 (file)
index 0000000..671c1bc
--- /dev/null
@@ -0,0 +1,17 @@
+This is a development version of nvi.
+Use at your own risk.
+
+Please do not contact the original authors about bugs you
+find in this version. Contact skimo-vi@kotnet.org instead.
+
+There is no guarantee that anything in this version will be
+available in upcoming stable releases.
+
+New versions will be made available on 
+http://www.kotnet.org/~skimo/nvi
+
+As always this software comes with absolutely NO WARRANTY.
+
+Now read the original README file.
+
+Sven Verdoolaege
diff --git a/dist/nvi/README.DB3 b/dist/nvi/README.DB3
new file mode 100644 (file)
index 0000000..58b4a62
--- /dev/null
@@ -0,0 +1,22 @@
+This version of vi requires DB3.1 or better, which can be found
+on http://www.sleepycat.com/ .
+
+Note that there is a small problem with DB 3.2 in that it will
+not let nvi read in a final line that doesn't end in a newline.
+This should be fixed in DB 3.3
+
+If your system library (such as glibc prior to version 2.2) uses a
+previous version of db (e.g. DB2) internally, you must configure with
+--enable-dynamic-loading to avoid symbols in the internally used db from
+being resolved against the newer db.
+
+If, on top of that, the vi binary is explicitly linked against that
+previous version of db (such as might happen if you enable the perl
+embedding), you should compile the 3.x version with all symbols internally
+resolved.  In case you use the Gnu linker (ld), this can be accomplished
+by passing it the -Bsymbolic option. You can do this by setting CC
+to e.g. "gcc -Wl,-Bsymbolic" prior to configuring db.
+See docs/ref/build_unix/flags.html in the db distribution for more
+information.
+
+skimo@kotnet.org
diff --git a/dist/nvi/TODO b/dist/nvi/TODO
new file mode 100644 (file)
index 0000000..f0667c4
--- /dev/null
@@ -0,0 +1,123 @@
+# Id: TODO,v 8.2 1997/04/12 15:53:31 bostic Exp (Berkeley) Date: 1997/04/12 15:53:31
+
+========================================================================
+GENERAL
+========================================================================
+2.0:   Open mode is not yet implemented.
+
+
+========================================================================
+DB
+========================================================================
+1.N    When nvi edits files that don't have trailing newlines, it appends
+       one, regardless.  This is required, by default, from POSIX.2.
+
+1.N:   If you run out of space in the recovery directory, the recovery
+       file is left in place.
+
+2.0:   It's known that it's possible to sync the backing files in the
+       wrong manner, leaving backup files that aren't recoverable.  This
+       is going to be left alone until we have a logging version of DB,
+       which will hopefully fix this (or at least make it possible to
+       easily do so).
+
+========================================================================
+VI
+========================================================================
+1.N:   Make the search pattern and command history (what the '.' command
+       executes) remembered between windows, or configurable so that it
+       is.
+
+1.N:   Change the screen scrolling to not eat user characters...  i.e.
+       g/pattern/foo should not eat already entered chars.
+
+1.N:   The vi main command loop should use the general-purpose overflow
+       and underflow routines.  In addition, the vi command loop uses
+       unsigned longs -- should probably be fixed as a 32-bit unsigned
+       type, and then check to make sure it's never used as as variable
+       type again.
+
+1.N:   Should "view" set a lock on the file?
+
+1.N:   Should "view" copy the file (or even open a recovery file)?
+
+1.N:   The strings found by searches should be highlighted until the next
+       character is entered.
+
+1.N:   Display a split vi screen for the :help command.
+
+1.N:   When getting a key for a continue screen, we should always read from
+       the terminal, not from a mapped key.
+
+1.N:   The sentence, paragraph and section movement commands don't match
+       historic practice in some boundary cases.  This should be left
+       alone until POSIX 1003.2 makes up its mind.
+
+1.N:   The vs_sm_fill routine should scroll if possible, not always redraw.
+
+1.N:   Think about setting a dirty/inuse bits on the lines of the SMAP
+       structure.  That way the message routines could steal lines and
+       refresh would continue to work, because it would know not to touch
+       the lines that were in use.
+
+========================================================================
+EX
+========================================================================
+2.0:   ^C isn't passed to the shell in the script windows as an interrupt
+       character.
+
+2.0:   It would be nice to inverse video the replaced text during
+       interactive substitute.
+
+2.0:   The :args command should put the current file name out in reverse
+       video.  This isn't going to be easy, currently only full lines can
+       be in reverse video, not just parts.
+
+========================================================================
+CURSES
+========================================================================
+1.N    In single-line screens, have to press 'q' twice when quitting out
+       of  a ":set all" display.
+
+========================================================================
+MOTIF/IPC
+========================================================================
+1.N:   We currently permit the user to change the lines, columns and term
+       edit options.  Shouldn't that be illegal in a window interface?
+
+========================================================================
+REDESIGN
+========================================================================
+2.0:   There's a serious problem with error returns -- we need to separate
+       command failure from fatal error, consistently, over the entire source
+       tree.  We need to rework all of vi to have three return values:
+               0: success
+               1: vi error, continue
+               2: fatal error, die
+       Right now we don't recognize fatal errors for what they are.
+
+2.0:   The complete list of POSIX.1 calls that can return EINTR are:
+               wait, waitpid, sleep, dup2, close, read, write,
+               fcntl(SETLCKW) tcsetattr, tcdrain
+       The problem is that technically, any system/library call can
+       return EINTR, so, while nvi blocks (most of?) the obvious ones,
+       someone may have to do a complete pass and block signals
+       everywhere.
+
+2.0:   The options hardtabs, lisp, optimize, redraw, and slowopen
+       are recognized, but not implemented.
+
+
+2.0:   Field editing shouldn't be hard to add to nvi:
+
+       Field editing file template:
+       version #
+       field # row/column start        row/column stop
+       label   field #                 Label string
+       re      field #                 Matching re string.
+       field # row/column start        row/column stop
+       label   field #                 Label string
+       re      field #                 Matching re string.
+
+       <tab> moves to the next field
+       <bs> in column 0 moves to the previous field
diff --git a/dist/nvi/build.unix/README b/dist/nvi/build.unix/README
new file mode 100644 (file)
index 0000000..eb52814
--- /dev/null
@@ -0,0 +1,362 @@
+#      Id: README,v 8.29 2001/05/13 20:52:36 skimo Exp (Berkeley) Date: 2001/05/13 20:52:36
+
+Nvi uses the GNU autoconf program for configuration and compilation.  You
+should enter:
+
+       ../dist/configure
+       make
+
+and nvi will configure the system and build one or two binaries:  nvi and
+tknvi.  You can use any path to the configure script, e.g., to build for
+an x86 architecture, I suggest that you do:
+
+       mkdir build.x86
+       cd build.x86
+       ../dist/configure
+       make
+
+There are options that you can specify to the configure command.  See
+the next section for a description of these options.
+
+If you want to rebuild or reconfigure nvi, for example, because you change
+your mind as to the curses library that you want to use, create a new
+directory and reconfigure it using "configure" and whatever options you
+choose, don't try to selectively edit the files.
+
+By default, nvi is installed as "vi", with hard links to "ex" and "view".
+To install them using different names, use the configure program options.
+For example, to install them as "nvi", "nex" and "nview", use:
+
+       configure --program-prefix=n
+
+See the section below on installation for details.
+
+Note, if you're building nvi on a LynxOS system, you should read the
+README.LynxOS file in this directory for additional build instructions
+that are specific to that operating system.
+
+If you have trouble with this procedure, send email to the addresses
+listed in ../README.  In that email, please provide a complete script
+of the output for all of the above commands that you entered.
+
+=-=-=-=-=-=-=
+NVI'S OPTIONS TO THE CONFIGURE PROGRAM
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+There are many options that you can enter to the configuration program.
+To see a complete list of the options, enter "configure --help".  Only
+a few of them are nvi specific.  These options are as follows:
+
+  --disable-re            DON'T use the nvi-provided RE routines.
+  --enable-debug          Build a debugging version.
+  --enable-perlinterp     Include a Perl interpreter in vi.
+  --enable-tclinterp      Include a Tk/Tcl interpreter in vi.
+  --enable-gtk           Build a gtk front-end.
+  --enable-motif         Build a motif front-end.
+  --enable-threads       Turn on thread support.
+  --enable-widechar      Build a wide character aware vi (experimental).
+  --with-curses=DIR       Path to curses installation.
+  --with-db3=db3prefix    Path to db3 installation.
+  --enable-dynamic-loading Load DB 3 dynamically.
+
+disable-re:
+       By default, nvi loads its own versions of the POSIX 1003.2 Regular
+       Expression routines (which are Henry Spencer's implementation).
+       If your C library contains an implementation of the POSIX 1003.2
+       RE routines (note, this is NOT the same as the historic UNIX RE
+       routines), and you want to use them instead, enter:
+
+       --disable-re
+
+       as an argument to configure, and the RE routines will be taken
+       from whatever libraries you load.  Please ensure that your RE
+       routines implement Henry Spencer's extensions for doing vi-style
+       "word" searches.
+
+enable-debug:
+       If you want to build nvi with no optimization (i.e. without -O
+       as a compiler flag), with -g as a compiler flag, and with DEBUG
+       defined during compilation, enter:
+
+       --enable-debug
+
+       as an argument to configure.
+
+enable-perlinterp:
+       If you have the Perl 5 libraries and you want to compile in the
+       Perl interpreter, enter:
+
+       --enable-perlinterp
+
+       as an argument to configure.  (Note: this is NOT possible with
+       Perl 4, or even with Perl 5 versions earlier than 5.002.)
+
+enable-tclinterp:
+       If you have the Tk/Tcl libraries and you want to compile in the
+       Tcl/Tk interpreter, enter:
+
+       --enable-tclinterp
+
+       as an argument to configure.  If your Tk/Tcl include files and
+       libraries aren't in the standard library and include locations,
+       see the next section of this README file for more information.
+
+enable-gtk:
+       If you have the Gtk libraries and you want to build the Gtk
+       nvi front-end, enter:
+
+       --enable-gtk
+
+       as an argument to configure.  If your Gtk include files and
+       libraries aren't in the standard library and include locations,
+       see the next section of this README file for more information.
+       See also the enable-threads option.
+
+enable-motif:
+       If you have the Motif libraries and you want to build the Motif
+       nvi front-end, enter:
+
+       --enable-motif
+
+       as an argument to configure.  If your Motif include files and
+       libraries aren't in the standard library and include locations,
+       see the next section of this README file for more information.
+
+enable-threads:
+       If you want to be able to use multiple windows in the Gtk
+       front-end, you should specify this option.
+
+with-curses:
+       Specifies the path where curses is installed.
+
+with-db3:
+       Specifies the path where DB3 is installed.
+       See README.DB3 for more information about DB3.
+
+enable-dynamic-loading:
+       Dynamically load DB3 library.
+       See README.DB3 for more information about DB3.
+
+enable-widechar:
+       Enables support for wide characters.
+       Note that this is still rather experimental.
+
+       If you try this out on Solaris, you will want to point nvi
+       to the curses in /usr/xpg4/ which is CSI compliant.
+
+=-=-=-=-=-=-=
+ADDING OR CHANGING COMPILERS, OR COMPILE OR LOAD LINE FLAGS
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+If you want to use a specific compiler, specify the CC environment
+variable before running configure.  For example:
+
+       env CC=gcc configure
+
+Using anything other than the native compiler will almost certainly
+mean that you'll want to check the compile and load line flags, too.
+
+If you want to specify additional load line flags, specify the ADDLDFLAGS
+environment variable before running configure.  For example:
+
+       env ADDLDFLAGS="-Q" configure
+
+would specify the -Q flag in the load line when the nvi programs are
+loaded.
+
+If you don't want configure to use the default load line flags for the
+system, specify the LDFLAGS environment variable before running configure.
+For example:
+
+       env LDFLAGS="-32" configure
+
+will cause configure to set the load line flags to "-32", and not set
+them based on the current system.
+
+If you want to specify additional compile line flags, specify the
+ADDCPPFLAGS environment variable before running configure.  For example:
+
+       env ADDCPPFLAGS="-I../foo" configure
+
+would cause the compiler to be passed the -I../foo flag when compiling
+test programs during configuration as well as when building nvi object
+files.
+
+If you don't want configure to use the default compile line flags for the
+system, specify the CPPFLAGS environment variable before running configure.
+For example:
+
+       env CPPFLAGS="-I.." configure
+
+will cause configure to use "-I.." as the compile line flags instead of
+the default values.
+
+=-=-=-=-=-=-=
+ADDING LIBRARIES AND INCLUDE FILES
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+If the Tk/Tcl or any other include files or libraries are in non-standard
+places on your system, you will need to specify the directory path where
+they can be found.
+
+If you want to specify additional library paths, set the ADDLIBS environment
+variable before running configure.  For example:
+
+       env ADDLIBS="-L/a/b -L/e/f -ldb" configure
+
+would specify two additional directories to search for libraries, /a/b
+and /e/f, and one additional library to load, "db".
+
+If you want to specify additional include paths, specify the ADDCPPFLAGS
+environment variable before running configure.  For example:
+
+       env ADDCPPFLAGS="-I/usr/local/include" LIBS="-ldb" configure
+
+would search /usr/local/include for include files, as well as load the db
+library as described above.
+
+As a final example, let's say that you've downloaded ncurses from the net
+and you've built it in a directory named ncurses which is at the same
+level in the filesystem hierarchy as nvi.  You would enter something like:
+
+       env ADDCPPFLAGS="-I../../ncurses/include" \
+           ADDLIBS="-L../../ncurses/libraries" configure
+
+to cause nvi to look for the curses include files and the curses library
+in the ncurses environment.
+
+Notes:
+       Make sure that you prepend -L to any library directory names, and
+       that you prepend -I to any include file directory names!  Also,
+       make sure that you quote the paths as shown above, i.e. with
+       single or double quotes around the values you're specifying for
+       ADDCPPFLAGS and ADDLIBS.
+
+       =-=-=-=-=-=
+       You should NOT need to add any libraries or include files to load
+       the Perl5 interpreter.  The configure script will obtain that
+       information directly from the Perl5 program.  This means that the
+       configure script must be able to find perl in its path.  It looks
+       for "perl5" first, and then "perl".  If you're building a Perl
+       interpreter and neither is found, it's a fatal error.
+
+       =-=-=-=-=-=
+       You do not need to specify additional libraries to load Tk/Tcl,
+       Perl or curses, as the nvi configuration script adds the
+       appropriate libraries to the load line whenever you specify
+       --enable-tknvi or other Perl or Tk/Tcl related option, or build
+       the Tk/Tcl or curses version of nvi.  The library names that are
+       automatically loaded are as follows:
+
+       for Perl:       -lperl
+       for Tk/Tcl:     -ltk -ltcl -lm
+       for curses:     -lcurses
+
+       In addition, the configure script loads:
+
+               ... the X libraries when loading the Tk/Tcl libraries,
+                   if they exist.
+
+               ... the -ltermcap or -ltermlib libraries when loading
+                   any curses library, if they exist.
+
+       =-=-=-=-=-=
+       The env command is available on most systems, and simply sets one
+       or more environment variables before running a command.  If the
+       env command is not available to you, you can set the environment
+       variables in your shell before running configure.  For example,
+       in sh or ksh, you could do:
+
+               ADDLIBS="-L/a/b -L/e/f -ldb" configure
+
+       and in csh or tcsh, you could do:
+
+               setenv ADDLIBS "-L/a/b -L/e/f -ldb"
+               configure
+
+       See your shell manual page for further information.
+
+=-=-=-=-=-=-=
+INSTALLING NVI
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Nvi installs the following files into the following locations, with
+the following default values:
+
+Variables:             Default value:
+prefix                 /usr/local
+exec_prefix            $(prefix)
+bindir                 $(prefix)/bin
+datadir                        $(prefix)/share
+mandir                 $(prefix)/man
+
+File(s):               Default location
+----------------------------------------
+vi                     $(bindir)/vi
+vi.1                   $(mandir)/man1/vi.1
+vi.0                   $(mandir)/cat1/vi.0
+Perl scripts           $(datadir)/vi/perl/
+Tcl scripts            $(datadir)/vi/tcl/
+Message Catalogs       $(datadir)/vi/catalog/
+
+Notes:
+       There are two hard links to the vi program, named ex and view.
+       Similarly, there are two hard links to the unformatted vi manual
+       page, named ex.1 and view.1, and two hard links to the formatted
+       manual page, named ex.0 and view.0.  These links are created when
+       the program and man pages are installed.
+
+       If you want to install vi, ex, view and the man pages as nvi, nex,
+       nview, use the configure option --program-prefix=n.  Other, more
+       complex transformations are possible -- use configure --help to
+       see more options.
+
+       To move the entire installation tree somewhere besides /usr/local,
+       change the value of both "exec_prefix" and "prefix".  To move the
+       binaries to a different place, change the value of "bindir".
+       Similarly, to put the datafiles (the message catalogs, Perl and
+       Tcl scripts) or the man pages in a different place, change the
+       value of "datadir" or "mandir".  These values can be changed as
+       part of configuration:
+
+               configure --exec_prefix=/usr/contrib --prefix=/usr/share
+
+       or when doing the install itself:
+
+               make exec_prefix=/usr/contrib prefix=/usr/contrib install
+
+       The datafile directory (e.g., /usr/local/share/vi by default) is
+       completely removed and then recreated as part of the installation
+       process.
+
+=-=-=-=-=-=-=
+NVI AND THE CURSES LIBRARY
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The major portability problem for nvi is selecting a curses library.
+Unfortunately, it is common to find broken versions of curses -- the
+original System V curses was broken, resulting in all vendors whose
+implementations are derived from System V having broken implementations
+in turn.
+
+If you use the vendor's or other curses library, and you see any of the
+following symptoms:
+
+       + Core dumps in curses routines.
+       + Missing routines when compiling.
+       + Repainting the wrong characters on the screen.
+       + Displaying inverse video in the wrong places.
+       + Failure to reset your terminal to the correct modes on exit.
+
+you have a broken curses implementation, and you should reconfigure nvi
+to use another curses library.
+
+An alternative for your vendor's curses is ncurses, available from
+ftp://ftp.gnu.org/pub/gnu/ncurses/
+
+One final note.  If you see the following symptoms:
+
+       + Line-by-line screen repainting instead of scrolling.
+
+it usually means that your termcap or terminfo information is insufficient
+for the terminal.
diff --git a/dist/nvi/build.unix/README.LynxOS b/dist/nvi/build.unix/README.LynxOS
new file mode 100644 (file)
index 0000000..2cc68da
--- /dev/null
@@ -0,0 +1,320 @@
+README.LynxOS
+=============
+
+Written by Ronald F. Guilmette <rfg@monkeys.com>
+
+Last modified Wed Aug 14 23:10:07 PDT 1996
+------------------------------------------
+
+0. Introduction
+---------------
+
+This file describes how to build and install the Berkeley nvi editor for
+the LynxOS 2.4.0 operating system.
+
+LynxOS 2.4.0 is available for a variety of different hardware platforms, in
+particular, x86, m680x0, Sparc, and PowerPC.  I have successfully built nvi
+on all four of these flavors of LynxOS by following the procedures given in
+this file.
+
+Note that these procedures may not work on versions of LynxOS prior to 2.4.0.
+(As I understand it, a good deal of work went into making the 2.4.0 release
+more POSIX-compliant, and I have no idea what build glitches, if any, you
+might encounter if you try to build nvi on a pre-2.4.0 version of LynxOS.)
+
+There are basically four steps to configuring, building, and installing nvi
+on LynxOS, namely:
+
+       1.  Get setup to use the proper C compiler.
+       2.  Replace your installed `tr' program.
+       3.  Fix your system include files.
+       4.  Do a normal configure, build, and install of nvi.
+
+These steps are described in separate sections below.
+
+1.  Get Setup to Use the Proper C Compiler
+------------------------------------------
+
+The first step when building nvi on LynxOS is to set your $PATH environment
+variable properly so that the gcc 2.x compiler appears first on your path,
+prior to the older (and less robust) gcc 1.xx compiler (typically installed
+as /bin/gcc) and/or the old Lynx proprietary C compiler (typically installed
+as /bin/cc), both of which may also be present on your system.
+
+Note that for most operating systems, the configure script for nvi tries
+to use whatever compiler you have installed (and in your $PATH) as "cc",
+however in the special case of LynxOS, the configure script will auto-
+matically try to find a "gcc" program on your $PATH in preference to a
+compiler called "cc".  If the nvi configure script only find a compiler
+called "cc", that's OK.  It will still try to see if that is really just
+the GNU C compiler installed under the name "cc".
+
+Regardless of the name however (be it "gcc" or "cc") the first C compiler
+in your $PATH should be some _recent_ (i.e. 2.0 or later) version of the
+GNU C compiler... and the nvi configure script now checks that this is the
+case, and fails if it isn't.
+
+Oddly enough, LynxOS 2.4.0 (and some prior versions) shipped with as many
+as three different C compilers installed, so it is important to set your
+$PATH environment variable carfully in order to get the proper C compiler
+to appear first in your $PATH.  You want to avoid having either the /bin/gcc
+compiler or the /bin/cc compiler be the first C compiler in your $PATH.
+
+To make sure that the GNU C version 2.x compiler which was shipped with your
+LynxOS system appears first on your path, you will need to either set your
+$PATH variable (for sh/bash/ksh users) or your $path variable (for csh/tcsh
+users).  You can, of course, just do this at the shell command prompt, but
+it is probably better to actually edit this change into your .profile file
+(for sh/bash/ksh users) or into your .cshrc file (for csh/tcsh users).
+
+The pathname of the directory that contains the GNU C version 2.x compiler
+is (unfortunately) dependent upon the exact type of LynxOS system you have.
+
+For LynxOS 2.4.0 on x86 systems, gcc 2.x is located in:
+
+       /cygnus/94q4-lynxos-x86/bin
+
+For LynxOS 2.4.0 on m680x0 systems, gcc 2.x is located in:
+
+       /cygnus/94q4-lynxos-68k/bin
+
+For LynxOS 2.4.0 on Sparc systems, gcc 2.x is located in:
+
+       /cygnus/94q4-lynxos-usparc/bin
+
+For LynxOS 2.4.0 on PowerPC systems, gcc 2.x is located in:
+
+       /cygnus/95q2-lynxos-ppc/bin
+
+(Note also that these locations may change in LynxOS 2.5.x and beyond.)
+
+Anyway, it is imperative that you setup your $PATH environment variable
+(*before* you do the configure step for nvi) so that the GNU C version 2.x
+compiler appears in your $PATH before either the /bin/cc or /bin/gcc
+compilers (if present).  If you fail to do this, the configure step for
+nvi will fail, because the compiler script actually checks (now) that the
+compiler you are using (if your are on a LynxOS system) is gcc 2.0 or
+later.
+
+To make absolutely sure that you will be configuring and building nvi with
+the proper C compiler (i.e. the GNU C version 2.x compiler on your system)
+you should add the directory name listed above for your specific system type
+to your $PATH setting in your $HOME/.profile file.  (For csh/tcsh users, you
+will instead want to add the relevant directory name to the setting of your
+$path variable in your ~/.cshrc file.)  Once you have added the proper direc-
+tory name (from the list given above) to your $HOME/.profile file (or to your
+~/.cshrc file, if you are using csh or tcsh) you should log out completely
+and then log back into the system just to make sure your new $PATH/$path
+setting takes effect properly.
+
+When you finish making this adjustment to your $PATH (or $path), the most
+up-to-date version of gcc on your system should be available to you as the
+first `gcc' program on your $PATH.  You should verify that this is indeed the
+case simply by typing `gcc -v' and then checking the version number reported
+by the compiler.  It should say either "2.6-94q4" or (on PowerPC systems) it
+should say "2.6-95q2".  If you don't get these results, try again to set your
+$PATH (or $path) until you do.  You won't be able to build nvi until you are
+properly setup to use gcc version 2.0 or later.
+
+Performing the steps shown above will insure that your subsequent configura-
+tion and build steps for nvi will make use of the most up-to-date version of
+gcc that was shipped with your Lynx operating system.  (Note that the versions
+of gcc which are currently shipping with LynxOS 2.4.0 are also somewhat out-
+of-date themselves, but they are still quite a bit newer and more bug-free
+and ANSI conformant that those other two C compilers, /bin/cc and /bin/gcc,
+which also ship with LynxOS 2.4.0.)
+
+(Note:  At present, LynxOS version 2.4.0 is the latest officially released
+version of LynxOS, and all of the above information is accurate and correct
+for LynxOS 2.4.0 as of the time of this writing.  However it is rumored that
+future releases of LynxOS may provide a still newer version of gcc, and that
+it may be located in the /usr/bin directory.  Thus, if you are building nvi
+for some LynxOS version later than 2.4.0, you may wish to check and see if
+your system has a program called /usr/bin/gcc, and use that version of gcc,
+if available, rather than the one suggested above.)
+
+2.  Replace Your Installed `tr' Program
+---------------------------------------
+
+The `tr' program which comes bundled with LynxOS 2.4.0 (as /bin/tr) has a
+somewhat obscure bug which just happens to be tickled by almost all GNU
+`autoconf' generated `configure' scripts (including the one that nowadays
+comes bundled with nvi).  Using the stock /bin/tr program on LynxOS when
+executing such `configure' scripts _will_ cause these scripts to malfunction
+in various ways.  It is therefore imperative that you replace your LynxOS
+/bin/tr program with a properly working version of the `tr' command _before_
+you even try to configure nvi.  (You can tell if your `tr' program has the
+bug by executng the command "echo ab- | tr ab- ABC".  If this yields the
+string "Ab-" then you have the bug.  If it yields "ABC" then you don't.)
+
+You can obtain sources for a working version of the `tr' command as part of
+the GNU `textutils' package (the latest version of which, at the time of this
+writing, is 1.19).  The GNU textutils package is available for downloading
+from prep.ai.mit.edu in the pub/gnu directory.  Look for the file named
+textutils-1.19.tar.gz, or an even more recent version of textutils, if one
+is available.  Fetch it, gunzip it, untar it, and follow the directions in
+the INSTALL file included in the tar file to build and install the entire
+textutils set of utility programs (which includes a working `tr' program).
+Then just make sure that the GNU version of `tr' appears on your $PATH
+_before_ the LynxOS version of `tr' (i.e. /bin/tr).  Be sure to do this
+step _before_ you start to configure nvi.
+
+When building the textutils set of programs, I suggest that you use the most
+up-to-date C compiler available on your system (as described above).  Also,
+note that it will be important for you to AVOID using the -O (optimize)
+compiler option when building the GNU textutils package, even if you are
+using the most up-to-date version of gcc which shipped with your system.
+If you try to use -O when building the textutils package on an x86 with
+the Cygnus 94q4 C compiler, you will end up with a `tr' program which will
+malfunction even worse than the one you are trying to replace!  If you use
+-O when building the textutils package on LynxOS on the PowerPC (using the
+Cygnus 95q2 C compiler) you will just get yourself a compiler crash.  So
+just don't use -O when building textutils.  You can avoid using -O by in-
+voking make in the textutils directory as follows:
+
+       make CFLAGS="-g"
+
+(Note:  At present, LynxOS version 2.4.0 is the latest officially released
+version of LynxOS, and all of the above information is accurate and correct
+for LynxOS 2.4.0 as of the time of this writing.  However it is rumored that
+the bug in the /bin/tr program will be fixed in future releases of LynxOS,
+so if you have a version of LynxOS later than 2.4.0, you may wish to check
+and see if your /bin/tr program even has the problematic bug before bothering
+with all of this.)
+
+
+3.  Fix Your System Include Files
+---------------------------------
+
+If you are building nvi on a PowerPC system, it is also important that you
+apply the patches given at the end of this file to your /usr/include files.
+(Note that you will have to be root in order to do this.)  Two of the patches
+included below fix a pair of serious bugs in the /usr/include/stdarg.h file
+on the PowerPC, and you really _do_ want to have these bugs fixed anyway,
+because without these fixes, anything that you compile which uses <stdarg.h>
+will very likely malfunction at run-time.
+
+Regardless of which LynxOS platform you are using (i.e. x86, PowerPC, Sparc,
+or m680x0) you may want to apply all of the system include files patches that
+are included below anyway.  Doing so will clean up a few minor problems with
+the relevant system include files (i.e. <stdarg.h>, <ioctl.h>, and <wait.h>)
+and this step will also prevent a few warnings which you would otherwise get
+during the build of nvi.
+
+You can apply all of the patches given at the end of this file simply by
+doing the following:
+
+       su root
+       cd /usr/include
+       /bin/patch < this-file
+
+Where `this-file' is the actual full pathname of the file you are now reading,
+wherever it may reside on your own system.
+
+(Note:  At present, LynxOS version 2.4.0 is the latest officially released
+version of LynxOS, and all of the above information is accurate and correct
+for LynxOS 2.4.0 as of the time of this writing.  However it is rumored that
+future releases of LynxOS may incorporate some or all of the important system
+include file fixes provided below.  Thus, if you are building nvi for some
+LynxOS version later than 2.4.0, you should probably go ahead and try to
+apply the patches given below to your system include files, and then just
+don't worry about it if these patches seem to have already been applied.)
+
+
+4.  A Brief Note about Sendmail
+-------------------------------
+
+I should mention also that LynxOS does not normally ship with the `sendmail'
+mail transfer program installed, either under /usr/lib/ or anywhere else for
+that matter.  This isn't really a big problem, but nvi normally wants and
+expects to have a sendmail program available so that it can send users notifi-
+cations (by mail) whenever a partially edited file is preserved by the editor
+in response to a sudden system crash, a sudden system shutdown, or an unexpect-
+ed serial-line hangup.  You can configure and build nvi without any sendmail
+program installed on your system, but you will get warnings about its absence
+when you are doing the initial configure step prior to actually building nvi.
+If you want to have a fully-functional nvi which does send out notification
+messages (by mail) whenever partially edited files are preserved during a
+serial line hangup or system crash, then you should get the BSD sendmail
+sources (via ftp from ftp.cs.berkeley.edu), build and install sendmail, and
+then reconfigure, rebuild, and reinstall nvi.
+
+Please contact me at the E-mail address below if you experience any problems in
+building or using nvi on LynxOS.  I make no guarrantees, but I may be willing
+to try to help.
+
+Ron Guilmette
+Roseville, California
+<rfg@monkeys.com>
+August 14, 1996
+
+
+cut here for LynxOS 2.4.0 system include files patches
+-----------------------------------------------------------------------------
+*** wait.h     Fri Apr 26 10:02:45 1996
+--- wait.h     Sun May 19 05:36:50 1996
+***************
+*** 94,104 ****
+  /* Function prototypes */
+  #ifndef __LYNXOS
+- #ifdef _POSIX_SOURCE
+  extern pid_t wait            _AP((int *));
+  extern pid_t waitpid _AP((pid_t, int *, int));
+! #else
+! extern int wait              _AP((union wait *));
+! extern int waitpid   _AP((int, union wait *, int));
+! extern int wait3     _AP((union wait *, int, struct rusage *));
+  #endif
+  #endif /* !__LYNXOS */
+--- 94,101 ----
+  /* Function prototypes */
+  #ifndef __LYNXOS
+  extern pid_t wait            _AP((int *));
+  extern pid_t waitpid _AP((pid_t, int *, int));
+! #ifndef _POSIX_SOURCE
+! extern int wait3     _AP((int *, int, struct rusage *));
+  #endif
+  #endif /* !__LYNXOS */
+*** ioctl.h    Fri Apr 26 16:50:51 1996
+--- ioctl.h    Sat May 18 17:55:16 1996
+***************
+*** 572,576 ****
+  
+  #ifndef __LYNXOS
+! extern int ioctl     _AP((int, int, char *));
+  #endif
+  
+--- 572,576 ----
+  
+  #ifndef __LYNXOS
+! extern int ioctl     _AP((int, int, ...));
+  #endif
+  
+*** stdarg.h   Fri Apr 26 16:51:02 1996
+--- stdarg.h   Sat May 18 19:34:13 1996
+***************
+*** 88,92 ****
+       (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+  
+! #define va_start(AP, LASTARG)        (AP = ((char *) __builtin_next_arg ()))
+  
+  void va_end(va_list);                /* Defined in libgcc.a */
+--- 88,92 ----
+       (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+  
+! #define va_start(AP, LASTARG)        (AP = ((char *) __builtin_next_arg (LASTARG)))
+  
+  void va_end(va_list);                /* Defined in libgcc.a */
+***************
+*** 162,166 ****
+       (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+  
+! #define va_start(AP, LASTARG)        (AP = ((char *) __builtin_next_arg ()))
+  
+  void va_end(va_list);                /* Defined in libgcc.a */
+--- 162,166 ----
+       (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+  
+! #define va_start(AP, LASTARG)        (AP = ((char *) __builtin_next_arg (LASTARG)))
+  
+  void va_end(va_list);                /* Defined in libgcc.a */
diff --git a/dist/nvi/build.unix/README.Solaris b/dist/nvi/build.unix/README.Solaris
new file mode 100644 (file)
index 0000000..c2a7344
--- /dev/null
@@ -0,0 +1,10 @@
+There are some known problems with Solaris curses.
+Please give ncurses a try when you encounter a screen output problem.
+
+Apparently, the more recent Solaris compilers invoke the incremental linker,
+`ild', when the "-g" option is used and one or more "xxx.o" files are
+specified on the command line during the link phase.  Unfortunately, the
+executable produced is up to 3-4 times as big as an executable generated
+by the standard linker `ld'.
+You can bypass this by adding "-xildoff" to LDFLAGS or by
+setting CFLAGS (to something that does not contain "-g").
diff --git a/dist/nvi/catalog/Makefile b/dist/nvi/catalog/Makefile
new file mode 100644 (file)
index 0000000..2a3652d
--- /dev/null
@@ -0,0 +1,84 @@
+#      Id: Makefile,v 8.30 1996/11/27 11:59:09 bostic Exp (Berkeley) Date: 1996/11/27 11:59:09
+
+CAT=   dutch english french german ru_RU.KOI8-R spanish swedish
+FILES= ../cl/*.c ../common/*.c ../ex/*.c ../vi/*.c
+
+all: dump ${CAT}
+
+${CAT}: english.base
+       @echo "... $@";                                                 \
+       rm -f $@;                                                       \
+       sort -u $@.base |                                               \
+       awk '{                                                          \
+               if ($$1 == 1) {                                         \
+                       print "\nMESSAGE NUMBER 1 IS NOT LEGAL";        \
+                       exit 1;                                         \
+               }                                                       \
+               if (++nline > $$1) {                                    \
+                       print "DUPLICATE MESSAGE NUMBER " $$1;          \
+                       exit 1;                                         \
+               }                                                       \
+               for (; nline < $$1; ++nline)                            \
+                       print "";                                       \
+               print $0;                                               \
+       }' |                                                            \
+       sed -e '1s/^/VI_MESSAGE_CATALOG/'                               \
+           -e '/"/s/^[^"]*"//'                                         \
+           -e '1!s/"$$/X/' > $@;                                       \
+       chmod 444 $@;                                                   \
+       if grep DUPLICATE $@ > /dev/null; then                          \
+               grep DUPLICATE $@;                                      \
+       fi;                                                             \
+       if grep 'NOT LEGAL' $@ > /dev/null; then                        \
+               grep 'NOT LEGAL' $@;                                    \
+       fi
+
+CHK=   dutch.check english.check french.check german.check \
+       ru_RU.KOI8-R.check spanish.check swedish.check
+check: ${CHK}
+${CHK}: ${CAT}
+       @echo "... $@";                                                 \
+       f=`basename $@ .check`;                                         \
+       (echo "Unused message id's (this is okay):";                    \
+       awk '{                                                          \
+               while (++nline < $$1)                                   \
+                       printf "%03d\n", nline;                         \
+       }' < $$f.base;                                                  \
+       echo =========================;                                 \
+       echo "MISSING ERROR MESSAGES (Please add!):";                   \
+       awk '{print $$1}' < $$f.base | sort -u > __ck1;                 \
+       awk '{print $$1}' < english.base | sort -u > __ck2;             \
+       comm -13 __ck1 __ck2;                                           \
+       echo =========================;                                 \
+       echo "Extra error messages (just delete them):";                \
+       comm -23 __ck1 __ck2;                                           \
+       echo =========================;                                 \
+       echo "MESSAGES WITH THE SAME MESSAGE ID's (FIX!):";             \
+       for j in                                                        \
+           `sed '/^$$/d' < $$f.base | sort -u |                        \
+           awk '{print $$1}' | uniq -d`; do                            \
+               egrep $$j $$f.base;                                     \
+       done;                                                           \
+       echo =========================;                                 \
+       echo "Duplicate messages, both id and message (this is okay):"; \
+       sed '/^$$/d' < $$f.base | sort | uniq -c |                      \
+       awk '$$1 != 1 { print $$0 }' | sort -n;                         \
+       echo =========================;                                 \
+       echo "Duplicate messages, just message (this is okay):";        \
+       sed '/^$$/d' < $$f | sort | uniq -c |                           \
+       awk '$$1 != 1 { print $$0 }' | sort -n;                         \
+       echo =========================) > $@
+
+english.base: dump ${FILES} #Makefile
+       ./dump ${FILES} |\
+       sed -e '/|/!d' \
+           -e 's/|/ "/' \
+           -e 's/^"//' \
+           -e 's/\\"/"/g' |\
+       sort -n > $@
+
+dump: dump.c
+       ${CC} -O -o dump dump.c
+
+clean:
+       rm -f dump dump.o ${CAT} english.base *.check __ck1 __ck2
diff --git a/dist/nvi/catalog/README b/dist/nvi/catalog/README
new file mode 100644 (file)
index 0000000..a110db1
--- /dev/null
@@ -0,0 +1,166 @@
+#      Id: README,v 8.4 1994/11/22 09:52:04 bostic Exp (Berkeley) Date: 1994/11/22 09:52:04
+
+Generally, all non-system error and informational messages in nvi are
+catalog messages, i.e. they can be tailored to a specific langauge.
+Command strings, usage strings, system errors and other "known text"
+are not.  It would certainly be possible to internationalize all the
+text strings in nvi, but it's unclear that it's the right thing to do.
+
+First, there's no portable way to do message catalogs.  The System V
+scheme is a reasonable choice, but none of the 4BSD derived systems
+support it.  So, catalogs are completely implemented within nvi, and
+don't require any library support.
+
+Message catalogs in nvi are fairly simple.  Every catalog message
+consists of two parts -- an initial number followed by a pipe (`|')
+character, followed by the English text for the message.  For example:
+
+       msgq(sp, M_ERR, "001|This is an error message");
+
+would be a typical message.
+
+When the msgq() routine is called, if the user has specified a message
+catalog and the format string (the third argument) has a leading number,
+then it is converted to a record number, and that record is retrieved
+from the message catalog and used as a replacement format string.  If
+the record can't be retrieved for any reason, the English text is displayed
+instead.
+
+Each message format string MUST map into the English format string, i.e.
+it can't display more or different arguments than the English one.
+
+For example:
+
+       msgq(sp, M_ERR, "002|Error: %d %x", arg1, arg2);
+
+is a format string that displays two arguments.  It is possible, however,
+to reorder the arguments or to not display all of them.  The convention
+nvi uses is the System V printf(3) convention, i.e. "%[0-9]*$" is the name
+of a specific, numbered argument.  For example:
+
+       msgq(sp, M_ERR, "002|Error: %2$d %1$x", arg1, arg2);
+
+displays the arguments in reverse order.
+
+If the system supports this convention in its library printf routines
+(as specified by the test #define NL_ARGMAX), nvi uses those routines.
+Otherwise, there is some serious magic going on in common/msg.c to make
+this all work.
+
+Arguments to the msgq function are required to contain ONLY printable
+characters.  No further translation is done by the msgq routine before
+displaying the message on the screen.  For example, in the msgq call:
+
+       msgq(sp, M_ERR, "003|File: %s", file_name);
+
+"file_name" must contain only printable characters.  The routine
+msg_print() returns a printable version of a string in allocated
+memory.  For example:
+
+       char *p;
+
+       p = msg_print(sp, file_name);
+       msgq(sp, M_ERR, M("003", "File: %s"), p);
+       FREE_SPACE(sp, p, 0);
+
+makes sure that "file_name" is printable before calling the msgq
+routine.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The message catalogs themselves are maintained in two files.  The first
+is the "base file" which contains two fields, a record number and the
+message itself.  All base files are named using the convention
+"vi_<language>.base", e.g. the English one is "vi_english.base".  For
+example:
+
+       002 "Unable to create temporary file"
+       003 "Warning: %s is not a regular file"
+       004 "%s already locked, session is read-only"
+       005 "%s: remove"
+       006 "%s: close"
+       007 "%s: remove"
+       008 "%s: remove"
+       009 "Read-only file, not written; use ! to override"
+       010 "Read-only file, not written"
+
+are the first few lines of the current vi_english.base file.  Note that
+message #1 is missing -- the first message of each catalog is a special
+one, so that nvi can recognize message catalog files.  It's added by the
+Makefile script that creates the second version of the message catalog.
+
+The second file is the file used by nvi to access messages, and is a list
+of the messages, one per line:
+
+       VI_MESSAGE_CATALOG
+       Unable to create temporary fileX
+       Warning: %s is not a regular fileX
+       %s already locked, session is read-onlyX
+       %s: removeX
+       %s: closeX
+       %s: removeX
+       %s: removeX
+       Read-only file, not written; use ! to overrideX
+       Read-only file, not writtenX
+
+Note that all messages have had a trailing 'X' character appended.  This
+is to provide nvi a place to store a trailing nul for the message so that
+C library routines that expect one won't be disappointed.
+
+These files are named for their language, e.g. "vi_english".  The second
+files are automatically created from the first files.
+
+To create a new catalog for nvi:
+
+Copy the file vi_english.base to a file that you can modify , e.g.  "cp
+vi_english.base vi_german.base".  For each of the messages in the file,
+replace the message with the string that you want to use.  To find out
+what the arguments to a message are, I'm afraid you'll have to search
+the source code for the message number.  You can find them fairly quickly
+by doing:
+
+       cd ..; egrep '123\|' */*.[chys]
+
+I'm sorry that there's not an easier way, but I couldn't think of
+anything that wasn't a lot of work.
+
+If, for some reason, you don't have the file vi_english.base, or you
+have new sources for which you want to create a new base catalog, you
+can create it by running the command "make english" in the catalog
+directory.
+
+Once you've translated all of the strings, then add your catalog to the
+"CAT=" line of the Makefile, and run the command "make catalog".  This
+will create the second (and corresponding) file for each file named
+<language>.base.
+
+Don't worry about missing line numbers, i.e. base files that look like:
+
+       005     Message number 5.
+       007     Message number 7.
+
+This simply means that a message was deleted during the course of nvi's
+development.  It will be taken care of automatically when you create
+the second form of the file.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+If you add new messages to the nvi sources, you can check your work by
+doing "make english; make check".  The "make check" target lists unused
+message numbers, duplicate message numbers, and duplicate messages.
+Unused message numbers are only useful if you are condensing messages.
+Duplicate message numbers are a serious problem and have to be fixed.
+Duplicate messages are only interesting if a message appears often enough
+that it's worth creating a routine so that the string is only need in
+a single place.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+To select a catalog when running nvi, set the "msgcat" option.  If the
+value of this option ends with a '/', it is treated as the name of a
+directory that contains a message catalog "vi_XXXX", where XXXX is the
+value of the LANG environmental variable, if it's set, or the value of
+the LC_MESSAGES environmental variable if it's not.  If neither of those
+environmental variables are set, or if the option doesn't end in a '/',
+the option is treated as the full path name of the message catalog to use.
+
+If any messages are missing from the catalog, the backup text (English)
+is used instead.
diff --git a/dist/nvi/catalog/dump.c b/dist/nvi/catalog/dump.c
new file mode 100644 (file)
index 0000000..114ff5a
--- /dev/null
@@ -0,0 +1,91 @@
+/*     $NetBSD: dump.c,v 1.2 2008/06/11 21:30:52 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+static char copyright[] =
+"%Z% Copyright (c) 1992, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "Id: dump.c,v 8.1 1994/08/31 13:27:37 bostic Exp (Berkeley) Date: 1994/08/31 13:27:37";
+#endif /* not lint */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+parse(fp)
+       FILE *fp;
+{
+       int ch, s1, s2, s3;
+
+#define        TESTD(s) {                                                      \
+       if ((s = getc(fp)) == EOF)                                      \
+               return;                                                 \
+       if (!isdigit(s))                                                \
+               continue;                                               \
+}
+#define        TESTP {                                                         \
+       if ((ch = getc(fp)) == EOF)                                     \
+               return;                                                 \
+       if (ch != '|')                                                  \
+               continue;                                               \
+}
+#define        MOVEC(t) {                                                      \
+       do {                                                            \
+               if ((ch = getc(fp)) == EOF)                             \
+                       return;                                         \
+       } while (ch != (t));                                            \
+}
+       for (;;) {
+               MOVEC('"');
+               TESTD(s1);
+               TESTD(s2);
+               TESTD(s3);
+               TESTP;
+               putchar('"');
+               putchar(s1);
+               putchar(s2);
+               putchar(s3);
+               putchar('|');
+               for (;;) {              /* dump to end quote. */
+                       if ((ch = getc(fp)) == EOF)
+                               return;
+                       putchar(ch);
+                       if (ch == '"')
+                               break;
+                       if (ch == '\\') {
+                               if ((ch = getc(fp)) == EOF)
+                                       return;
+                               putchar(ch);
+                       }
+               }
+               putchar('\n');
+       }
+}
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       FILE *fp;
+
+       for (; *argv != NULL; ++argv) {
+               if ((fp = fopen(*argv, "r")) == NULL) {
+                       perror(*argv);
+                       exit (1);
+               }
+               parse(fp);
+               (void)fclose(fp);
+       }
+       exit (0);
+}
diff --git a/dist/nvi/catalog/dutch.base b/dist/nvi/catalog/dutch.base
new file mode 100644 (file)
index 0000000..4886c91
--- /dev/null
@@ -0,0 +1,306 @@
+002 "regel te lang"
+003 "kan regel %lu niet verwijderen"
+004 "kan niet toevoegen aan regel %lu"
+005 "kan niet invoegen vooraan regel %lu"
+006 "kan regel %lu niet opslaan"
+007 "kan laatste regel niet lezen"
+008 "Fout: kan regel %lu niet vinden"
+009 "log bestand"
+010 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
+011 "geen wijzigingen om ongedaan te maken"
+012 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
+013 "Er vindt geen logging plaats, herhaling niet mogelijk"
+014 "geen wijzigingen om te herhalen"
+015 "%s/%d: schrijven naar log mislukt"
+016 "Vi's standaard invoer en uitvoer moeten aan een terminal gekoppeld zijn"
+017 "Merk %s: niet gezet"
+018 "Merk %s: de regel is verwijderd"
+019 "Merk %s: de cursor positie bestaat niet meer"
+020 "Fout: "
+021 "nieuw bestand"
+022 "naam veranderd"
+023 "gewijzigd"
+024 "ongewijzigd"
+025 "NIET BEVEILIGD"
+026 "niet schrijfbaar"
+027 "regel %lu uit %lu [%ld%%]"
+028 "leeg bestand"
+029 "regel %lu"
+030 "Het bestand %s is geen message catalog"
+031 "Niet in staat om de standaard %s optie in te stellen"
+032 "Gebruik: %s"
+033 "set: optie %s onbekend: 'set all' laat alle opties zien"
+034 "set: [no]%s optie kan geen waarde hebben"
+035 "set: %s optie moet een waarde hebben"
+036 "set: %s optie: %s"
+037 "set: %s optie: %s: getal is te groot"
+038 "set: %s optie: %s is een ongeldige waarde"
+039 "set: %s optie moet een waarde hebben"
+040 "Te weinig kolommen op het scherm, minder dan %d"
+041 "Aantal kolommen te groot, meer dan %d"
+042 "Te weinig regels op het scherm, minder dan %d"
+043 "Aantal regels te groot, meer dan %d"
+044 "De lisp optie is niet ondersteund"
+045 "messages niet uitgeschakeld: %s"
+046 "messages niet geactiveerd: %s"
+047 "set: de %s optie moet karakter paren bevatten"
+053 "De standaard buffer is leeg"
+054 "Buffer %s is leeg"
+055 "Bestanden met newlines in de naam kunnen niet hersteld worden"
+056 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
+057 "Bestand wordt gecopieerd voor herstel..."
+058 "Herstel mechanisme werkt niet: %s"
+059 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
+060 "Kon bestand niet veilig stellen: %s"
+061 "Bestand wordt gecopieerd voor herstel..."
+062 "Informatie met betrekking tot gebruiker nummer %u niet gevonden"
+063 "Kan herstel bestand niet beveiligen"
+064 "herstel buffer overgelopen"
+065 "herstel bestand"
+066 "%s: verminkt herstel bestand"
+067 "%s: verminkt herstel bestand"
+068 "U heeft geen bestand genaamd %s te herstellen"
+069 "U kan eerdere versies van dit bestand herstellen"
+070 "U kan nog meer bestanden herstellen"
+071 "kan geen email versturen: %s"
+072 "Bestand leeg; niets om te doorzoeken"
+073 "Einde van het bestand bereikt zonder dat het patroon gevonden is"
+074 "Geen vorig zoek patroon"
+075 "Patroon niet gevonden"
+076 "Begin van het bestand bereikt zonder dat het patroon gevonden is"
+077 "Zoek-operatie omgeslagen"
+078 "Bezig met zoeken..."
+079 "Geen niet-printbaar karakter gevonden"
+080 "Onbekend commando"
+082 "Commando niet beschikbaar in ex mode"
+083 "Aantal mag niet nul zijn"
+084 "%s: ongeldige regel aanduiding"
+085 "Interne fout in syntax tabel (%s: %s)"
+086 "Gebruik: %s"
+087 "%s: tijdelijke buffer niet vrijgegeven"
+088 "Vlag offset voor regel 1"
+089 "Vlag offset voorbij bestands einde"
+090 "bestand/scherm veranderd tijdens uitvoeren van @ in een blok"
+091 "bestand/scherm veranderd tijdens uitvoeren van globaal/v commando"
+092 "Ex commando mislukt: rest van commando(s) genegeerd"
+093 "Ex commando mislukt: gemappede toetsen genegeerd"
+094 "Het tweede adres is kleiner dan het eerste"
+095 "Geen merk naam opgegeven"
+096 "\\ niet gevolgd door / of ?"
+097 "Referentie aan een regel nummer kleiner dan 0"
+098 "Het %s commando is onbekend"
+099 "Adres waarde te groot"
+100 "Adres waarde te klein"
+101 "Ongeldige adres combinatie"
+102 "Ongeldig adres: slechts %lu regels in het bestand aanwezig"
+103 "Ongeldig adres: het bestand is leeg"
+104 "Het %s commando staat het adres 0 niet toe"
+105 "Geen afkortingen om weer te geven"
+106 "Afkortingen moeten eindigen met een "woord" letter"
+107 "Afkortingen mogen geen tabulaties of spaties bevatten"
+108 "Afkortingen mogen geen woord/niet-woord karakters mengen, behalve aan het einde"
+109 ""%s" is geen afkorting"
+110 "Vi commando mislukt: gemappede toetsen genegeerd"
+111 "Dit is het laatste bestand"
+112 "Dit is het eerste bestand"
+113 "Dit is het eerste bestand"
+114 "lijst met bestanden is leeg"
+115 "Geen voorgaand commando om "!" te vervangen"
+116 "Geen bestandsnaam voor %%"
+117 "Geen bestandsnaam voor #"
+118 "Fout: execl: %s"
+119 "I/O fout: %s"
+120 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+121 "Kan uw home directory niet vinden"
+122 "Nieuwe huidige directory: %s"
+123 "Geen cut buffers aanwezig"
+124 "Het %s commando kan niet gebruikt worden in een globaal of v commando"
+125 "%s/%s: niet gelezen: noch U noch root is de eigenaar"
+126 "%s/%s: niet gelezen: U bent niet de eigenaar"
+127 "%s/%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
+128 "%s: niet gelezen: noch U noch root is de eigenaar""
+129 "%s: niet gelezen: U bent niet de eigenaar"
+130 "%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
+131 "Geen volgende regel om samen te voegen"
+132 "Geen input map entries"
+133 "Geen command map entries"
+134 "Het %s karakter kan niet ge-remapped worden"
+135 ""%s" is niet gemapped"
+136 "Merk naam moet een enkel karakter zijn"
+137 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
+138 "Nieuw .exrc bestand: %s. "
+139 "doel regel ligt in het blok"
+140 "Het open commando vereist dat de open optie actief is"
+141 "Het open commando is nog niet ondersteund"
+142 "Kan dit bestand niet veilig stellen"
+143 "Bestand veilig gesteld"
+144 "%s resulteert in te veel bestandsnamen"
+145 "Alleen echte bestanden en named pipes kunnen gelezen worden"
+146 "%s: lees beveiliging niet beschikbaar"
+147 "Bezig met lezen..."
+148 "%s: %lu regels, %lu karakters"
+149 "Geen achtergrond schermen aanwezig"
+150 "Het script commando is alleen beschikbaar in vi mode"
+151 "Geen comando om uit te voeren"
+152 "shiftwidth optie op 0 gezet"
+153 "Count te groot"
+154 "Count te klein"
+155 "Reguliere expressie opgegeven; r vlag heeft geen betekenis"
+156 "De #, l en p vlaggen kunnen niet gecombineerd worden met de c vlag in vi mode"
+157 "Geen match gevonden"
+158 "Geen voorafgaande tag aanwezig"
+159 "Minder dan %s elementen op de tags stapel; gebruik :display t[ags]"
+160 "Geen bestand genaamd %s op de tags stapel; gebruik :display t[ags]"
+161 "Kies Enter om door te gaan: "
+162 "%s: tag niet gevonden"
+163 "%s: verminkte tag in %s"
+164 "%s: Het regel nummer van deze tag is voorbij het einde van het bestand"
+165 "De tags stapel is leeg"
+166 "%s: zoek patroon niet gevonden"
+167 "%d andere bestanden te wijzigen"
+168 "Buffer %s is leeg"
+169 "Bevestig wijziging? [n]"
+170 "Onderbroken"
+171 "Geen voorafgaande buffer om uit te voeren"
+172 "Geen vorige reguliere expressie"
+173 "Het %s commando vereist dat er een bestand geladen is"
+174 "Gebruik: %s"
+175 "Het visual commando vereist dat de open optie actief is"
+177 "Leeg bestand"
+178 "Geen voorafgaand F, f, T of t zoek commando"
+179 "%s niet gevonden"
+180 "Geen voorafgaand bestand te bewerken"
+181 "Cursor niet op een getal"
+182 "Getal wordt te groot"
+183 "Getal wordt te klein"
+184 "Geen overeenkomstig karakter op deze regel"
+185 "Overeenkomstig karakter niet gevonden"
+186 "Geen karakters te vervangen"
+187 "Geen ander scherm aanwezig"
+188 "Karakters achter het zoek patroon, de regel offset, en/of het z commando"
+189 "Geen voorafgaand zoek patroon"
+190 "Zoekopdracht na omslag teruggekeerd op originele positie"
+191 "Afkorting overschrijdt expansie limiet: karakters genegeerd"
+192 "Ongeldig karakter; quote to enter"
+193 "Reeds aan het begin van de invoer"
+194 "Niet meer karakters te verwijderen"
+195 "Verplaatsing voorbij het einde van het bestand"
+196 "Verplaatsing voorbij het einde van de regel"
+197 "Cursor niet verplaatst"
+198 "Reeds aan het begin van het bestand"
+199 "Verplaatsing voorbij het begin van het bestand"
+200 "Reeds in de eerste kolom"
+201 "Buffers moeten voor het commando opgegeven worden"
+202 "Reeds bij het einde van het bestand"
+203 "Reeds bij het einde van de regel"
+204 "%s is geen vi commando"
+205 "Gebruik: %s"
+206 "Geen karakters te verwijderen"
+207 "Het Q commando vereist de ex terminal interface"
+208 "Geen commando om te herhalen"
+209 "Het bestand is leeg"
+210 "%s mag niet gebruikt worden als een verplaatsings commando"
+211 "Al in commando mode"
+212 "Cursor niet in een woord"
+214 "Windows optie waarde is te groot, maximum is %u"
+215 "Toevoegen"
+216 "Veranderen"
+217 "Commando"
+218 "Invoegen"
+219 "Vervangen"
+220 "Verplaatsing voorbij het eind van het scherm"
+221 "Verplaatsing voorbij het begin van het scherm"
+222 "Scherm moet meer dan %d regels hebben om het te kunnen splitsen"
+223 "Er zijn geen achtergrond schermen"
+224 "Er is geen achtergrond scherm waarin U bestand %s aan het bewerken bent"
+225 "U kan uw enige scherm niet in de achtergrond zetten"
+226 "Het scherm kan slechts verkleind worden tot %d regels"
+227 "Het scherm kan niet kleiner"
+228 "Het scherm kan niet groter"
+230 "Dit scherm kan niet gesuspend worden"
+231 "Onderbroken: gemappede toetsen genegeerd"
+232 "vi: tijdelijke buffer niet vrijgegeven"
+233 "Deze terminal heeft geen %s toets"
+234 "Er kan slechts een buffer opgegeven worden"
+235 "Getal groter dan %lu"
+236 "Onderbroken"
+237 "Aanmaken van tijdelijk bestand is mislukt"
+238 "Waarschuwing: %s is geen regulier bestand"
+239 "%s is al geopend, bestand is in deze sessie niet schrijfbaar"
+240 "%s: verwijdering mislukt"
+241 "%s: sluiting mislukt"
+242 "%s: verwijdering mislukt"
+243 "%s: verwijdering mislukt"
+244 "Bestand niet schrijfbaar, niet weggeschreven; gebruik ! om het te forceren"
+245 "Bestand niet schrijfbaar, niet weggeschreven"
+246 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
+247 "%s bestaat al, niet weggeschreven"
+248 "Gebruik ! om een incompleet bestand weg te schrijven"
+249 "Bestand incompleet, niet weggeschreven"
+250 "%s: bestand op disk nieuwer dan deze versie; gebruik ! om het te forceren"
+251 "%s: bestand op disk nieuwer dan deze versie"
+252 "%s: schrijf beveiliging niet beschikbaar"
+253 "Bezig met schrijven..."
+254 "%s: WAARSCHUWING: BESTAND INCOMPLEET"
+255 "Reeds op de eerste tag van deze groep"
+256 "%s: nieuw bestand: %lu regels, %lu karakters"
+257 "%s: %lu regels, %lu karakters"
+258 "%s resulteert in te veel bestandsnamen"
+259 "%s: geen normaal bestand"
+260 "%s: U bent niet de eigenaar"
+261 "%s: kan gewijzigd worden door andere gebruikers"
+262 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+263 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik :edit! om het te forceren"
+264 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+265 "Tijdelijk bestand; exit negeert wijzigingen"
+266 "Bestand niet schrijfbaar, wijzigingen niet automatisch weggeschreven"
+267 "log opnieuw gestart"
+268 "Bevestig? [ynq]"
+269 "Druk op een toets om door te gaan: "
+270 "Druk op een toets om door te gaan [: voor meer ex commandos]: "
+271 "Druk op een toets om door te gaan [q om te stoppen]: "
+272 "Deze vorm van %s vereist de ex terminal interface"
+273 "Entering ex input mode."
+274 "Commando mislukt, nog geen bestand geladen."
+275 " doorgaan?"
+276 "Onverwacht character event"
+277 "Onverwacht end-of-file event"
+278 "Geen match gevonden voor dit patroon"
+279 "Onverwacht interrupt event"
+280 "Onverwacht quit event"
+281 "Onverwacht repaint event"
+282 "Reeds op de laatste tag van deze groep"
+283 "Het %s command vereist de ex terminal interface"
+284 "Deze vorm van %s is niet ondersteund als de secure edit optie actief is"
+285 "Onverwacht string event"
+286 "Onverwacht timeout event"
+287 "Onverwacht write event"
+289 "Shell expansies zijn niet ondersteund als de secure edit optie actief is"
+290 "Het %s commando is niet ondersteund als de secure edit optie actief is"
+291 "set: %s mag niet uitgezet worden"
+292 "Scherm te klein."
+293 "toegevoegd"
+294 "gewijzigd"
+295 "verwijderd"
+296 "samengevoegd"
+297 "verplaatst"
+298 "verschoven"
+299 "gebufferd"
+300 "regel"
+301 "regels"
+302 "Vi was niet geladen met een Tcl interpreter"
+303 "Bestand gewijzigd sinds het de laatste keer weg is geschreven."
+304 "Shell expansie mislukt"
+305 "Geen %s edit optie opgegeven"
+306 "Vi was niet geladen met een Perl interpreter"
+307 "Geen ex commando om uit te voeren"
+308 "Kies <CR> om commando uit te voeren, :q om te stoppen"
+309 "Gebruik "cscope help" voor uitleg"
+310 "Nog geen cscope connectie aanwezig"
+311 "%s: onbekend zoek type: gebruik een van %s"
+312 "%d: onbekende cscope sessie"
+313 "set: de %s optie mag nooit aangezet worden"
+314 "set: de %s optie mag nooit op 0 gezet worden"
+315 "%s: toegevoegd: %lu regels, %lu karakters"
+316 "Onverwacht resize event"
+317 "%d bestanden te wijzigen"
diff --git a/dist/nvi/catalog/dutch.owner b/dist/nvi/catalog/dutch.owner
new file mode 100644 (file)
index 0000000..27f47d3
--- /dev/null
@@ -0,0 +1 @@
+J.G. Vons <Gert-Jan.Vons@ocegr.fr>
diff --git a/dist/nvi/catalog/english.owner b/dist/nvi/catalog/english.owner
new file mode 100644 (file)
index 0000000..034567d
--- /dev/null
@@ -0,0 +1 @@
+Keith Bostic <bostic@cs.berkeley.edu>
diff --git a/dist/nvi/catalog/french.base b/dist/nvi/catalog/french.base
new file mode 100644 (file)
index 0000000..7733947
--- /dev/null
@@ -0,0 +1,308 @@
+002 "Dépassement de longueur de ligne"
+003 "impossible de supprimer la ligne %lu"
+004 "impossible d'ajouter à la ligne %lu"
+005 "impossible d'insérer devant la ligne %lu"
+006 "impossible de stocker la ligne %lu"
+007 "impossible d'obtenir la dernière ligne"
+008 "Erreur : impossible de récupérer la ligne %lu"
+009 "Fichier journal"
+010 "Aucune journalisation n'étant effectuée, impossible d'annuler"
+011 "Aucune action à annuler"
+012 "Aucune journalisation n'étant effectuée, impossible d'annuler"
+013 "Aucune journalisation n'étant effectuée, reprise actualisée impossible"
+014 "Aucune action à refaire"
+015 "%s/%d : Erreur d'écriture de journal"
+016 "L'entrée et la sortie Vi standards doivent être un terminal"
+017 "Marque %s : non définie"
+018 "Marque %s : la ligne a été supprimée"
+019 "Marque %s : la position du curseur n'existe plus"
+020 "Erreur : "
+021 "nouveau fichier"
+022 "le nom a changé"
+023 "modifié"
+024 "non modifié"
+025 "DÉVERROUILLÉ"
+026 "lecture seule"
+027 "ligne %lu de %lu [%ld%%]"
+028 "fichier vide"
+029 "ligne %lu"
+030 "Ce fichier %s n'est pas un catalogue de messages"
+031 "Impossible de configurer option %s par défaut"
+032 "Utilisation : %s"
+033 "Définition : pas d'option %s : 'set all' donne toutes les valeurs optionnelles"
+034 "Définition : option [no]%s ne prend pas de valeur"
+035 "Définition : l'option %s n'est pas booléenne"
+036 "Définition : option %s : %s"
+037 "Définition : option %s : %s : Dépassement de valeur"
+038 "Définition : option %s : %s n'est pas un nombre valide"
+039 "Définition : l'option %s n'est pas booléenne"
+040 "Les colonnes de l'écran sont trop petites, inférieures à %d"
+041 "Les colonnes de l'écran sont trop grandes, supérieures à %d"
+042 "Les lignes de l'écran sont trop courtes, inférieures à %d"
+043 "Les lignes de l'écran sont trop longues, supérieures à %d"
+044 "L'option lisp n'est pas implémentée"
+045 "Les messages ne sont pas désactivés : %s"
+046 "Les messages ne sont pas activés : %s"
+047 "D\82finition : l'option de %s doit \88tre en groupe de deux caract\8ares"
+053 "Le tampon par défaut est vide"
+054 "Le tampon %s est vide"
+055 "Les fichiers dont le nom contient des caractères de saut de ligne sont irrécupérables"
+056 "Impossible de récupérer les modifications si la session échoue"
+057 "Copie en cours du fichier pour récupération..."
+058 "La préservation a échoué : %s"
+059 "Impossible de récupérer les modifications si la session échoue"
+060 "La sauvegarde du fichier a échoué : %s"
+061 "Copie en cours du fichier pour récupération..."
+062 "Les renseignements sur l'identité %u de l'utilisateur sont introuvables"
+063 "Impossible de verrouiller le fichier de récupération"
+064 "Débordement de tampon du fichier de récupération"
+065 "Fichier de récupération"
+066 "%s : Fichier de récupération malformé"
+067 "%s : Fichier de récupération malformé"
+068 "Aucun fichier nommé %s à récupérer, que vous puissiez lire"
+069 "Il existe des versions récupérables antérieures à ce fichier"
+070 "Vous avez d'autres fichiers à récupérer"
+071 "pas d'envoi d'email : %s"
+072 "Fichier vide, rien à rechercher"
+073 "Fin de fichier atteinte sans trouver le motif"
+074 "Pas de motif de recherche précédent"
+075 "Motif introuvable"
+076 "Début du fichier atteint sans trouver le motif"
+077 "La recherche est revenue à son point de départ"
+078 "Recherche en cours..."
+079 "Caractère non-imprimable introuvable"
+080 "Nom de commande inconnu"
+082 "%s : Commande non disponible en ex mode"
+083 "Le compteur ne peut être zéro"
+084 "%s : mauvaise spécification de ligne"
+085 "Erreur de tableau de syntaxe interne (%s: %s)"
+086 "Utilisation : %s"
+087 "%s : tampon temporaire non libéré"
+088 "Décalage de drapeau hors de la ligne 1"
+089 "Décalage de drapeau hors de la fin du fichier"
+090 "@ avec plage, en cours d'exécution quand le fichier/l'écran a changé"
+091 "Commande Global/v en cours d'exécution quand le fichier/l'écran a changé"
+092 "La commande ex a échoué : commandes en attente abandonnées"
+093 "La commande ex a échoué : les touches affectées sont abandonnées"
+094 "La deuxième adresse est plus petite que la première"
+095 "Aucun nom de marque fourni"
+096 "\\ non suivi par / ou ?"
+097 "Référence à un numéro de ligne inférieure à 0"
+098 "La commande %s est inconnue"
+099 "Dépassement de la valeur adresse"
+100 "Dépassement négatif de la valeur adresse"
+101 "Combinaison d'adresse non valide"
+102 "Adresse non valide : il n'y a que %lu lignes dans ce fichier"
+103 "Adresse non valide : le fichier est vide"
+104 "La commande %s ne permet pas une adresse de 0"
+105 "Pas d'abréviations à afficher"
+106 "Les abréviations doivent finir par un caractère"mot"
+107 "Les abréviations ne peuvent pas contenir de tabulations ni d'espaces"
+108 "Les abréviations ne peuvent pas contenir un mélange de caractères mot/non-mot, sauf à la fin"
+109 ""%s" n'est pas une abréviation"
+110 "La commande Vi a échoué : Les touches affectées ont été abandonnées"
+111 "Plus de fichiers à éditer"
+112 "Pas de fichiers précédents à éditer"
+113 "Pas de fichiers précédents à rembobiner"
+114 "Pas de liste de fichiers à afficher"
+115 "Pas de commande précédente à remplacer"!""
+116 "Pas de nom de fichier à substituer à %%"
+117 "Pas de nom de fichier à substituer à #"
+118 "Erreur : execl : %s"
+119 "Erreur E/S : %s"
+120 "Fichier modifié depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser"
+121 "Impossible de trouver l'emplacement du répertoire d'origine"
+122 "Nouveau répertoire en cours : %s"
+123 "Pas de tampon de coupure à afficher"
+124 "La commande %s ne peut pas être utilisée à l'intérieur d'une commande globale ou commande v"
+125 "%s/%s : échec de source : ni vous ni le super-utilisateur n'êtes les propriétaires "
+126 "%s/%s : échec de source : vous n'êtes pas le propriétaire"
+127 "%s/%s : échec de source : peut être écrit par un utilisateur autre que le propriétaire"
+128 "%s : échec de source : ni vous ni le super-utilisateur n'êtes les propriétaires"
+129 "%s : échec de source : vous n'êtes pas le propriétaire"
+130 "%s : échec de source : peut être écrit par un utilisateur autre que le propriétaire"
+131 "Pas de lignes suivantes à joindre"
+132 "Pas d'entrées de mappage d'entrée"
+133 "Pas d'entrées de mappage de commandes"
+134 "Le caractère %s ne peut pas être remappé"
+135 ""%s" n'est pas actuellement mappé"
+136 "Les noms de marque ne doivent avoir qu'un caractère"
+137 "%s existe, non enregistré; utiliser ! pour outrepasser"
+138 "Nouveau fichier exrc : %s"
+139 "La ligne de destination est à l'intérieur de la plage à déplacer"
+140 "La commande ouverte nécessite que l'option ouverte soit définie"
+141 "La commande ouverte n'est pas encore implémentée"
+142 "La préservation de ce fichier est impossible"
+143 "Fichier préservé"
+144 "%s: étendu dans trop de noms de fichiers"
+145 "Vous ne pouvez lire que les fichiers standards et les canaux de transmission nommés"
+146 "%s: Interdiction de lecture non disponible"
+147 "Lecture en cours..."
+148 "%s: %lu lignes, %lu caractères"
+149 "Pas d'écrans d'arrière-plan à afficher"
+150 "La commande script n'est disponible qu'en mode vi"
+151 "Pas de commande à exécuter"
+152 "Option de largeur de décalage définie sur 0"
+153 "Compter dépassement"
+154 "Compter dépassement négatif"
+155 "Expression standard spécifiée; drapeau r superflu"
+156 "Vous ne pouvez pas en mode vi, combiner les drapeaux #, l et p avec le drapeau c"
+157 "Aucune correspondance trouvée"
+158 "Aucune marque précédente entrée"
+159 "Moins de %s entrées dans la pile de marques ; utilisez t[ags]"
+160 "Pas de fichier %s vers lequel retourner dans la pile de marques ; utiliser : affichage t[ags]"
+161 "Appuyez sur Entrée pour continuer :"
+162 "%s : marque introuvable"
+163 "%s : marque corrompue en %s"
+164 "%s : le numéro de ligne de la marque dépasse la fin du fichier"
+165 "La pile de marques est vide"
+166 "%s : motif de recherche introuvable"
+167 "%d fichiers supplémentaires à éditer"
+168 "Le tampon %s est vide
+169 "Confirmer les changements ? [n]"
+170 "Interrompu"
+171 "Pas de tampon précédent à exécuter"
+172 "Pas d'expression standard précédente"
+173 "La commande %s nécessite qu'un fichier ait déjà été lu en mémoire"
+174 "Utilisation : %s"
+175 "La commande visual nécessite que l'option open soit définie"
+177 "Fichier vide"
+178 "Pas de recherche précédente F, f, T ou t"
+179 "%s introuvable"
+180 "Pas de fichier précédent à éditer"
+181 "Le curseur n'est pas dans un nombre"
+182 "Le nombre obtenu est trop grand"
+183 "Le nombre obtenu est trop petit"
+184 "Pas de correspondance de caractère sur cette ligne"
+185 "Caractère correspondant introuvable"
+186 "Pas de caractères à remplacer"
+187 "Pas d'autre écran vers lequel basculer"
+188 "Caractères après la chaîne de recherche, décalage de ligne et/ou commande z"
+189 "Pas de motif de recherche précédent"
+190 "La recherche est revenue à son point de départ"
+191 "L'abréviation a dépassé la limite de l'expansion : caractères abandonnés"
+192 "Caractère non valide ; guillemet pour saisir"
+193 "Déjà au début de l'insertion"
+194 "Plus de caractères à effacer"
+195 "Déplacement hors de fin de fichier"
+196 "Déplacement hors de fin de ligne"
+197 "Aucun mouvement de curseur n'a été effectué"
+198 "Déjà au début du fichier"
+199 "Déplacement hors du début du fichier"
+200 "Déjà dans la première colonne"
+201 "Les tampons doivent être spécifiés avant la commande"
+202 "Déjà à la fin du fichier"
+203 "Déjà à la fin de la ligne"
+204 "%s n'est pas une commande vi"
+205 "Utilisation : %s"
+206 "Pas de caractères à supprimer"
+207 "La commande Q nécessite une interface terminal ex"
+208 "Pas de commande à répéter"
+209 "Le fichier est vide"
+209 "Le fichier est vide"
+210 "Vous ne pouvez pas utiliser %s comme commande de déplacement"
+211 "Déjà en mode commande"
+212 "Le curseur n'est pas dans un mot"
+214 "Valeur optionnelle de fenêtre trop grande, maximum est %u"
+215 "Ajouter"
+216 "Changer"
+217 "Commande"
+218 "Insérer"
+219 "Remplacer"
+220 "Déplacement hors de la fin d'écran"
+221 "Déplacement hors du début d'écran"
+222 "L'écran doit être supérieur à %d lignes pour se fractionner"
+223 "Il n'y a pas d'écran d'arrière-plan"
+224 "Il n'y a pas d'écran d'arrière-plan qui édite un fichier nommé %s"
+225 "Vous ne pouvez pas mettre à l'arrière-plan votre seul écran affiché"
+226 "L'écran ne peut être réduit qu'à %d rangs"
+227 "L'écran n'est pas auto-réductible"
+228 "L'écran n'est pas auto-extensible"
+230 "Vous ne pouvez pas mettre cet écran en attente"
+231 "Interrompu : les touches affectées ont été abandonnées"
+232 "vi : le tampon temporaire n' a pas été libéré"
+233 "Ce terminal n'a pas de touche %s"
+234 "Vous ne pouvez spécifier qu'un seul tampon"
+235 "Nombre supérieur à %lu"
+236 "Interrompu"
+237 "Impossible de créer un fichier temporaire"
+238 "Avertissement : %s n'est pas un fichier standard"
+239 "%s déjà verrouillé, session en lecture seule"
+240 "%s: supprimer"
+241 "%s: fermer"
+242 "%s: supprimer"
+243 "%s: supprimer"
+244 "Fichier en lecture seule, non écrit, utiliser ! pour outrepasser"
+245 "Fichier en lecture seule, non écrit"
+246 "%s existe, non écrit; utiliser ! pour outrepasser"
+247 "%s existe, non écrit"
+248 "Fichier partiel, non écrit; utiliser ! pour outrepasser"
+249 "Fichier partiel, non écrit"
+250 "%s: fichier modifié plus récemment que cet exemplaire; utiliser ! pour outrepasser"
+251 "%s: fichier modifié plus récemment que cet exemplaire"
+252 "%s: interdiction d'écriture non disponible"
+253 "Ecriture en cours..."
+254 "%s: AVERTISSEMENT : FICHIER TRONQUÉ"
+255 "Première marque de ce groupe déjà atteinte"
+256 "%s: nouveau fichier : %lu lignes, %lu caractères"
+257 "%s: %lu lignes, %lu caractères"
+258 "%s étendue à trop de noms de fichiers"
+259 "%s: pas un fichier standard"
+260 "%s: ne vous appartient pas"
+261 "%s: accessible par un utilisateur autre que son propriétaire"
+262 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser "
+263 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser :edit! pour outrepasser"
+264 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser"
+265 "Fichier temporaire ; quitter annulera les modifications"
+266 "Fichier en lecture seule ; les modifications ne sont pas écrites automatiquement"
+267 "Journal redémarré"
+268 "confirmer ? [ynq]"
+269 "Appuyez sur n'importe quelle touche pour continuer : "
+270 "Appuyez sur n'importe quelle touche pour continuer [: pour entrer plus de commandes ex] : "
+271 "Appuyez sur n'importe quelle touche pour continuer [q pour Quitter]: "
+272 "Cette forme de %s nécessite l'interface de terminal ex"
+273 "Entrée de mode entrée ex."
+274 "La commande a échoué, aucun fichier n'a encore été lu."
+275 "cont?"
+276 "Evénement imprévu de caractère"
+277 "Evénement imprévu de fin-de-fichier"
+278 "Pas de correspondances pour cette requête"
+279 "Evénement imprévu d'interruption"
+280 "Evénement quitter imprévu"
+281 "Evénement imprévu de rafraîchissement"
+282 "La dernière marque de ce groupe a déjà été atteinte"
+283 "La commande %s nécessite l'interface de terminal ex"
+284 "Cette forme de %s n'est pas reconnue quand l'option d'édition protégée est activée"
+285 "Evénement imprévu de chaîne"
+286 "Evénement imprévu de délai imparti"
+287 "Evénement d'écriture imprévu"
+289 "Les expansions du shell ne sont pas reconnues quand l'option d'édition protégée est activée"
+290 "La commande %s n'est pas reconnue quand l'option d'édition protégée est activée"
+291 "Définition : l'option %s ne peut pas être désactivée"
+292 "Affichage trop petit."
+293 "ajouté"
+294 "changé"
+295 "supprimé"
+296 "joint"
+297 "déplacé"
+298 "décalé"
+299 "coupé"
+300 "ligne"
+301 "lignes"
+302 "Vi n'a pas été chargé avec un interprétateur Tcl"
+303 "Ficher modifié depuis le dernier enregistrement."
+304 "L'expansion du shell a échoué"
+304 "L'expansion du shell a échoué"
+305 "Pas d'option d'édition %s spécifiée"
+306 "Vi n'a pas été chargé avec un interprétateur Perl"
+307 "Pas de commande ex à exécuter"
+308 "Entrez <CR> pour exécuter une commande, :q pour quitter"
+309 "Utiliser "cscope help" pour obtenir de l'aide"
+310 "Aucune connexion cscope n'est lancée"
+311 "%s : type de recherche inconnu : utiliser un des %s"
+312 "%d : Il n'existe pas de telle session cscope"
+313 "Définition : l'option %s ne peut jamais être activée"
+314 "Définition : l'option %s ne peut jamais être définie sur 0"
+315 "%s: joints : %lu lignes, %lu caractères"
+316 "événement imprévu de redimensionnement"
+317 "%d fichiers à éditer"
diff --git a/dist/nvi/catalog/german.base b/dist/nvi/catalog/german.base
new file mode 100644 (file)
index 0000000..64b30bb
--- /dev/null
@@ -0,0 +1,306 @@
+002 "Zeilenlängen-Überlauf"
+003 "kann Zeile %lu nicht löschen"
+004 "kann an Zeile %lu nicht anfügen"
+005 "kann in Zeile %lu nicht einfügen"
+006 "kann Zeile %lu nicht speichern"
+007 "kann letzte Zeile nicht lesen"
+008 "Fehler: kann Zeile %lu nicht wiederherstellen"
+009 "Protokolldatei"
+010 "Keine Protokollierung aktiv, Rückgängigmachen nicht möglich"
+011 "Keine Änderungen rückgängig zu machen"
+012 "Keine Protokollierung aktiv, Rückgängigmachen nicht möglich"
+013 "Keine Protokollierung aktiv, Wiederholung von Änderungen nicht möglich"
+014 "Keine Änderungen zu wiederholen"
+015 "%s/%d: Protokollschreibfehler"
+016 "Vi's Standardein- und -ausgabe muß ein Terminal sein"
+017 "Marke %s: nicht gesetzt"
+018 "Marke %s: die Zeile wurde gelöscht"
+019 "Marke %s: Cursorposition existiert nicht mehr"
+020 "Fehler: "
+021 "neue Datei"
+022 "Name geändert"
+023 "geändert"
+024 "nicht geändert"
+025 "NICHT GELOCKT"
+026 "nur zum Lesen"
+027 "Zeile %lu von %lu [%ld%%]"
+028 "leere Datei"
+029 "Zeile %lu"
+030 "Die Datei %s ist kein Meldungskatalog"
+031 "Setzen der Voreinstellung für %s Option nicht möglich"
+032 "Benutzung: %s"
+033 "set: keine %s Option: 'set all' zeigt alle Optionen mit Werten an"
+034 "set: der [no]%s Option kann kein Wert zugewiesen werden"
+035 "set: %s ist keine Boolsche Option"
+036 "set: %s Option: %s"
+037 "set: %s Option: %s: Werte-Überlauf"
+038 "set: %s Option: %s ist eine ungültige Zahl"
+039 "set: %s ist keine Boolsche Option"
+040 "Bildschirm hat zu wenig Spalten, weniger als %d"
+041 "Bildschirm hat zu viele Spalten, mehr als %d"
+042 "Bildschirm hat zu wenig Zeilen, weniger als %d"
+043 "Bildschirm hat zu viele Zeilen, mehr als %d"
+044 "Die lisp-Option ist nicht implementiert"
+045 "Meldungen nicht abgeschaltet: %s"
+046 "Meldungen nicht eingeschaltet: %s"
+047 "set: Die %s Option muss Gruppen zu zwei Zeichen enthalten"
+053 "Der Standardpuffer ist leer"
+054 "Puffer %s ist leer"
+055 "Dateien mit newlines im Namen sind nicht wiederherstellbar"
+056 "Änderungen nicht wiederherstellbar, falls die Editorsitzung schiefgeht"
+057 "kopiere Datei für Wiederherstellung ..."
+058 "Rettungsmechanismus funktioniert nicht: %s"
+059 "Änderungen nicht wiederherstellbar, falls die Editorsitzung schiefgeht"
+060 "Sicherung der Datei gescheitert: %s"
+061 "kopiere Datei für Wiederherstellung ..."
+062 "Informationen über den Benutzer mit id %u nicht gefunden"
+063 "Wiederherstellungsdatei kann nicht gelockt werden"
+064 "Puffer der Wiederherstellungsdatei übergelaufen"
+065 "Wiederherstellungsdatei"
+066 "%s: Wiederherstellungsdatei hat falsches Format"
+067 "%s: Wiederherstellungsdatei hat falsches Format"
+068 "Keine von Ihnen lesbaren Dateien mit Namen %s zum Wiederherstellen"
+069 "Es gibt ältere Versionen dieser Datei von Ihnen zum Wiederherstellen"
+070 "Sie haben noch andere Dateien zum Wiederherstellen"
+071 "schicke keine email: %s"
+072 "Datei leer; nichts zu suchen"
+073 "Dateiende erreicht, ohne das Suchmuster zu finden"
+074 "Kein altes Suchmuster"
+075 "Suchmuster nicht gefunden"
+076 "Dateianfang erreicht, ohne das Suchmuster zu finden"
+077 "Suche beginnt von vorn"
+078 "suche ..."
+079 "Keine nichtdruckbaren Zeichen gefunden"
+080 "Unbekannter Kommandoname"
+082 "%s: Kommando im ex-Modus nicht verfügbar"
+083 "Anzahl darf nicht Null sein"
+084 "%s: falsche Zeilenangabe"
+085 "Interner Syntaxtabellenfehler (%s: %s)"
+086 "Benutzung: %s"
+087 "%s: temporärer Puffer nicht freigegeben"
+088 "Flagoffset vor Zeile 1"
+089 "Flagoffset hinter dem Dateiende"
+090 "@ mit Bereich lief, als Datei/Anzeige geändert wurde"
+091 "globales oder v-Kommando lief, als Datei/Anzeige geändert wurde"
+092 "Ex-Kommando mißlungen: restliche Kommandoeingabe ignoriert"
+093 "Ex-Kommando mißlungen: umdefinierte Tasten ungültig"
+094 "Die zweite Adresse ist kleiner als die erste"
+095 "Kein Markenname angegeben"
+096 "\\ ohne folgenden / oder ?"
+097 "Referenz auf eine negative Zeilennummer"
+098 "Das Kommando %s ist unbekannt"
+099 "Adreßwert zu groß"
+100 "Adreßwert zu klein"
+101 "Ungültige Adreßkombination"
+102 "Ungültige Adresse: nur %lu Zeilen in der Datei"
+103 "Ungültige Adresse: die Datei ist leer"
+104 "Das Kommando %s erlaubt keine Adresse 0"
+105 "Keine Abkürzungen zum Anzeigen"
+106 "Abkürzungen müssen mit einem "Wort"-Zeichen enden"
+107 "Abkürzungen dürfen keine Tabulator- oder Leerzeichen enthalten"
+108 "In Abkürzungen dürfen außer am Ende Wort- und Nicht-Wort-Zeichen nicht gemischt werden"
+109 ""%s" ist keine Abkürzung"
+110 "Vi Kommando mißlungen: umdefinierte Tasten ungültig"
+111 "Keine weiteren Dateien zu editieren"
+112 "Keine vorhergehenden Dateien zu editieren"
+113 "Keine vorhergehenden Dateien für rewind"
+114 "Keine Dateiliste zum Anzeigen"
+115 "Kein vorhergehendes Kommando, um "!" zu ersetzen"
+116 "Kein Dateiname für %%"
+117 "Kein Dateiname für #"
+118 "Fehler: execl: %s"
+119 "E/A-Fehler: %s"
+120 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
+121 "Kann Homedirectory nicht bestimmen"
+122 "Neues aktuelles Directory: %s"
+123 "Keine Puffer anzuzeigen"
+124 "Das Kommando %s kann nicht als Teil eines global oder v Kommandos verwendet werden"
+125 "%s/%s: nicht gelesen: gehört weder Ihnen noch root"
+126 "%s/%s: nicht gelesen: gehört nicht Ihnen"
+127 "%s/%s: nicht gelesen: anderer Benutzer als Eigentümer hat Schreibrecht"
+128 "%s: nicht gelesen: gehört weder Ihnen noch root"
+129 "%s: nicht gelesen: gehört nicht Ihnen"
+130 "%s: nicht gelesen: anderer Benutzer als Eigentümer hat Schreibrecht"
+131 "Keine folgenden Zeilen zum Verbinden"
+132 "Kein input-Map Eintrag"
+133 "Kein command-Map Eintrag"
+134 "Das %s Zeichen kann nicht umgemappt werden"
+135 ""%s" ist momentan nicht gemappt"
+136 "Markennamen müssen einzelne Buchstaben sein"
+137 "%s existiert, nicht geschrieben; verwende ! zum Überschreiben"
+138 "Neue .exrc Datei: %s. "
+139 "Zielzeile ist innerhalb des Verschiebebereichs"
+140 "Das open Kommando verlangt, daß die open Option gesetzt ist"
+141 "Das open Kommando ist nocht nicht implementiert"
+142 "Rettung dieser Datei nicht möglich"
+143 "Datei gerettet"
+144 "%s wurde in zu viele Dateinamen expandiert"
+145 "Nur reguläre Dateien und named pipes können gelesen werden"
+146 "%s: Locken zum Lesen war nicht möglich"
+147 "lese ..."
+148 "%s: %lu Zeilen, %lu Zeichen"
+149 "Keine Hintergrundanzeigen vorhanden"
+150 "Das script Kommando ist nur im vi Modus verfügbar"
+151 "Kein Kommando auszuführen"
+152 "shiftwidth Option auf 0 gesetzt"
+153 "Anzahl-Überlauf"
+154 "Anzahl-Unterlauf"
+155 "Regulärer Ausdruck angegeben; r Flag bedeutungslos"
+156 "Die #, l und p Flags können im vi Modus nicht mit dem c Flag kombiniert werden"
+157 "Keine Übereinstimmung gefunden"
+158 "Kein vorhergehender 'tag' angegeben"
+159 "Weniger als %s Einträge auf dem 'tag'-Stack; verwende :display t[ags]"
+160 "Keine Datei namens %s auf dem 'tag'-Stack; verwende :display t[ags]"
+161 "Drücke Enter um fortzufahren: "
+162 "%s: 'tag' nicht gefunden"
+163 "%s: kaputter 'tag' in %s"
+164 "%s: die Zeilennummer des 'tag' ist hinter dem Dateiende"
+165 "Der 'tag' Stack ist leer"
+166 "%s: Suchmuster nicht gefunden"
+167 "%d weitere Dateien zu editieren"
+168 "Puffer %s ist leer"
+169 "Bestätige Änderung [n]"
+170 "Unterbrochen."
+171 "Kein vorhergehender Puffer zum Ausführen"
+172 "Kein vorhergehender regulärer Ausdruck"
+173 "Das Kommando %s verlangt, daß bereits eine Datei eingelesen wurde"
+174 "Benutzung: %s"
+175 "Das visual Kommando verlangt daß die open Option gesetzt ist"
+177 "Leere Datei"
+178 "Keine vorhergehende F, f, T oder t Suche"
+179 "%s nicht gefunden"
+180 "Keine vorhergehende Datei zu editieren"
+181 "Cursor nicht auf einer Zahl"
+182 "Sich ergebende Zahl ist zu groß"
+183 "Sich ergebende Zahl ist zu klein"
+184 "Kein korrespondierendes Zeichen in dieser Zeile"
+185 "Korrespondierendes Zeichen nicht gefunden"
+186 "Keine Zeichen zu ersetzen"
+187 "Keine andere Anzeige zum Hinschalten"
+188 "Zeichen nach Suchmuster, Zeilenoffset und/oder z Kommando"
+189 "Kein altes Suchmuster"
+190 "Suche zur ursprünglichen Position zurückgekehrt"
+191 "Abkürzung überschreitet Expansionsgrenze: Zeichen weggelassen"
+192 "Nicht erlaubtes Zeichen; maskiere zum Eingeben"
+193 "Bereits am Anfang der Eingabe"
+194 "Keine weiteren Zeichen zu löschen"
+195 "Bewegung hinter das Dateiende"
+196 "Bewegung hinter das Zeilenende"
+197 "Keine Cursorbewegung gemacht"
+198 "Bereits am Dateianfang"
+199 "Bewegung vor den Dateianfang"
+200 "Bereits in der ersten Spalte"
+201 "Puffer sollen vor dem Kommando angegeben werden"
+202 "Bereits am Dateiende"
+203 "Bereits am Zeilenende"
+204 "%s ist kein vi Kommando"
+205 "Benutzung: %s"
+206 "Keine Zeichen zu löschen"
+207 "Das Q Kommando benötigt das ex Terminal Interface"
+208 "Kein Kommando zu wiederholen"
+209 "Die Datei ist leer"
+210 "%s kann nicht als Bewegungskommando verwendet werden"
+211 "Bereits im Kommando-Modus"
+212 " Cursor nicht auf einem Wort"
+214 "Wert der Window Option ist zu groß, max ist %u"
+215 "Anhängen"
+216 "Ändern"
+217 "Kommando"
+218 "Einfügen"
+219 "Ersetzen"
+220 "Bewegung hinter das Anzeigenende"
+221 "Bewegung vor den Anzeigenanfang"
+222 "Anzeige muß für Bildschirmteilung größer als %d sein"
+223 "Keine Hintergrundanzeigen vorhanden"
+224 "Es gibt keine Hintergrundanzeige, die eine Datei namens %s editiert"
+225 "Die einzige dargestellte Anzeige kann nicht in den Hintergrund gebracht werden"
+226 "Die Anzeige kann nur auf %d Zeilen verkleinert werden"
+227 "Die Anzeige kann nicht verkleinert werden"
+228 "Die Anzeige kann nicht vergrößert werden"
+230 "Diese Anzeige kann nicht gestopt werden"
+231 "Unterbrochen: umdefinierte Tasten ungültig"
+232 "vi: temporärer Puffer nicht freigegeben"
+233 "Dieses Terminal hat keine %s Taste"
+234 "es kann nur ein Puffer angegeben werden"
+235 "Zahl größer als %lu"
+236 "Unterbrochen"
+237 "Nicht möglich, temporäre Datei anzulegen"
+238 "Warnung: %s ist keine reguläre Datei"
+239 "%s ist bereits gelockt, Editorsitzung schreibgeschützt"
+240 "%s: löschen"
+241 "%s: schließen"
+242 "%s: löschen"
+243 "%s: löschen"
+244 "Datei nicht schreibbar, nicht geschrieben; verwende ! zum Überschreiben"
+245 "Datei nicht schreibbar, nicht geschrieben"
+246 "%s existiert, nicht geschrieben; verwende ! zum Überschreiben"
+247 "%s existiert, nicht geschrieben"
+248 "Teil der Datei, nicht geschrieben; verwende ! zum Überschreiben"
+249 "Teil der Datei, nicht geschrieben"
+250 "%s: Datei wurde später als diese Kopie verändert; verwende ! zum Überschreiben"
+251 "%s: Datei wurde später als diese Kopie verändert"
+252 "%s: Locken zum Schreiben war nicht möglich"
+253 "schreibe ..."
+254 "%s: WARNUNG: DATEI ABGESCHNITTEN"
+255 "Bereits am ersten 'tag' dieser Gruppe"
+256 "%s: neue Datei: %lu Zeilen, %lu Zeichen"
+257 "%s: %lu Zeilen, %lu Zeichen"
+258 "%s wurde in zu viele Dateinamen expandiert"
+259 "%s: keine reguläre Datei"
+260 "%s: gehört nicht Ihnen"
+261 "%s: anderer Benutzer als Eigentümer hat Zugriff"
+262 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
+263 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende :edit! zum ignorieren"
+264 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
+265 "Datei ist temporär; beim Verlassen gehen die Änderungen verloren"
+266 "Datei ist schreibgeschützt, Änderungen werden nicht automatisch geschrieben"
+267 "Portokollierung neu begonnen"
+268 "bestätigen [ynq]"
+269 "Drücke beliebige Taste um fortzufahren"
+270 "Drücke beliebige Taste um fortzufahren [: um weitere Kommandos einzugeben]: "
+271 "Drücke beliebige Taste um fortzufahren [q zum Verlassen]: "
+272 "Diese Form von %s benötigt das ex Terminal-Interface"
+273 "Gehe in ex Eingabe-Modus.\n"
+274 "Kommando schiefgelaufen, noch keine Datei eingelesen"
+275 " weiter?"
+276 "unerwartetes Zeichen - Ereignis"
+277 "unerwartetes Dateiende - Ereignis"
+278 "Keine Position zum Anspringen gefunden"
+279 "unerwartetes Unterbrechungs - Ereignis"
+280 "unerwartetes Verlassen - Ereignis"
+281 "unerwartetes Wiederherstellungs - Ereignis"
+282 "Bereits am letzten 'tag' dieser Gruppe"
+283 "Das %s Kommando benötigt das ex Terminal-Interface"
+284 "Diese Form von %s wird nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
+285 "unerwartetes Zeichenketten - Ereignis"
+286 "unerwartetes timeout - Ereignis"
+287 "unerwartetes Schreibe - Ereignis"
+289 "Shell Expandierungen nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
+290 "Das %s Kommando wird nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
+291 "set: %s kann nicht ausgeschaltet werden"
+292 "Anzeige zu klein."
+293 "angefügt"
+294 "geändert"
+295 "gelöscht"
+296 "verbunden"
+297 "verschoben"
+298 "geschoben"
+299 "in Puffer geschrieben"
+300 "Zeile"
+301 "Zeilen"
+302 "Vi wurde nicht mit dem Tcl Interpreter gelinkt"
+303 "Datei wurde seit dem letzten Schreiben verändert."
+304 "Shell Expansion hat nicht geklappt"
+305 "Es ist keine %s Editieroption angegeben"
+306 "Vi wurde nicht mit einem Perl Interpreter geladen"
+307 "Kein ex Kommando auszuführen"
+308 "Drücke <CR> um ein Kommando auszuführen, :q zum verlassen"
+309 "Verwende "cscope help" für Hilestellung"
+310 "Keine cscope Verbindung aktiv"
+311 "%s: unbekannter Suchtyp: verwende einen aus %s"
+312 "%d: keine solche cscope Verbindung"
+313 "set: die %s Option kann nicht eingeschaltet werden"
+314 "set: die %s Option kann nicht auf 0 gesetzt werden"
+315 "%s: angefügt: %lu Zeilen, %lu Zeichen"
+316 "unerwartetes Größenveränderungs - Ereignis"
+317 "%d Dateien zu edieren"
diff --git a/dist/nvi/catalog/german.owner b/dist/nvi/catalog/german.owner
new file mode 100644 (file)
index 0000000..efed56a
--- /dev/null
@@ -0,0 +1,2 @@
+Bernhard Daeubler      <daeb@physik.uni-ulm.de>
+Joerg Wunsch           <joerg_wunsch@uriah.heep.sax.de>
diff --git a/dist/nvi/catalog/ru_RU.KOI8-R.base b/dist/nvi/catalog/ru_RU.KOI8-R.base
new file mode 100644 (file)
index 0000000..a52532d
--- /dev/null
@@ -0,0 +1,214 @@
+002 "ðÅÒÅÐÏÌÎÅÎÉÅ ÚÎÁÞÅÎÉÑ ÄÌÉÎÙ ÓÔÒÏËÉ"
+003 "ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÓÔÒÏËÕ %lu"
+004 "ÎÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ Ë ÓÔÒÏËÅ %lu"
+005 "ÎÅ×ÏÚÍÏÖÎÏ ×ÓÔÁ×ÉÔØ × ÓÔÒÏËÕ %lu"
+006 "ÎÅ×ÏÚÍÏÖÎÏ ÓÏÈÒÁÎÉÔØ ÓÔÒÏËÕ %lu"
+007 "ÎÅ×ÏÚÍÏÖÎÏ ÄÏÓÔÁÔØ ÐÏÓÌÅÄÎÀÀ ÓÔÒÏËÕ"
+009 "æÁÊÌ ÚÁÐÉÓÅÊ"
+010 "úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎÅ×ÏÚÍÏÖÎÏ ÏÔÍÅÎÉÔØ ÐÏÓÌÅÄÎÀÀ ËÏÍÁÎÄÕ"
+011 "îÅÔ ÉÚÍÅÎÅÎÉÊ ÄÌÑ ÏÔÍÅÎÙ"
+012 "úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎÅ×ÏÚÍÏÖÎÏ ÏÔÍÅÎÉÔØ ÐÏÓÌÅÄÎÀÀ ËÏÍÁÎÄÕ"
+013 "úÁÐÉÓÉ ÎÅ ×ÅÌÉÓØ, ÎÅ×ÏÚÍÏÖÎÏ ÐÒÏÓÍÏÔÒÅÔØ ×ÐÅÒÅÄ"
+014 "îÅÔ ÉÚÍÅÎÅÎÉÊ ÄÌÑ ÐÅÒÅÄÅÌËÉ"
+015 "%s/%d: ÏÛÉÂËÁ ÐÒÉ ÚÁÐÉÓÉ ÐÒÏÔÏËÏÌÁ"
+016 "óÔÁÎÄÁÒÔÎÙÊ ××ÏÄ/×Ù×ÏÄ ÄÌÑ VI ÄÏÌÖÅΠÂÙÔØ ÔÅÒÍÉÎÁÌ"
+017 "ïÔÍÅÔËÁ %s: ÎÅ ÕÓÔÁÎÏ×ÌÅÎÁ"
+018 "ïÔÍÅÔËÁ %s: ÓÔÒÏËÁ ÂÙÌÁ ÕÄÁÌÅÎÁ"
+019 "ïÔÍÅÔËÁ %s: ÐÏÚÉÃÉÉ ËÕÒÓÏÒÁ ÂÏÌØÛÅ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+020 "ïÛÉÂËÁ: "
+030 "æÁÊÌ %s ÎÅ Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ ÓÏÏÂÝÅÎÉÊ"
+031 "îÅ×ÏÚÍÏÖÎÏ ÕÓÔÁÎÏ×ÉÔØ ÏÐÃÉÀ %s ÐÏ ÕÍÏÌÞÁÎÉÀ"
+032 "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s"
+033 "ïÐÃÉÉ %s ÎÅÔ: 'set all' ÐÏËÁÚÙ×ÁÅÔ ×ÓÅ ×ÏÚÍÏÖÎÙÅ ÏÐÃÉÉ"
+034 "set: [no]%s ÎÅ ÐÒÉÎÉÍÁÅÔ ÔÁËÏÇÏ ÚÎÁÞÅÎÉÑ"
+035 "set: %s ÏÐÃÉÑ ÎÅ Ñ×ÌÑÅÔÓÑ ÌÏÇÉÞÅÓËÏÊ"
+038 "set: ÎÅÐÒÁ×ÉÌØÎÏÅ ÚÎÁÞÅÎÉÅ %s"
+039 "set: %s ÏÐÃÉÑ ÎÅ Ñ×ÌÑÅÔÓÑ ÌÏÇÉÞÅÓËÏÊ"
+040 "ëÏÌÉÞÅÓÔ×Ï ËÏÌÏÎÏË ÜËÒÁÎÁ ÓÌÉÛËÏÍ ÍÁÌÏ, ÍÅÎØÛÅ ÞÅÍ %d"
+041 "ëÏÌÉÞÅÓÔ×Ï ËÏÌÏÎÏË ÜËÒÁÎÁ ÓÌÉÛËÏÍ ×ÅÌÉËÏ, ÂÏÌØÛÅ ÞÅÍ %d"
+042 "ëÏÌÉÞÅÓÔ×Ï ÓÔÒÏË ÜËÒÁÎÁ ÓÌÉÛËÏÍ ÍÁÌÏ, ÍÅÎØÛÅ ÞÅÍ %d"
+043 "ëÏÌÉÞÅÓÔ×Ï ÓÔÒÏË ÜËÒÁÎÁ ÓÌÉÛËÏÍ ×ÅÌÉËÏ, ÂÏÌØÛÅ ÞÅÍ %d"
+044 "ïÐÃÉÑ lisp ÏÔÓÕÔÓÔ×ÕÅÔ"
+045 "óÏÏÂÝÅÎÉÑ ÎÅ ×ÙËÌÀÞÅÎÙ: %s"
+046 "óÏÏÂÝÅÎÉÑ ÎÅ ×ËÌÀÞÅÎÙ: %s"
+048 "ïÐÃÉÑ paragraph ÄÏÌÖÎÁ ÓÏÓÔÏÑÔØ ÉÚ ÇÒÕÐРӠÄ×ÕÍÑ ÓÉÍ×ÏÌÁÍÉ"
+049 "ïÐÃÉÑ section ÄÏÌÖÎÁ ÓÏÓÔÏÑÔØ ÉÚ ÇÒÕÐРӠÄ×ÕÍÑ ÓÉÍ×ÏÌÁÍÉ"
+053 "óÔÁÒÔÏ×ÙÊ ÂÕÆÅÒ ÐÕÓÔ"
+054 "âÕÆÅÒ %s ÐÕÓÔ"
+055 "æÁÊÌÙ Ó ÓÉÍ×ÏÌÁÍÉ ÐÅÒÅ×ÏÄÁ ÓÔÒÏËÉ × ÉÍÅÎÉ ÎÅ ÍÏÇÕÔ ÂÙÔØ ×ÏÓÓÔÁÎÏ×ÌÅÎÙ"
+056 "éÚÍÅÎÅÎÉÑ ÎÅ ÓÏÈÒÁÎÅÎÙ ÐÒÉ ËÒÁÈÅ ÓÅÓÓÉÉ"
+058 "óÏÈÒÁÎÅÎÉÅ ÎÅ ÕÄÁÌÏÓØ: %s"
+059 "éÚÍÅÎÅÎÉÑ ÎÅ ÓÏÈÒÁÎÑÀÔÓÑ ÐÒÉ ÏÂÒÙ×Å ÓÅÓÓÉÉ"
+060 "óÏÈÒÁÎÅÎÉÅ ËÏÐÉÉ ÆÁÊÌÁ ÎÅ ÕÄÁÌÏÓØ: %s"
+062 "éÎÆÏÒÍÁÃÉÉ ÎÁ ÐÏÌØÚÏ×ÁÔÅÌÑ %u ÎÅ ÎÁÊÄÅÎÏ"
+063 "îÅ×ÏÚÍÏÖÎÏ ÚÁÝÉÔÉÔØ ÓÐÁÓÅÎÎÙÊ ÆÁÊÌ"
+064 "âÕÆÅÒ ×ÏÓÓÔÁÎÏ×ÌÅÎÎÏÇÏ ÆÁÊÌÁ ÐÅÒÅÐÏÌÎÅÎ"
+065 "÷ÏÓÓÔÁÎÏ×ÌÅÎÎÙÊ ÆÁÊÌ"
+066 "%s: ÎÅ ÄÏ ËÏÎÃÁ ×ÏÓÓÔÁÎÏ×ÌÅÎÎÙÊ ÆÁÊÌ"
+067 "%s: ÎÅ ÄÏ ËÏÎÃÁ ×ÏÓÓÔÁÎÏ×ÌÅÎÎÙÊ ÆÁÊÌ"
+068 "æÁÊÌÏ× Ó ÉÍÅÎÅÍ %s, ËÏÔÏÒÙÅ ÷Ù ÍÏÖÅÔÅ ÞÉÔÁÔØ, ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+069 "åÓÔØ ÓÔÁÒÙÅ ×ÅÒÓÉÉ ÆÁÊÌÁ, ËÏÔÏÒÙÅ ÍÏÖÎÏ ×ÏÓÓÔÁÎÏ×ÉÔØ"
+070 "óÕÝÅÓÔ×ÕÀÔ ÄÒÕÇÉÅ ÆÁÊÌÙ, ËÏÔÏÒÙÅ ÍÏÖÎÏ ×ÏÓÓÔÁÎÏ×ÉÔØ"
+071 "Å-mail ÎÅ ÐÏÓÌÁÎ: %s"
+072 "æÁÊÌ ÐÕÓÔ - ÉÓËÁÔØ ÎÅÞÅÇÏ"
+073 "äÏÓÔÉÇÎÕÔ ËÏÎÅàÆÁÊÌÁ ÂÅÚ ÎÁÈÏÖÄÅÎÉÑ ÏÂÒÁÚÃÁ ÐÏÉÓËÁ"
+074 "îÅ ÚÁÄÁΠÏÂÒÁÚÅàÐÏÉÓËÁ"
+075 "ïÂÒÁÚÅàÐÏÉÓËÁ ÎÅ ÎÁÊÄÅÎ"
+076 "äÏÓÔÕÐÎÏ ÎÁÞÁÌÏ ÆÁÊÌÁ ÂÅÚ ÎÁÈÏÖÄÅÎÉÑ ÏÂÒÁÚÃÁ ÐÏÉÓËÁ"
+077 "ðÏÉÓË ÚÁÃÉËÌÅÎ"
+079 "îÅÐÅÞÁÔÎÙÈ ÓÉÍ×ÏÌÏ× ÎÅ ÎÁÊÄÅÎÏ"
+080 "îÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ"
+082 "%s: ËÏÍÁÎÄÁ ÎÅ ÄÏÓÔÕÐÎÁ × ÒÅÖÉÍÅ ex"
+083 "óÞÅÔÞÉË ÎÅ ÍÏÖÅÔ ÂÙÔØ ÎÕÌÅÍ"
+084 "%s: ÎÅÐÒÁ×ÉÌØÎÏÅ ÕËÁÚÁÎÉÅ ÓÔÒÏËÉ"
+085 "÷ÎÕÔÒÅÎÎÑÑ ÏÛÉÂËÁ × ÓÉÎÔÁËÓÉÓÅ (%s: %s)"
+086 "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s"
+087 "%s: ×ÒÅÍÅÎÎÙÊ ÂÕÆÅÒ ÎÅ ÉÓÐÏÌØÚÏ×ÁÎ"
+088 "íÅÔËÁ ÐÏÓÔÁ×ÌÅÎÁ ÐÅÒÅÄ ÓÔÒÏËÏÊ 1"
+089 "íÅÔËÁ ÐÏÓÔÁ×ÌÅÎÁ ÐÏÓÌÅ ËÏÎÃÁ ÆÁÊÌÁ"
+092 "ëÏÍÁÎÄÁ ex ÎÅ ÕÄÁÌÁÓØ: ÐÏÓÌÅÄÕÀÝÉÅ ËÏÍÁÎÄÙ ÚÁÂÙÔÙ"
+094 "÷ÔÏÒÏÊ ÁÄÒÅÓ ÍÅÎØÛÅ ÞÅÍ ÐÅÒ×ÙÊ"
+095 "îÅ ÕËÁÚÁÎÏ ÎÁÚ×ÁÎÉÅ ÏÔÍÅÔËÉ"
+096 "\\ ÎÅ ÚÁ×ÅÒÛÁÅÔÓÑ / ÉÌÉ ?"
+097 "óÓÙÌËÁ Ë ÓÔÒÏËÅ Ó ÎÏÍÅÒÏÍ ÍÅÎØÛÅ 0"
+098 "ëÏÍÁÎÄÁ %s ÎÅÉÚ×ÅÓÔÎÁ"
+099 "ðÅÒÅÐÏÌÎÅÎÉÅ ÚÎÁÞÅÎÉÑ ÁÄÒÅÓÁ"
+100 "îÅÄÏÂÏÒ ÚÎÁÞÅÎÉÑ ÁÄÒÅÓÁ"
+101 "îÅÄÏÐÕÓÔÉÍÁÑ ËÏÍÂÉÎÁÃÉÑ × ÁÄÒÅÓÅ"
+102 "îÅÐÒÁ×ÉÌØÎÙÊ ÁÄÒÅÓ: ×ÓÅÇÏ %lu ÓÔÒÏË × ÆÁÊÌÅ"
+103 "îÅÐÒÁ×ÉÌØÎÙÊ ÁÄÒÅÓ: ÆÁÊÌ ÐÕÓÔ"
+104 "ëÏÍÍÁÎÄÁ %s ÎÅ ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÁÄÒÅÓ 0"
+105 "áÂÂÒÅ×ÉÁÔÕÒÙ ÏÔÓÕÔÓÔ×ÕÀÔ"
+106 "áÂÂÒÅ×ÉÁÔÕÒÙ ÄÏÌÖÎÙ ÚÁËÁÎÞÉ×ÁÔØÓÑ ÓÉÍ×ÏÌÏÍ "word""
+107 "áÂÂÒÅ×ÉÁÔÕÒÙ ÎÅ ÍÏÇÕÔ ÓÏÄÅÒÖÁÔØ ÓÉÍ×ÏÌÏÙ ÔÁÂÌÑÃÉÉ ÉÌÉ ÐÒÏÂÅÌÙ"
+108 "áÂÂÒÅ×ÉÁÔÕÒÙ ÎÅ ÍÏÇÕÔ ÓÏÞÅÔÁÔØÓÑ Ó ÓÉÍ×ÏÌÁÍÉ ÓÌÏ×/ÎÅ-ÓÌÏ×, ÚÁ ÉÓËÌÀÞÅÎÉÅÍ ËÏÎÃÁ ÓÔÒÏËÉ"
+109 ""%s" ÎÅ Ñ×ÌÑÅÔÓÑ ÁÂÂÒÅ×ÉÁÔÕÒÏÊ"
+111 "æÁÊÌÏ× ÄÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ ÂÏÌØÛÅ ÎÅÔ"
+112 "ïÔÓÕÔÓÔ×ÉÅ ÐÒÅÄÙÄÕÝÅÇÏ ÆÁÊÌÁ ÄÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+113 "ïÔÓÕÔÓÔ×ÉÅ ÐÒÅÄÙÄÕÝÅÇÏ ÆÁÊÌÁ ÄÌÑ ÐÒÏÓÍÏÔÒÁ ÎÁÚÁÄ"
+114 "îÅÔ ÆÁÊÌÏ×"
+115 "ïÔÓÕÔÓÔ×ÉÅ ÐÒÅÄÙÄÕÝÅÊ ËÏÍÁÎÄÙ ÄÌÑ ÚÁÍÅÎÙ "!""
+116 "ïÔÓÕÔÓÔ×ÉÅ ÚÁÍÅÎÙ ÄÌÑ %%"
+117 "ïÔÓÕÔÓÔ×ÉÅ ÚÁÍÅÎÙ ÄÌÑ #"
+118 "ïÛÉÂËÁ: execl: %s"
+119 "ïÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ: %s"
+120 "æÁÊÌ ÉÚÍÅÎÅΠӠÍÏÍÅÎÔÁ ÐÏÓÌÅÄÎÅÊ ÐÏÌÎÏÊ ÚÁÐÉÓÉ: ÉÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+121 "îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÄÏÍÁÛÎÉÊ ËÁÔÁÌÏÇ"
+122 "îÏ×ÙÊ ËÁÔÁÌÏÇ: %s"
+123 "îÅÔ ×ÙÒÅÚÁÎÙÈ ÂÕÆÅÒÏ×"
+124 "ëÏÍÁÎÄÁ %s ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎÁ ×ÎÕÔÒÉ ÇÌÏÂÁÌØÎÏÊ ÉÌÉ v ËÏÍÁÎÄÙ"
+125 "%s/%s: ÎÅ ÏÔËÒÙÔ: ÎÅ ÐÒÉÎÁÄÌÅÖÉÔ ÷ÁÍ ÉÌÉ root-Õ"
+126 "%s/%s: ÎÅ ÏÔËÒÙÔ: ÎÅ ÐÒÉÎÁÄÌÅÖÉÔ ÷ÁÍ"
+127 "%s/%s: ÎÅ ÏÔËÒÙÔ: ×ÏÚÍÏÖÎÏÓÔØ ÚÁÐÉÓÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ, ÎÅ Ñ×ÌÑÀÝÅÇÏÓÑ ×ÌÁÄÅÌØÃÅÍ"
+128 "%s: ÎÅ ÓÞÉÔÁÎ: ÎÅ ÐÒÉÎÁÄÌÅÖÉÔ ÷ÁÍ ÉÌÉ root-Õ"
+129 "%s: ÎÅ ÓÞÉÔÁÎ: ÎÅ ÐÒÉÎÁÄÌÅÖÉÔ ÷ÁÍ"
+130 "%s: ÎÅ ÓÞÉÔÁÎ: ×ÏÚÍÏÖÎÏÓÔØ ÚÁÐÉÓÉ Õ ÐÏÌØÚÏ×ÁÔÅÌÑ, ÎÅ Ñ×ÌÑÀÝÅÇÏÓÑ ×ÌÁÄÅÌØÃÅÍ"
+131 "ðÏÓÌÅÄÕÀÝÉÅ ÓÔÒÏËÉ ÏÔÓÕÔÓÔ×ÕÀÔ"
+132 "ïÔÓÕÔÓÔ×ÉÅ ÐÁÒÁÍÅÔÒÏ× ××ÏÄÁ"
+133 "ïÔÓÕÔÓÔ×ÉÅ ÐÁÒÁÍÅÔÒÏ× ËÏÍÁÎÄÙ"
+134 "óÉÍ×ÏÌ %s ÎÅ ÍÏÖÅÔ ÂÙÔØ ÐÅÒÅÎÁÚÎÁÞÅÎ"
+135 ""%s" ÎÁ ÄÁÎÎÙÊ ÍÏÍÅÎÔ ÎÅ ÎÁÚÎÁÞÅÎ"
+136 "éÍÑ ÍÅÔËÉ ÄÏÌÖÎÏ ÂÙÔØ ÏÄÎÉÍ ÓÉÍ×ÏÌÏÍ"
+137 "%s ÓÕÝÅÓÔ×ÕÅÔ, ÎÅ ÚÁÐÉÓÁÎ; ÉÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+138 "îÏ×ÙÊ ÆÁÊÌ exrc: %s"
+139 "óÔÒÏËÁ ÐÅÒÅÎÏÓÁ ÎÁÈÏÄÉÔÓÑ ×ÎÕÔÒÉ ÐÁÒÁÍÅÔÒÏ× ÐÅÒÅÎÏÓÁ"
+140 "ëÏÍÁÎÄÁ open ÐÏÄÒÁÚÕÍÅ×ÁÅÔ ÕÓÔÁÎÏ×ËÕ ÏÐÃÉÉ open"
+141 "ëÏÍÁÎÄÁ open ÎÅ ÒÅÁÌÉÚÏ×ÁÎÁ"
+142 "úÁÝÉÔÁ ÆÁÊÌÁ ÎÅ×ÏÚÍÏÖÎÁ"
+143 "æÁÊÌ ÚÁÝÉÝÅÎ"
+144 "%s ÒÁÓÛÉÒÉÌÓÑ × ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ ËÏÌÉÞÅÓÔ×Ï ÉÍÅΠÆÁÊÌÏ×"
+146 "%s: ÚÁÝÉÔÁ ÎÁ ÞÔÅÎÉÅ ÂÙÌÁ ÎÅÄÏÓÔÕÐÎÁ"
+148 "%s: %lu ÓÔÒÏË, %lu ÓÉÍ×ÏÌÏ×"
+149 "îÅÔ ÔÅÎÅ×ÙÈ ÏËÏÎ"
+150 "ëÏÍÁÎÄÁ script ÉÓÐÏÌØÚÕÅÔÓÑ ÔÏÌØËÏ × ÒÅÖÉÍÅ vi"
+151 "îÅÔ ËÏÍÁÎÄÙ ÄÌÑ ÉÓÐÏÌÎÅÎÉÑ"
+152 "ïÐÃÉÑ shiftwidth ÕÓÔÁÎÏ×ÌÅÎÁ ÎÁ 0"
+153 "ðÅÒÅÐÏÌÎÅÎÉÅ ÓÞÅÔÞÉËÁ"
+154 "ãÉËÌ ×ÙÐÏÌÎÅΠÎÅ ÄÏ ËÏÎÃÁ"
+155 "õËÁÚÁÎÏ ÒÅÇÕÌÑÒÎÏÅ ×ÙÒÁÖÅÎÉÅ: ÆÌÁÇ r ÎÅ ÎÕÖÅÎ"
+156 "æÌÁÇÉ #, l É p ÎÅ ÍÏÇÕÔ ÂÙÔØ ÏÂßÅÄÉÎÅÎÙ Ó ÆÌÁÇÏÍ c × ÒÅÖÉÍÅ vi"
+157 "óÏ×ÐÁÄÅÎÉÊ ÎÅÔ"
+158 "íÅÔËÁ ÏÔÓÕÔÓÔ×ÕÅÔ"
+159 "÷ ÓÔÅËÅ ÍÅÔÏË ÚÁÐÉÓÅÊ ÍÅÎØÛÅ, ÞÅÍ %s, ÉÓÐÏÌØÚÕÊÔÅ :display t[ags]"
+160 "æÁÊÌÁ Ó ÉÍÅÎÅÍ %s × ÓÔÅËÅ ÍÅÔÏË ÎÅÔ; ÉÓÐÏÌØÚÕÊÔÅ :display t[ags]"
+162 "%s: ÍÅÔËÁ ÎÅ ÎÁÊÄÅÎÁ"
+163 "%s: ÐÌÏÈÁÑ ÍÅÔËÁ × %s"
+165 "óÔÅË ÍÅÔÏË ÐÕÓÔ"
+166 "%s: ÏÂÒÁÚÅàÐÏÉÓËÁ ÎÅ ÎÁÊÄÅÎ"
+168 "âÕÆÅÒ %s ÐÕÓÔ"
+170 "ðÒÅÒ×ÁÎÏ"
+171 "ïÔÓÕÔÓÔ×ÉÅ ÂÕÆÅÒÁ ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ"
+172 "îÅÔ ÐÒÅÄÉÄÕÝÅÇÏ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ"
+173 "ëÏÍÁÎÄÁ %s ÐÏÄÒÁÚÕÍÅ×ÁÅÔ ÎÁÌÉÞÉÅ ÐÒÏÞÔÅÎÎÏÇÏ ÆÁÊÌÁ"
+174 "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s"
+175 "ëÏÍÁÎÄÁ visual ÐÏÄÒÁÚÕÍÅ×ÁÅÔ ÏÂÑÚÁÔÅÌØÎÕÀ ÕÓÔÁÎÏ×ËÕ ÏÐÃÉÉ open"
+177 "ðÕÓÔÏÊ ÆÁÊÌ"
+178 "îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÐÏÉÓËÁ F, f, T, ÉÌÉ t"
+179 "%s ÎÅ ÎÁÊÄÅÎÏ"
+180 "îÅÔ ÐÒÅÄÙÄÕÝÅÇÏ ÆÁÊÌÁ ÄÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+181 "ëÕÒÓÏÒ ÓÔÏÉÔ ÎÅ ÎÁ ÃÉÆÒÅ"
+182 "ðÏÌÕÞÅÎÎÏÅ ÞÉÓÌÏ ÓÌÉÛËÏÍ ×ÅÌÉËÏ"
+183 "ðÏÌÕÞÅÎÎÏÅ ÞÉÓÌÏ ÓÌÉÛËÏÍ ÍÁÌÏ"
+184 "ðÏÄÈÏÄÑÝÅÇÏ ÓÉÍ×ÏÌÁ ÎÅÔ ÎÁ ÜÔÏÊ ÓÔÒÏËÅ"
+185 "ðÏÄÈÏÄÑÝÉÊ ÓÉÍ×ÏÌ ÎÅ ÎÁÊÄÅÎ"
+186 "îÅÔ ÓÉÍ×ÏÌÏ× ÄÌÑ ÕÄÁÌÅÎÉÑ"
+187 "äÒÕÇÏÇÏ ÜËÒÁÎÁ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+188 "óÉÍ×ÏÌÙ ÐÏÓÌÅ ÓÔÒÏËÉ ÄÌÑ ÐÏÉÓËÁ, ÓÍÅÝÅÎÉÑ ÓÔÒÏËÉ É/ÉÌÉ ËÏÍÁÎÄÙ z"
+189 "ðÒÏÛÌÙÊ ÏÂÒÁÚÅàÐÏÉÓËÁ ÏÔÓÕÔÓÔ×ÕÅÔ"
+190 "ðÏÉÓË ÚÁ×ÅÒÛÉÌÓÑ ÎÁ ÎÁÞÁÌØÎÏÊ ÐÏÚÉÃÉÉ"
+192 "óÉÍ×ÏÌ ÎÅÐÒÁ×ÉÌÅÎ; Ë×ÏÔÉÒÕÊÔÅ ÄÌÑ ××ÏÄÁ"
+193 "õÖÅ ÎÁ ÎÁÞÁÌÅ ×ÓÔÁ×ËÉ"
+194 "îÅÔ ÓÉÍ×ÏÌÏ× ÄÌÑ ÕÄÁÌÅÎÉÑ"
+195 "ðÅÒÅÄ×ÉÖÅÎÉÅ ÚÁ ËÏÎÅàÆÁÊÌÁ"
+196 "ðÅÒÅÄ×ÉÖÅÎÉÅ ÚÁ ËÏÎÅàÓÔÒÏËÉ"
+197 "ä×ÉÖÅÎÉÅ ÓÔÒÏËÉ ÎÅ ÓÄÅÌÁÎÏ"
+198 "õÖÅ ÎÁ ÎÁÞÁÌÅ ÆÁÊÌÁ"
+199 "ä×ÉÖÅÎÉÅ ËÕÒÓÏÒÁ ÚÁ ÎÁÞÁÌÏ ÆÁÊÌÁ"
+200 "õÖÅ × ÐÅÒ×ÏÊ ËÏÌÏÎËÅ"
+201 "âÕÆÅÒÙ ÄÏÌÖÎÙ ÂÙÔØ ÕËÁÚÁÎÙ ÄÏ ×ÙÐÏÌÎÅÎÉÑ ËÏÍÁÎÄÙ"
+202 "õÖÅ ÎÁ ËÏÎÃÅ ÆÁÊÌÁ"
+203 "õÖÅ ÎÁ ËÏÎÃÅ ÓÔÒÏËÉ"
+204 "%s ÎÅ Ñ×ÌÑÅÔÓÑ ËÏÍÁÎÄÏÊ VI"
+205 "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s"
+206 "îÅÔ ÓÉÍ×ÏÌÏ× ÄÌÑ ÕÄÁÌÅÎÉÑ"
+208 "îÅÔ ËÏÍÁÎÄÙ ÄÌÑ ÐÏ×ÔÏÒÁ"
+210 "ëÏÍÁÎÄÁ %s ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎÁ ËÁË ËÏÍÁÎÄÁ ÐÅÒÅÍÅÝÅÎÉÑ"
+211 "õÖÅ × ËÏÍÁÎÄÎÏÍ ÒÅÖÉÍÅ"
+214 "úÎÁÞÅÎÉÅ ÏÐÃÉÉ windows ÓÌÉÛËÏÍ ×ÅÌÉËÏ, ÍÁËÓÉÍÁÌØÎÏÅ ÚÎÁÞÅÎÉÅ = %u"
+220 "ä×ÉÖÅÎÉÅ ËÕÒÓÏÒÁ ÚÁ ËÏÎÅàÜËÒÁÎÁ"
+221 "ä×ÉÖÅÎÉÅ ËÕÒÓÏÒÁ ÚÁ ÎÁÞÁÌÏ ÜËÒÁÎÁ"
+223 "ôÅÎÅ×ÙÈ ÏËÏΠÎÅÔ"
+224 "îÅ ÓÕÝÅÓÔ×ÕÅÔ ÔÅÎÅ×ÏÇÏ ÏËÎÁ Ó ÒÅÄÁËÔÉÒÏ×ÁÎÉÅÍ ÆÁÊÌÁ %s"
+225 "÷Ù ÎÅ ÍÏÖÅÔÅ ÓÄÅÌÁÔØ ÅÄÉÎÓÔ×ÅÎÎÏÅ ÏËÎÏ ÔÅÎÅ×ÙÍ"
+226 "üËÒÁΠÍÏÖÅÔ ÂÙÔØ ÓÖÁÔ"
+227 "üËÒÁΠÎÅ ÍÏÖÅÔ ÂÙÔØ ÓÖÁÔ ÔÏÌØËÏ ÄÏ %d ÓÔÒÏË"
+228 "üËÒÁΠÎÅ ÍÏÖÅÔ ÂÙÔØ ÒÁÓÛÉÒÅÎ"
+233 "äÁÎÎÙÊ ÔÉРÔÅÒÍÉÎÁÌÁ ÎÅ ÉÍÅÅÔ ËÌÁ×ÉÛÉ %s"
+237 "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ×ÒÅÍÅÎÎÙÊ ÆÁÊÌ"
+238 "÷ÎÉÍÁÎÉÅ: %s ÓÐÅÃÉÁÌØÎÙÊ ÆÁÊÌ"
+239 "%s ÕÖÅ ÚÁÂÌÏËÉÒÏ×ÁÎ, ÄÏÓÔÕÐÅΠÔÏÌØËÏ ÎÁ ÞÔÅÎÉÅ"
+240 "%s: ÕÄÁÌÅÎ"
+241 "%s: ÚÁËÒÙÔ"
+242 "%s: ÕÄÁÌÅÎ"
+243 "%s: ÕÄÁÌÅÎ"
+244 "æÁÊÌ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ, ÎÅ ÚÁÐÉÓÁÎ: éÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+245 "æÁÊÌ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ, ÎÅ ÚÁÐÉÓÁÎ"
+246 "%s ÓÕÝÅÓÔ×ÕÅÔ, ÎÅ ÚÁÐÉÓÁÎ; ÉÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+247 "%s ÓÕÝÅÓÔ×ÕÅÔ, ÎÅ ÚÁÐÉÓÁÎ"
+248 "éÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÞÁÓÔÉÞÎÏÊ ÚÁÐÉÓÉ ÆÁÊÌÁ"
+249 "þÁÓÔØ ÆÁÊÌÁ, ÆÁÊÌ ÎÅ ÚÁÐÉÓÁÎ"
+250 "%s: æÁÊÌ ÉÚÍÅÎÑÌÓÑ ÐÏÚÄÎÅÅ, ÞÅÍ ÄÁÎÎÁÑ ËÏÐÉÑ: ÉÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+251 "%s: æÁÊÌ ÉÚÍÅÎÑÌÓÑ ÐÏÚÄÎÅÅ, ÞÅÍ ÄÁÎÎÁÑ ËÏÐÉÑ"
+252 "%s: ÚÁÝÉÔÁ ÎÁ ÚÁÐÉÓØ ÂÙÌÁ ÎÅÄÏÓÔÕÐÎÁ"
+254 "%s: ÷îéíáîéå: æáêì õóåþåî"
+256 "%s: ÎÏ×ÙÊ ÆÁÊÌ: %lu ÓÔÒÏË, %lu ÓÉÍ×ÏÌÏ×"
+257 "%s: %lu ÓÔÒÏË, %lu ÓÉÍ×ÏÌÏ×"
+258 "%s ÒÁÓÛÉÒÉÌÓÑ × ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ ËÏÌÉÞÅÓÔ×Ï ÉÍÅΠÆÁÊÌÏ×"
+259 "%s: ÓÐÅÃÉÁÌØÎÙÊ ÆÁÊÌ"
+260 "%s: ÎÅ ÐÒÉÎÁÄÌÅÖÉÔ ÷ÁÍ"
+261 "%s: ÄÏÓÔÕÐÅΠÎÅ ÔÏÌØËÏ ÷ÁÍ"
+262 "æÁÊÌ ÉÚÍÅÎÅΠÓÏ ×ÒÅÍÅÎÉ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ: ÓÏÈÒÁÎÉÔÅ ÉÌÉ ÉÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+263 "æÁÊÌ ÉÚÍÅÎÅΠÓÏ ×ÒÅÍÅÎÉ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ: ÓÏÈÒÁÎÉÔÅ ÉÌÉ ÉÓÐÏÌØÚÕÊÔÅ :edit ÄÌÑ ÏÂÈÏÄÁ"
+264 "æÁÊÌ ÉÚÍÅÎÅΠÓÏ ×ÒÅÍÅÎÉ ÐÏÓÌÅÄÎÅÊ ÚÁÐÉÓÉ: ÓÏÈÒÁÎÉÔÅ ÉÌÉ ÉÓÐÏÌØÚÕÊÔÅ ! ÄÌÑ ÏÂÈÏÄÁ"
+265 "æÁÊÌ ×ÒÅÍÅÎÎÙÊ: ×ÙÈÏÄ ÓÏÔÒÅÔ ÌÀÂÙÅ ÉÚÍÅÎÅÎÉÑ"
+267 "úÁÐÉÓÉ ÎÁÞÁÔÙ ÚÁÎÏ×Ï"
diff --git a/dist/nvi/catalog/ru_RU.KOI8-R.owner b/dist/nvi/catalog/ru_RU.KOI8-R.owner
new file mode 100644 (file)
index 0000000..35aa5c9
--- /dev/null
@@ -0,0 +1,2 @@
+Andrey A. Chernov <ache@nagual.ru>
+Dima Ruban <dima@rdy.com>
diff --git a/dist/nvi/catalog/spanish.base b/dist/nvi/catalog/spanish.base
new file mode 100644 (file)
index 0000000..64514bc
--- /dev/null
@@ -0,0 +1,308 @@
+002 "Desbordamiento de longitud de l¡nea"
+003 "no se puede borrar la l¡nea %lu"
+004 "no se puede a¤adir la l¡nea %lu"
+005 "no se puede insertar en la l¡nea %lu"
+006 "no se puede guardar la l¡nea %lu"
+007 "no se puede obtener la £ltima l¡nea"
+008 "Error: no se puede recuperar la l¡nea %lu"
+009 "Archivo de log"
+010 "No se realiza log, no se puede deshacer"
+011 "No hay cambios para deshacer"
+012 "No se realiza log, no se puede deshacer"
+013 "No se realiza log, no se puede remontar hacia adelante"
+014 "No hay cambios para rehacer"
+015 "%s/%d: error de log"
+016 "La entrada y salida est ndar de Vi debe ser una terminal"
+017 "Marcar %s: no determinado"
+018 "Marcar %s: se borr¢ la l¡nea"
+019 "Marcar %s: la posici¢n del cursor ya no existe"
+020 "Error: "
+021 "nuevo archivo"
+022 "nombre cambiado"
+023 "modificado"
+024 "no modificado"
+025 "DESTRABADO"
+026 "lectura solamente"
+027 "l¡nea %lu de %lu [%ld%%]"
+028 "archivo vac¡o"
+029 "l¡nea %lu"
+030 "El archivo %s no es un cat logo de mensajes"
+031 "No se puede determinar la opci¢n por omisi¢n %s"
+032 "Uso: %s"
+033 "determinar: no hay opci¢n %s: 'determinar todo' establece todos los valores de opci¢n"
+034 "determinar: [no] hay opci¢n %s no tiene valor"
+035 "determinar: opci¢n %s no es booleano"
+036 "determinar: opci¢n %s: %s"
+037 "determinar: opci¢n %s: %s: desbordamiento de valores"
+038 "determinar: opci¢n %s: %s es un n£mero ilegal"
+039 "determinar: opci¢n %s no es booleano"
+040 "Las columnas en pantalla son demasiado peque¤as, menos de %d"
+041 "Las columnas en pantalla son demasiado grandes, m s de %d"
+042 "Las l¡neas en pantalla son demasiado peque¤as, menos de %d"
+043 "Las l¡neas en pantalla son demasiado grandes, m s de %d"
+044 "La opci¢n lisp no est  implementada"
+045 "mensajes no desconectados: %s"
+046 "mensajes no conectados: %s"
+047 "determinar: La opci¢n de %s debe estar en dos grupos de caracteres"
+053 "El buffer por omisi¢n est  vac¡o"
+054 "El buffer %s est  vac¡o"
+055 "Los archivos con nuevas l¡neas en el nombre son irrecuperables"
+056 "Las modificaciones no pueden recuperarse si la sesi¢n falla"
+057 "Copiando archivo para recuperaci¢n..."
+058 "Preservaci¢n fracasada: %s"
+059 "Las modificaciones no pueden recuperarse si la sesi¢n falla"
+060 "Archivo de respaldo fracasado: %s"
+061 "Copiando archivo para recuperaci¢n..."
+062 "Informaci¢n sobre identificaci¢n del usuario %u no encontrada"
+063 "No se puede trabar archivo de recuperaci¢n"
+064 "Desbordamiento de buffer de archivo de recuperaci¢n"
+065 "Archivo de recuperaci¢n"
+066 "%s: archivo de recuperaci¢n defectuoso"
+067 "%s: archivo de recuperaci¢n defectuoso"
+068 "No hay archivos denominados %s, que usted pueda leer, para recuperar"
+069 "Existen versiones m s antiguas de este archivo que usted puede recuperar"
+070 "Existen otros archivos que usted puede recuperar"
+071 "no env¡a email: %s"
+072 "Archivo vac¡o; no hay nada para buscar"
+073 "Se alcanz¢ el final del archivo sin encontrar el patr¢n"
+074 "No hay patr¢n anterior de b£squeda"
+075 "No se encontr¢ el patr¢n"
+076 " Se alcanz¢ el principio del archivo sin encontrar el patr¢n"
+077 "B£squeda reiniciada"
+078 "Buscando..."
+079 "No se encontr¢ ning£n car cter no imprimible"
+080 "Nombre de comando desconocido"
+082 "%s: comando no disponible en modalidad ex"
+083 "La cuenta no puede ser cero"
+084 "%s: mala especificaci¢n de l¡nea"
+085 "Error interno de tabla de sintaxis (%s: %s)"
+086 "Uso: %s"
+087 "%s: buffer temporario no liberado"
+088 "Desplazamiento de marcador a antes de la l¡nea 1"
+089 "Desplazamiento de marcador m s all  del final del archivo"
+090 "@ con rango que corre cuando se cambia el archivo/la pantalla"
+091 "Comando global/v que corre cuando se cambia el archivo/la pantalla"
+092 "Comando Ex fracasado: comandos pendientes descartados"
+093 "Comando Ex fracasado: teclas mapeadas descartadas"
+094 "La segunda direcci¢n es m s peque¤a que la primera"
+095 "No se suministra nombre de marca"
+096 "\\ no es seguido por / o ?"
+097 "Referencia a un n£mero de l¡nea menor que 0"
+098 "El comando %s es desconocido"
+099 "Desbordamiento de valor de direcci¢n"
+100 "Subdesbordamiento de valor de direcci¢n"
+101 "Combinaci¢n de direcci¢n ilegal"
+102 "Direcci¢n ilegal: s¢lo %lu l¡neas en el archivo"
+103 "Direcci¢n ilegal: el archivo est  vac¡o"
+104 "El comando %s no permite una direcci¢n de 0"
+105 "No hay abreviaturas para visualizar"
+106 "Las abreviaturas deben terminar con un car cter de \"palabra\" "
+107 "Las abreviaturas no pueden contener tabs o espacios"
+108 "Las abreviaturas no pueden mezclar caracteres palabra/no-palabra, salvo al final"
+109 "\"%s\" no es una abreviatura"
+110 "Comando Vi fracasado: teclas mapeadas descartadas"
+111 "No hay m s archivos para editar"
+112 "No hay archivos anteriores para editar"
+113 "No hay archivos anteriores para rebobinar"
+114 "No hay lista de archivos para visualizar"
+115 "No hay un comando anterior para reemplazar a \"!\""
+116 "No hay nombre de archivo para sustituir por %%"
+117 "No hay nombre de archivo para sustituir por #"
+118 "Error: execl: %s"
+119 "Error de E/S: %s"
+120 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
+121 "No se puede encontrar la ubicaci¢n del directorio inicial"
+122 "Nuevo directorio actual: %s"
+123 "No hay buffers sueltos para visualizar"
+124 "El comando %s no puede usarse como parte de un comando global o v"
+125 "%s/%s: sin fuente: no le pertenece a usted o a ra¡z"
+126 "%s/%s: sin fuente: no le pertenece a usted"
+127 "%s/%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
+128 "%s: sin fuente: no le pertenece a usted o a ra¡z"
+129 "%s: sin fuente: no le pertenece a usted"
+130 "%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
+131 "No hay l¡neas siguientes para unir"
+132 "No hay anotaciones de mapa de entrada"
+133 "No hay anotaciones de mapa de comando"
+134 "El car cter %s no puede remapearse"
+135 "\"%s\" no est  mapeado actualmente"
+136 "Marca de nombres debe ser un s¢lo car cter"
+137 "%s existe, no est  escrito; usar ! para alterar"
+138 "Nuevo archivo exrc: %s"
+139 "La l¡nea de destino se encuentra dentro del rango de movimiento"
+140 "El comando abierto requiere que se determine la opci¢n abierta"
+141 "El comando abierto no se ha implementado a£n"
+142 "No es posible preservar este archivo"
+143 "Archivo preservado"
+144 "%s: expandido a demasiados nombres de archivo"
+145 "S¢lo pueden leerse los archivos regulares y los conductos nombrados"
+146 "%s: traba de lectura no disponible"
+147 "Leyendo..."
+148 "%s: %lu l¡neas, %lu caracteres"
+149 "No hay pantallas de fondo para mostrar"
+150 "El comando de script s¢lo est  disponible en modalidad vi"
+151 "No hay comando para ejecutar"
+152 "opci¢n de ancho de desplazamiento en 0"
+153 "Desbordamiento de cuenta"
+154 "Subdesbordamiento de cuenta"
+155 "Expresi¢n regular especificada; marcador r no tiene significado"
+156 "Los marcadores #, l y p no pueden combinarse con el marcador c en la modalidad vi"
+157 "No se encontr¢ coincidencia"
+158 "No se ingres¢ un identificador anterior"
+159 "Se encontraron menos de %s anotaciones en la pila de identificadores; usar :visualizar i[dentificadores]"
+160 "No hay archivo %s en la pila de identificadores al que se pueda volver; usar :visualizar i[dentificadores]" 
+161 "Presionar Intro para continuar: "
+162 "%s: no se encontr¢ el identificador"
+163 "%s: identificador corrompido en %s"
+164 "%s: el n£mero de l¡nea del identificador es posterior al final del archivo"
+165 "La pila de identificadores est  vac¡a"
+166 "%s: patr¢n de b£squeda no encontrado"
+167 "%d archivos m s para editar"
+168 "El buffer %s est  vac¡o"
+169 "¨Confirmar cambio? [n]"
+170 "Interrumpido"
+171 "No hay buffer anterior para ejecutar"
+172 "No hay expresi¢n regular anterior"
+173 "El comando %s requiere que se haya le¡do un archivo"
+174 "Uso: %s"
+175 "El comando visual requiere que se determine la opci¢n abierta"
+177 "Archivo vac¡o"
+178 "No hay b£squeda F, f, T o t anterior"
+179 "%s no se encontr¢"
+180 "No hay archivo anterior para editar"
+181 "El cursor no est  en un n£mero"
+182 "El n£mero resultante es demasiado grande"
+183 " El n£mero resultante es demasiado peque¤o"
+184 "No hay car cter coincidente en esta l¡nea"
+185 "No se encontr¢ un car cter coincidente"
+186 "No hay caracteres para reemplazar"
+187 "No hay otra pantalla a la que se pueda pasar"
+188 "Caracteres despu\82s de cadena de b£squeda, desplazamiento de l¡nea y/o comando z"
+189 "No hay patr¢n anterior de b£squeda"
+190 "B£squeda vuelve a la posici¢n inicial"
+191 "Se super¢ el l¡mite de expansi¢n de abreviatura: se descartaron caracteres"
+192 "Car cter ilegal; mencionar para entrar"
+193 "Ya se encuentra al principio de la inserci¢n"
+194 "No hay m s caracteres para borrar"
+195 "Movimiento m s all  del final del archivo"
+196 "Movimiento m s all  del final de la l¡nea"
+197 "No hay movimiento del cursor"
+198 "Ya se encuentra al principio del archivo"
+199 "Movimiento m s all  del principio del archivo"
+200 "Ya se encuentra en la primera columna"
+201 "Los buffers deben especificarse antes del comando"
+202 "Ya se encuentra al final del archivo"
+203 "Ya se encuentra al final de la l¡nea"
+204 "%s no es un comando vi"
+205 "Uso: %s"
+206 "No hay caracteres para borrar"
+207 "El comando Q requiere la interfase de terminal ex"
+208 "No hay comando para repetir"
+209 "El archivo est  vac¡o"
+209 "El archivo est  vac¡o"
+210 "%s no puede usarse como comando de movimiento"
+211 "Ya se encuentra en modalidad de comando"
+212 "El cursor no se encuentra en una palabra"
+214 "El valor de opci¢n de Windows es demasiado grande, el m x. es %u"
+215 "A¤adir"
+216 "Cambiar"
+217 "Comando"
+218 "Insertar"
+219 "Reemplazar"
+220 "El movimiento va m s all  del final de la pantalla"
+221 "El movimiento va m s all  del principio de la pantalla"
+222 "La pantalla debe tener m s de %d l¡neas para dividirse"
+223 "No hay pantallas de fondo"
+224 "No hay pantalla de fondo editando un archivo denominado %s"
+225 "No se puede poner fondo a la £nica pantalla que se visualiza"
+226 "La pantalla s¢lo puede reducirse a %d hileras"
+227 "La pantalla no puede reducirse"
+228 "La pantalla no puede aumentarse"
+230 "Esta pantalla no puede suspenderse"
+231 "Interrumpido: teclas mapeadas descartadas"
+232 "vi: buffer temporario no liberado"
+233 "Esta terminal no tiene tecla %s"
+234 "S¢lo un buffer puede especificarse"
+235 "N£mero mayor que %lu"
+236 "Interrumpido"
+237 "No se puede crear archivo temporario"
+238 "Advertencia: %s no es un archivo regular"
+239 "%s ya se encuentra trabado, la sesi¢n es de lectura solamente"
+240 "%s: eliminar"
+241 "%s: cerrar"
+242 "%s: eliminar"
+243 "%s: eliminar"
+244 "Archivo de lectura solamente, no escrito; usar ! para alterar"
+245 " Archivo de lectura solamente, no escrito"
+246 "%s existe, no escrito; usar ! para alterar"
+247 "%s existe, no escrito"
+248 "Archivo parcial, no escrito; usar ! para alterar"
+249 "Archivo parcial, no escrito"
+250 "%s: archivo modificado m s recientemente que esta copia; usar ! para alterar"
+251 "%s: archivo modificado m s recientemente que esta copia"
+252 "%s: la traba de escritura no estaba disponible"
+253 "Escribiendo..."
+254 "%s: ADVERTENCIA: ARCHIVO TRUNCADO"
+255 "Ya se encuentra en el primer identificador de este grupo"
+256 "%s: nuevo archivo: %lu l¡neas, %lu caracteres"
+257 "%s: %lu l¡neas, %lu caracteres"
+258 "%s expandido a demasiados nombres de archivos"
+259 "%s: no es un archivo regular"
+260 "%s: no le pertenece"
+261 "%s: accesible por un usuario que no sea el propietario"
+262 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
+263 "Archivo modificado desde la £ltima escritura completa; escribir o usar :editar! para alterar"
+264 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
+265 "El archivo es temporario; al salir se descartar n las modificaciones"
+266 "Archivo de lectura solamente, las modificaciones no se autoescriben"
+267 "Se reinici¢ el log"
+268 "confirmar? [snq]"
+269 "Presionar cualquier tecla para continuar: "
+270 "Presionar cualquier tecla para continuar [: para ingresar m s comandos ex]: "
+271 "Presionar cualquier tecla para continuar [q para salir]: "
+272 "Esta forma de %s requiere la interfase terminal ex"
+273 "Ingresando en la modalidad de entrada ex."
+274 "Comando fracasado, no hay archivo le¡do aun."
+275 " cont?"
+276 "Evento inesperado de car cter"
+277 "Evento inesperado de final de archivo"
+278 "No hay coincidencias para consulta"
+279 "Evento inesperado de interrupci¢n"
+280 "Evento inesperado de salida"
+281 "Evento inesperado de repintura"
+282 "Ya se encuentra en el £ltimo identificador de este grupo"
+283 "El comando %s requiere la interfase terminal ex"
+284 "Esta forma de %s no se encuentra soportada cuando se determina la opci¢n de edici¢n segura"
+285 "Evento inesperado de cadena"
+286 "Evento inesperado de tiempo excedido"
+287 "Evento inesperado de escritura"
+289 "Las expansiones de shell no se encuentran soportadas cuando se determina la opci¢n de edici¢n segura"
+290 "El comando %s no se encuentra soportado cuando se determina la opci¢n de edici¢n segura"
+291 "determinar: la opci¢n %s puede no estar desconectada"
+292 "El monitor es demasiado peque¤o."
+293 "agregado"
+294 "cambiado"
+295 "borrado"
+296 "unido"
+297 "movido"
+298 "desplazado"
+299 "arrancado"
+300 "l¡nea"
+301 "l¡neas"
+302 "Vi no se carg¢ con un int\82rprete Tcl"
+303 "Archivo modificado desde la £ltima escritura."
+304 "Expansi¢n de shell fracasada"
+304 "Expansi¢n de shell fracasada"
+305 "No hay opci¢n de edici¢n %s especificada"
+306 "Vi no se carg¢ con un int\82rprete Perl"
+307 "No hay comando ex para ejecutar"
+308 "Ingresar <CR> para ejecutar un comando, :q para salir"
+309 "Usar \"cscope ayuda\" para obtener ayuda"
+310 "No hay conexiones cscope corriendo"
+311 "%s: tipo de b£squeda desconocido: usar uno de %s"
+312 "%d: no existe esta sesi¢n cscope"
+313 "determinar: la opci¢n %s no puede conectarse nunca"
+314 "determinar: la opci¢n %s no puede determinarse nunca en 0"
+315 "%s: a¤adido: %lu l¡neas, %lu caracteres"
+316 "Evento inesperado de modificaci¢n de tama¤o"
+317 "%d archivos para editar"
diff --git a/dist/nvi/catalog/spell.ok b/dist/nvi/catalog/spell.ok
new file mode 100644 (file)
index 0000000..00be471
--- /dev/null
@@ -0,0 +1,19 @@
+ARGMAX
+LC
+NL
+XXXX
+arg1
+arg2
+chys
+english
+english.base
+german.base
+langauge
+msg
+msg.c
+msgcat
+msgq
+nvi
+nvi's
+pathname
+sp
diff --git a/dist/nvi/catalog/swedish.base b/dist/nvi/catalog/swedish.base
new file mode 100644 (file)
index 0000000..8582e45
--- /dev/null
@@ -0,0 +1,306 @@
+002 "För långa rader"
+003 "kan inte ta bort rad %lu"
+004 "kan inte lägga till på rad %lu"
+005 "kan inte sätta in på rad %lu"
+006 "kan inte lagra rad %lu"
+007 "kan inte hämta sista raden"
+008 "Fel: kan inte hämta rad %lu"
+009 "Loggningsfil"
+010 "Loggning utförs inte, ångra är inte möjligt"
+011 "Inga ändringar att ångra"
+012 "Loggning utförs inte, ångra är inte möjligt"
+013 "Loggning utförs inte, ångra ångra är inte möjligt"
+014 "Inga ändringar att återgöra"
+015 "%s/%d: fel vid loggning"
+016 "Vi:s standard in och ut måste gå till en terminal"
+017 "Markering %s: inte satt"
+018 "Markering %s: raden har tagits bort"
+019 "Markering %s: markörpositionen finns inte längre"
+020 "Fel: "
+021 "ny fil"
+022 "namnet ändrades"
+023 "ändrad"
+024 "oförändrad"
+025 "OLÅST"
+026 "inte skrivbar"
+027 "rad %lu av %lu [%ld%%]"
+028 "tom fil"
+029 "rad %lu"
+030 "Filen %s är ingen meddelandekatalog"
+031 "Kan inte sätta standardvärde för %s flaggan"
+032 "Användning: %s"
+033 "set: %s är en okänd flagga: "set all" visar alla flaggor"
+034 "set: [no]%s flaggan kan inte ges ett värde"
+035 "set: %s flaggan är inte boleansk"
+036 "set: %s flaggan: %s"
+037 "set: %s flaggan: %s: för stort värde"
+038 "set: %s flaggan: %s är ett otillåtet tal"
+039 "set: %s flaggan är inte boleansk"
+040 "Fönsterkolumnerna är för få, mindre än %d"
+041 "Fönsterkolumnerna är för många, fler än %d"
+042 "Fönsterraderna är för få, mindre än %d"
+043 "Fönsterraderna är för många, fler än %d"
+044 "Lisp flaggan är inte implementerad"
+045 "meddelanden är inte avslagna: %s"
+046 "meddelanden är inte påslagna: %s"
+047 "set: %s flaggan måste ges i teckengrupper om två"
+053 "Standardbufferten är tom"
+054 "Buffer %s är tom"
+055 "Filer med radmatning i namnet kan inte återskapas"
+056 "Ändringar kan inte återskapas om programmet kraschar"
+057 "Kopierar filen för återskapning..."
+058 "Säkerhetskopiering misslyckades: %s"
+059 "Ändringar kan inte återskapas om programmet kraschar"
+060 "Misslyckades att säkerhetskopiera filen: %s"
+061 "Kopierar filen för återskapning..."
+062 "Kan inte hitta information om användaridentitet %u"
+063 "Kan inte låsa återskapningsfilen"
+064 "Återskapningsfilens buffer överskriven"
+065 "Återskapningsfil"
+066 "%s: Återskapningsfilen är korrupt"
+067 "%s: Återskapningsfilen är korrupt"
+068 "Det finns ingen fil %s, läsbar av dig, att återskapa"
+069 "Det finns äldre versioner av denna fil som du kan återskapa"
+070 "Det finns andra filer du kan återskapa"
+071 "skickar inte email: %s"
+072 "Filen är tom; inget att söka i"
+073 "Kom till slutet på filen utan att hitta söksträngen"
+074 "Ingen tidigare söksträng"
+075 "Hittar inte söksträngen"
+076 "Kom till början av filen utan att hitta söksträngen"
+077 "Sökningen slog runt"
+078 "Söker..."
+079 "Inga icke skrivbara tecken funna"
+080 "Okänt kommandonamn"
+082 "%s: kommandot är inte tillgängligt i "ex" läge"
+083 "Talet får inte vara noll"
+084 "%s: Ogiltig radspecifikation"
+085 "Fel i intern syntaxtabell (%s: %s)"
+086 "Användning: %s"
+087 "%s: temporärbuffert inte frisläppt"
+088 "Offset är före rad 1"
+089 "Offset är efter slutet på filen"
+090 "@ med intervall exekverades när filen/fönstret ändrades"
+091 "Global/v kommando exekverades när filen/fönstret ändrades"
+092 "Ex kommando misslyckades: efterföljande kommandon ignorerade"
+093 "Ex kommando misslyckades: omdefinierade tangenter ignorerade"
+094 "Den andra adressen är mindre än den första"
+095 "Inget namn på markering givet"
+096 "\\ följs inte av / eller ?"
+097 "Referens till ett radnummer mindre än 0"
+098 "%s kommandot är inte känt"
+099 "Värdet på adressen är för stort"
+100 "Värdet på adressen är för litet"
+101 "Otillåten adresskombination"
+102 "Otillåten adress: bara %lu rader finns i filen"
+103 "Otillåten adress: filen är tom"
+104 "%s kommandot tillåter inte en adress som är 0"
+105 "Inga förkortningar att visa"
+106 "Förkortningar måste sluta med ett "ord" tecken"
+107 "Förkortningar kan inte innehålla mellanslag eller tab"
+108 "Förkortningar kan inte blanda "ord"/"icke ord" tecken, utom i slutet"
+109 ""%s" är ingen förkortning"
+110 "Vi kommando misslyckades: omdefinierade tangenter ignorerade"
+111 "Inga fler filer att editera"
+112 "Inga tidigare filer att editera"
+113 "Inga tidigare filer att spela tillbaka"
+114 "Ingen fillista att visa"
+115 "Inget tidigare kommando att ersätta "!" med"
+116 "Inget filnamn att ersätta %% med"
+117 "Inget filnamn att ersätta # med"
+118 "Fel: execl: %s"
+119 "I/O fel: %s"
+120 "Filen ändrad efter sista skrivning; spara eller använd !"
+121 "Kan inte hitta hemkatalog"
+122 "Ny nuvarande katalog: %s"
+123 "Inga "cut buffers" att visa"
+124 "%s kommandot kan inte används som del i ett "global" eller v kommando"
+125 "%s/%s: inte läst: varken du eller root är ägare"
+126 "%s/%s: inte läst: du är inte ägare"
+127 "%s/%s: inte läst: skrivbar av annan än ägaren"
+128 "%s: inte läst: varken du eller root är ägare"
+129 "%s: inte läst: du är inte ägare"
+130 "%s: inte läst: skrivbar av annan än ägaren"
+131 "Ingen nästa rad att sätta ihop med"
+132 "Det finns inget i inmatningsmappningen"
+133 "Det finns inget i kommandomappningen"
+134 "%s tecknet kan inte mappas om"
+135 ""%s" är inte ommappat just nu"
+136 "Namn på markeringar måste vara ett tecken långa"
+137 "%s finns, inget sparat; använd ! för att spara"
+138 "Ny exrc fil: %s"
+139 "Målraden ligger inne i området som ska flyttas"
+140 "Open kommandot kräver att open flaggan är satt"
+141 "Open kommandot är inte implementerat ännu"
+142 "Säkerhetskopiering av filen är inte möjligt"
+143 "Filen säkerhetskopierad"
+144 "%s expanderade till för många filnamn"
+145 "Endast vanliga filer och namngivna rör kan läsas"
+146 "%s: läslåset är otillgängligt"
+147 "Läser..."
+148 "%s: %lu rader, %lu tecken"
+149 "Inga bakgrundsfönster att visa"
+150 "Script kommandot finns bara i "vi" läge"
+151 "Inget kommando att exekvera"
+152 "shiftwidth flaggan satt till 0"
+153 "Talet har för stort värde"
+154 "Talet har för litet värde"
+155 "Reguljärt uttryck är givet; r flaggan är meningslös"
+156 "#, l och p flaggorna kan inte kombineras med c flaggan i "vi" läge"
+157 "Ingen matchande text funnen"
+158 "Inget tidigare märke har givits"
+159 "Det är färre än %s märken i stacken; använd :display t[ags]"
+160 "Det finns ingen fil %s i märkesstacken; använd :display t[ags]"
+161 "Tryck Enter för att fortsätta: "
+162 "%s: märke inte funnet"
+163 "%s: korrupt märke i %s"
+164 "%s: märkets radnummer är bortom filslutet"
+165 "Märkesstacken är tom"
+166 "%s: söksträngen inte funnen"
+167 "%d filer till att editera"
+168 "Buffert %s är tom"
+169 "Bekräfta ändring? [n]"
+170 "Avbruten"
+171 "Ingen tidigare buffert att exekvera"
+172 "Inget tidigare reguljärt uttryck"
+173 "%s kommandot kräver att en fil redan lästs in"
+174 "Användning: %s"
+175 "Visual kommandot kräver att open flaggan är satt"
+177 "Tom fil"
+178 "Ingen tidigare F, f, T eller t sökning"
+179 "%s inte funnen"
+180 "Ingen tidigare fil att editera"
+181 "Markören är inte i ett tal"
+182 "Det resulterande talet är för stort"
+183 "Det resulterande talet är för litet"
+184 "Inget matchande tecken på denna rad"
+185 "Matchande tecken inte funnet"
+186 "Det finns inga tecken att ersätta"
+187 "Det finns inget fönster att byta till"
+188 "Tecken efter söksträng, radoffset och/eller z kommandot"
+189 "Ingen tidigare söksträng"
+190 "Sökningen slog runt till ursprungliga positionen"
+191 "Förkortning överskred expanderingsgränsen: tecken har tagits bort"
+192 "Ogiltigt tecken; använd "quote" för att sätta in"
+193 "Redan i början på insättningen"
+194 "Inga fler tecken att ta bort"
+195 "Försök att gå bortom slutet på filen"
+196 "Försök att gå bortom slutet på raden"
+197 "Ingen förflyttning gjord"
+198 "Redan i början på filen"
+199 "Försök att gå före början på filen"
+200 "Redan i första kolumnen"
+201 "Buffertar måste anges före kommandot"
+202 "Redan i slutet av filen"
+203 "Redan på slutet av raden"
+204 "%s är inte ett "vi" kommando"
+205 "Användning: %s"
+206 "Inga tecken att ta bort"
+207 "Q kommandot kräver "ex" i terminalläge"
+208 "Inget kommando att repetera"
+209 "Filen är tom"
+210 "%s kan inte användas som ett förflyttningskommando"
+211 "Redan i kommando läge"
+212 "Markören är inte i ett ord"
+214 "Windows flaggans värde är för stor, största värde är %u"
+215 "Lägg till"
+216 "Ändra"
+217 "Kommando"
+218 "Sätt in"
+219 "Ersätt"
+220 "Förflyttning bortom fönsterslut"
+221 "Förflyttning till före fönstrets början"
+222 "Fönstret måste vara större än %d rader för delning"
+223 "Det finns inga fönster i bakgrunden"
+224 "Det finns inget fönster i bakgrunden som editerar filen %s"
+225 "Du får inte sätta ditt enda synliga fönster i bakgrunden"
+226 "Fönstret kan bara krympa till %d rader"
+227 "Fönstret kan inte krympa"
+228 "Fönstret kan inte växa"
+230 "Detta fönster kan inte pausas"
+231 "Avbrutet: omdefinierade tangenter ignorerade"
+232 "vi: temporärbuffertar inte frisläppta"
+233 "Denna terminal har ingen %s tangent"
+234 "Endast en buffert kan anges"
+235 "Talet är större än %lu"
+236 "Avbrutet"
+237 "Kan inte skapa temporär fil"
+238 "Warning: %s är inte en normal fil"
+239 "%s är redan låst, detta blir en icke skrivbar session"
+240 "%s: ta bort"
+241 "%s: stäng"
+242 "%s: ta bort"
+243 "%s: ta bort"
+244 "Ej skrivbar fil, filen inte sparad; använd ! för att skriva över"
+245 "Ej skrivbar fil, filen inte sparad"
+246 "%s finns, ej sparad; använd ! för att utföra operationen"
+247 "%s finns, filen inte sparad"
+248 "Ofullständig fil, filen inte sparad, använd ! för att skriva över"
+249 "Ofullständig fil, filen inte sparad"
+250 "%s: filen ändrad efter denna kopia togs; använd ! för att utföra operationen"
+251 "%s: filen ändrad efter denna kopia togs"
+252 "%s: skrivlåset är otillgängligt"
+253 "Skriver..."
+254 "%s: VARNING: FILEN TRUNKERAD"
+255 "Redan vid första märket i denna grupp"
+256 "%s: ny fil: %lu rader, %lu tecken"
+257 "%s: %lu rader, %lu tecken"
+258 "%s expanderade till för många filnamn"
+259 "%s är inte en normal fil"
+260 "%s ägs inte av dig"
+261 "%s är åtkomstbar av andra än ägaren"
+262 "Filen har ändrats efter den sparats; spara eller använd !"
+263 "Filen har ändrats efter den sparats; spara eller använd :edit!"
+264 "Filen har ändrats efter den sparats; spara eller använd !"
+265 "Filen är temporär; exit kastar bort ändringarna"
+266 "Ej skrivbar fil, ändringar har inte automatsparats"
+267 "Loggningen startar om"
+268 "bekräfta? [ynq]"
+269 "Tryck på en tangent för att fortsätta: "
+270 "Tryck på en tangent för att fortsätta [: för att ge fler kommandon]: "
+271 "Tryck på en tangent för att fortsätta [q för att avsluta]: "
+272 "Den formen av %s kräver "ex" i terminalläge"
+273 "Går till "ex" inmatningsläge."
+274 "Kommandot misslyckades, ingen fil inläst ännu."
+275 " forts?"
+276 "Oväntad teckenhändelse"
+277 "Oväntad filslutshändelse"
+278 "Sökningen hittade ingenting"
+279 "Oväntad avbrottshändelse"
+280 "Oväntad avslutningshändelse"
+281 "Oväntad omritningshändelse"
+282 "Redan vid sista märket i denna grupp"
+283 "%s kommandot kräver "ex" i terminalläge"
+284 "Den formen av %s är inte tillgänglig när secure edit flaggan är satt"
+285 "Oväntad stränghändelse"
+286 "Oväntad tidshändelse"
+287 "Oväntad skrivhändelse"
+289 "Skalexpansion är inte tillgänglig när secure edit flaggan är satt"
+290 "%s kommandot är inte tillgänglig när secure edit flaggan är satt"
+291 "set: %s kan inte slås av"
+292 "Fönstret för litet."
+293 "tillagda"
+294 "ändrade"
+295 "borttagna"
+296 "ihopsatta"
+297 "flyttade"
+298 "flyttade"
+299 "inklistrade"
+300 "rad"
+301 "rader"
+302 "Vi har inte länkats med en Tcl tolk"
+303 "Filen har ändrats efter den sparats."
+304 "Skalexpansion misslyckades"
+305 "Ingen %s edit flagga given"
+306 "Vi har inte länkats med en Perl tolk"
+307 "Inga "ex" kommandon att exekvera"
+308 "Tryck <CR> för att exekvera kommando, :q för att avsluta"
+309 "Gör "cscope help" för hjälp"
+310 "Inga cscope kopplingar körs"
+311 "%s: okänd söktyp: använd en av %s"
+312 "%d: ingen sådan cscope session"
+313 "set: %s flaggan får aldrig slås på"
+314 "set: %s flaggan får aldrig sättas till 0"
+315 "%s: tillagt: %lu rader, %lu tecken"
+316 "Oväntad storleksändring"
+317 "%d filer att editera"
diff --git a/dist/nvi/catalog/swedish.owner b/dist/nvi/catalog/swedish.owner
new file mode 100644 (file)
index 0000000..2b36f2d
--- /dev/null
@@ -0,0 +1 @@
+Jan Djarv <jan.djarv@mbox200.swipnet.se>
diff --git a/dist/nvi/cl/README.signal b/dist/nvi/cl/README.signal
new file mode 100644 (file)
index 0000000..cf17a6b
--- /dev/null
@@ -0,0 +1,174 @@
+#      Id: README.signal,v 10.1 1995/06/23 10:28:17 bostic Exp (Berkeley) Date: 1995/06/23 10:28:17
+
+There are six (normally) asynchronous actions about which vi cares:
+SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP and SIGWINCH.
+
+The assumptions:
+       1: The DB routines are not reentrant.
+       2: The curses routines may not be reentrant.
+       3: Neither DB nor curses will restart system calls.
+
+XXX
+Note, most C library functions don't restart system calls.  So, we should
+*probably* start blocking around any imported function that we don't know
+doesn't make a system call.  This is going to be a genuine annoyance...
+
+SIGHUP, SIGTERM
+       Used for file recovery.  The DB routines can't be reentered, nor
+       can they handle interrupted system calls, so the vi routines that
+       call DB block signals.  This means that DB routines could be
+       called at interrupt time, if necessary.
+
+SIGQUIT
+       Disabled by the signal initialization routines.  Historically, ^\
+       switched vi into ex mode, and we continue that practice.
+
+SIGWINCH:
+       The interrupt routine sets a global bit which is checked by the
+       key-read routine, so there are no reentrancy issues.  This means
+       that the screen will not resize until vi runs out of keys, but
+       that doesn't seem like a problem.
+
+SIGINT and SIGTSTP are a much more difficult issue to resolve.  Vi has
+to permit the user to interrupt long-running operations.  Generally, a
+search, substitution or read/write is done on a large file, or, the user
+creates a key mapping with an infinite loop.  This problem will become
+worse as more complex semantics are added to vi, especially things like
+making it a pure text widget.  There are four major solutions on the table,
+each of which have minor permutations.
+
+1:     Run in raw mode.
+
+       The up side is that there's no asynchronous behavior to worry about,
+       and obviously no reentrancy problems.  The down side is that it's easy
+       to misinterpret characters (e.g. :w big_file^Mi^V^C is going to look
+       like an interrupt) and it's easy to get into places where we won't see
+       interrupt characters (e.g. ":map a ixx^[hxxaXXX" infinitely loops in
+       historic implementations of vi).  Periodically reading the terminal
+       input buffer might solve the latter problem, but it's not going to be
+       pretty.
+
+       Also, we're going to be checking for ^C's and ^Z's both, all over
+       the place -- I hate to litter the source code with that.  For example,
+       the historic version of vi didn't permit you to suspend the screen if
+       you were on the colon command line.  This isn't right.  ^Z isn't a vi
+       command, it's a terminal event.  (Dammit.)
+
+2:     Run in cbreak mode.  There are two problems in this area.  First, the
+       current curses implementations (both System V and Berkeley) don't give
+       you clean cbreak modes. For example, the IEXTEN bit is left on, turning
+       on DISCARD and LNEXT.  To clarify, what vi WANTS is 8-bit clean, with
+       the exception that flow control and signals are turned on, and curses
+       cbreak mode doesn't give you this.
+
+       We can either set raw mode and twiddle the tty, or cbreak mode and
+       twiddle the tty.  I chose to use raw mode, on the grounds that raw
+       mode is better defined and I'm less likely to be surprised by a curses
+       implementation down the road.  The twiddling consists of setting ISIG,
+       IXON/IXOFF, and disabling some of the interrupt characters (see the
+       comments in cl_init.c).  This is all found in historic System V (SVID
+       3) and POSIX 1003.1-1992, so it should be fairly portable.
+
+       The second problem is that vi permits you to enter literal signal
+       characters, e.g. ^V^C.  There are two possible solutions.  First, you
+       can turn off signals when you get a ^V, but that means that a network
+       packet containing ^V and ^C will lose, since the ^C may take effect
+       before vi reads the ^V.  (This is particularly problematic if you're
+       talking over a protocol that recognizes signals locally and sends OOB
+       packets when it sees them.)  Second, you can turn the ^C into a literal
+       character in vi, but that means that there's a race between entering
+       ^V<character>^C, i.e. the sequence may end up being ^V^C<character>.
+       Also, the second solution doesn't work for flow control characters, as
+       they aren't delivered to the program as signals.
+
+       Generally, this is what historic vi did.  (It didn't have the curses
+       problems because it didn't use curses.)  It entered signals following
+       ^V characters into the input stream, (which is why there's no way to
+       enter a literal flow control character).
+
+3:     Run in mostly raw mode; turn signals on when doing an operation the
+       user might want to interrupt, but leave them off most of the time.
+
+       This works well for things like file reads and writes.  This doesn't
+       work well for trying to detect infinite maps.  The problem is that
+       you can write the code so that you don't have to turn on interrupts
+       per keystroke, but the code isn't pretty and it's hard to make sure
+       that an optimization doesn't cover up an infinite loop.  This also
+       requires interaction or state between the vi parser and the key
+       reading routines, as an infinite loop may still be returning keys
+       to the parser.
+
+       Also, if the user inserts an interrupt into the tty queue while the
+       interrupts are turned off, the key won't be treated as an interrupt,
+       and requiring the user to pound the keyboard to catch an interrupt
+       window is nasty.
+
+4:     Run in mostly raw mode, leaving signals on all of the time.  Done
+       by setting raw mode, and twiddling the tty's termios ISIG bit.
+
+       This works well for the interrupt cases, because the code only has
+       to check to see if the interrupt flag has been set, and can otherwise
+       ignore signals.  It's also less likely that we'll miss a case, and we
+       don't have to worry about synchronizing between the vi parser and the
+       key read routines.
+
+       The down side is that we have to turn signals off if the user wants
+       to enter a literal character (e.g. ^V^C).  If the user enters the
+       combination fast enough, or as part of a single network packet,
+       the text input routines will treat it as a signal instead of as a
+       literal character.  To some extent, we have this problem already,
+       since we turn off flow control so that the user can enter literal
+       XON/XOFF characters.
+
+       This is probably the easiest to code, and provides the smoothest
+       programming interface.
+
+There are a couple of other problems to consider.
+
+First, System V's curses doesn't handle SIGTSTP correctly.  If you use the
+newterm() interface, the TSTP signal will leave you in raw mode, and the
+final endwin() will leave you in the correct shell mode.  If you use the
+initscr() interface, the TSTP signal will return you to the correct shell
+mode, but the final endwin() will leave you in raw mode.  There you have
+it: proof that drug testing is not making any significant headway in the
+computer industry.  The 4BSD curses is deficient in that it does not have
+an interface to the terminal keypad.  So, regardless, we have to do our
+own SIGTSTP handling.
+
+The problem with this is that if we do our own SIGTSTP handling, in either
+models #3 or #4, we're going to have to call curses routines at interrupt
+time, which means that we might be reentering curses, which is something we
+don't want to do.
+
+Second, SIGTSTP has its own little problems.  It's broadcast to the entire
+process group, not sent to a single process.  The scenario goes something
+like this: the shell execs the mail program, which execs vi.  The user hits
+^Z, and all three programs get the signal, in some random order.  The mail
+program goes to sleep immediately (since it probably didn't have a SIGTSTP
+handler in place).  The shell gets a SIGCHLD, does a wait, and finds out
+that the only child in its foreground process group (of which it's aware)
+is asleep.  It then optionally resets the terminal (because the modes aren't
+how it left them), and starts prompting the user for input.  The problem is
+that somewhere in the middle of all of this, vi is resetting the terminal,
+and getting ready to send a SIGTSTP to the process group in order to put
+itself to sleep.  There's a solution to all of this: when vi starts, it puts
+itself into its own process group, and then only it (and possible child
+processes) receive the SIGTSTP.  This permits it to clean up the terminal
+and switch back to the original process group, where it sends that process
+group a SIGTSTP, putting everyone to sleep and waking the shell.
+
+Third, handing SIGTSTP asynchronously is further complicated by the child
+processes vi may fork off.  If vi calls ex, ex resets the terminal and
+starts running some filter, and SIGTSTP stops them both, vi has to know
+when it restarts that it can't repaint the screen until ex's child has
+finished running.  This is solveable, but it's annoying.
+
+Well, somebody had to make a decision, and this is the way it's going to be
+(unless I get talked out of it).  SIGINT is handled asynchronously, so
+that we can pretty much guarantee that the user can interrupt any operation
+at any time.  SIGTSTP is handled synchronously, so that we don't have to
+reenter curses and so that we don't have to play the process group games.
+^Z is recognized in the standard text input and command modes.  (^Z should
+also be recognized during operations that may potentially take a long time.
+The simplest solution is probably to twiddle the tty, install a handler for
+SIGTSTP, and then restore normal tty modes when the operation is complete.)
diff --git a/dist/nvi/cl/cl.h b/dist/nvi/cl/cl.h
new file mode 100644 (file)
index 0000000..d0e9ea5
--- /dev/null
@@ -0,0 +1,120 @@
+/*     $NetBSD: cl.h,v 1.2 2010/02/03 15:34:37 roy Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: cl.h,v 10.32 2001/08/28 11:33:40 skimo Exp (Berkeley) Date: 2001/08/28 11:33:40
+ */
+
+/* Avoid clash on OSF1 */
+#undef DB
+
+#ifdef USE_SLANG_CURSES
+#include <slcurses.h>
+#else
+#ifdef HAVE_NCURSESW_NCURSES_H /* { */
+#include <ncursesw/ncurses.h>
+#else /* } { */
+#ifdef HAVE_NCURSES_H /* { */
+#include <ncurses.h>
+#else /* } { */
+#include <curses.h>
+#include <term.h>
+#include <termcap.h>
+#endif /* } */
+#endif
+#endif
+
+typedef struct _cl_private {
+       char     ibuf[256];     /* Input keys. */
+
+       size_t   skip;          /* Remaining keys. */
+
+       CONVWIN cw;             /* Conversion buffer. */
+
+       int      eof_count;     /* EOF count. */
+
+       struct termios orig;    /* Original terminal values. */
+       struct termios ex_enter;/* Terminal values to enter ex. */
+       struct termios vi_enter;/* Terminal values to enter vi. */
+
+       char    *el;            /* Clear to EOL terminal string. */
+       char    *cup;           /* Cursor movement terminal string. */
+       char    *cuu1;          /* Cursor up terminal string. */
+       char    *rmso, *smso;   /* Inverse video terminal strings. */
+       char    *smcup, *rmcup; /* Terminal start/stop strings. */
+
+       char    *oname;         /* Original screen window name. */
+
+       SCR     *focus;         /* Screen that has the "focus". */
+
+       int      killersig;     /* Killer signal. */
+#define        INDX_HUP        0
+#define        INDX_INT        1
+#define        INDX_TERM       2
+#define        INDX_WINCH      3
+#define        INDX_MAX        4       /* Original signal information. */
+       struct sigaction oact[INDX_MAX];
+
+       enum {                  /* Tty group write mode. */
+           TGW_UNKNOWN=0, TGW_SET, TGW_UNSET } tgw;
+
+       enum {                  /* Terminal initialization strings. */
+           TE_SENT=0, TI_SENT } ti_te;
+
+#define        CL_IN_EX        0x0001  /* Currently running ex. */
+#define        CL_LAYOUT       0x0002  /* Screen layout changed. */
+#define        CL_RENAME       0x0004  /* X11 xterm icon/window renamed. */
+#define        CL_RENAME_OK    0x0008  /* User wants the windows renamed. */
+#define        CL_SCR_EX_INIT  0x0010  /* Ex screen initialized. */
+#define        CL_SCR_VI_INIT  0x0020  /* Vi screen initialized. */
+#define        CL_SIGHUP       0x0040  /* SIGHUP arrived. */
+#define        CL_SIGINT       0x0080  /* SIGINT arrived. */
+#define        CL_SIGTERM      0x0100  /* SIGTERM arrived. */
+#define        CL_SIGWINCH     0x0200  /* SIGWINCH arrived. */
+#define        CL_STDIN_TTY    0x0400  /* Talking to a terminal. */
+       u_int32_t flags;
+} CL_PRIVATE;
+
+#define        CLP(sp)         ((CL_PRIVATE *)((sp)->gp->cl_private))
+#define        GCLP(gp)        ((CL_PRIVATE *)gp->cl_private)
+#define        CLSP(sp)        ((WINDOW *)((sp)->cl_private))
+
+/* Return possibilities from the keyboard read routine. */
+typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_INTR, INP_TIMEOUT } input_t;
+
+/* The screen position relative to a specific window. */
+/*
+#define        RCNO(sp, cno)   (sp)->coff + (cno)
+#define        RLNO(sp, lno)   (sp)->roff + (lno)
+*/
+#define        RCNO(sp, cno)   (cno)
+#define        RLNO(sp, lno)   (lno)
+
+/*
+ * XXX
+ * Some implementations of curses.h don't define these for us.  Used for
+ * compatibility only.
+ */
+#ifndef TRUE
+#define        TRUE    1
+#endif
+#ifndef FALSE
+#define        FALSE   0
+#endif
+
+#include "extern.h"
+
+#ifdef USE_PERL_SETENV
+#include "../perl_api/extern.h"
+#define cl_setenv(sp,name,val) perl_setenv(sp,name,val)
+#define cl_unsetenv(sp,name)   perl_setenv(sp,name,NULL)
+#else
+#define cl_setenv(sp,name,val) setenv(name,val,1)
+#define cl_unsetenv(sp,name)   unsetenv(name)
+#endif
diff --git a/dist/nvi/cl/cl_bsd.c b/dist/nvi/cl/cl_bsd.c
new file mode 100644 (file)
index 0000000..e4f20b7
--- /dev/null
@@ -0,0 +1,350 @@
+/*     $NetBSD: cl_bsd.c,v 1.4 2010/02/03 15:34:37 roy Exp $ */
+
+/*-
+ * Copyright (c) 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cl_bsd.c,v 8.32 2000/12/01 13:56:17 skimo Exp (Berkeley) Date: 2000/12/01 13:56:17";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "cl.h"
+
+#ifndef HAVE_CURSES_SETUPTERM
+static char    *ke;                            /* Keypad on. */
+static char    *ks;                            /* Keypad off. */
+static char    *vb;                            /* Visible bell string. */
+#endif
+
+/*
+ * HP's support the entire System V curses package except for the tigetstr
+ * and tigetnum functions.  Ultrix supports the BSD curses package except
+ * for the idlok function.  Cthulu only knows why.  Break things up into a
+ * minimal set of functions.
+ */
+
+#ifndef HAVE_CURSES_WADDNSTR
+/*
+ * waddnstr --
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_WADDNSTR
+ * PUBLIC: int waddnstr __P((WINDOW*, char *, int));
+ * PUBLIC: #endif
+ */
+int
+waddnstr(w, s, n)
+       WINDOW *w;
+       char *s;
+       int n;
+{
+       int ch;
+
+       while (n-- && (ch = *s++))
+               waddch(w, ch);
+       return (OK);
+}
+#endif
+
+#ifndef        HAVE_CURSES_BEEP
+/*
+ * beep --
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_BEEP
+ * PUBLIC: void beep __P((void));
+ * PUBLIC: #endif
+ */
+void
+beep()
+{
+       (void)write(1, "\007", 1);      /* '\a' */
+}
+#endif /* !HAVE_CURSES_BEEP */
+
+#ifndef        HAVE_CURSES_FLASH
+/*
+ * flash --
+ *     Flash the screen.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_FLASH
+ * PUBLIC: void flash __P((void));
+ * PUBLIC: #endif
+ */
+void
+flash()
+{
+       if (vb != NULL) {
+               (void)tputs(vb, 1, cl_putchar);
+               (void)fflush(stdout);
+       } else
+               beep();
+}
+#endif /* !HAVE_CURSES_FLASH */
+
+#ifndef        HAVE_CURSES_IDLOK
+/*
+ * idlok --
+ *     Turn on/off hardware line insert/delete.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_IDLOK
+ * PUBLIC: void idlok __P((WINDOW *, int));
+ * PUBLIC: #endif
+ */
+void
+idlok(win, bf)
+       WINDOW *win;
+       int bf;
+{
+       return;
+}
+#endif /* !HAVE_CURSES_IDLOK */
+
+#ifndef        HAVE_CURSES_KEYPAD
+/*
+ * keypad --
+ *     Put the keypad/cursor arrows into or out of application mode.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_KEYPAD
+ * PUBLIC: int keypad __P((void *, int));
+ * PUBLIC: #endif
+ */
+int
+keypad(a, on)
+       void *a;
+       int on;
+{
+       char *p;
+
+       if ((p = tigetstr(on ? "smkx" : "rmkx")) != (char *)-1) {
+               (void)tputs(p, 0, cl_putchar);
+               (void)fflush(stdout);
+       }
+       return (0);
+}
+#endif /* !HAVE_CURSES_KEYPAD */
+
+#ifndef        HAVE_CURSES_NEWTERM
+/*
+ * newterm --
+ *     Create a new curses screen.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_NEWTERM
+ * PUBLIC: void *newterm __P((const char *, FILE *, FILE *));
+ * PUBLIC: #endif
+ */
+void *
+newterm(a, b, c)
+       const char *a;
+       FILE *b, *c;
+{
+       return (initscr());
+}
+#endif /* !HAVE_CURSES_NEWTERM */
+
+#ifndef        HAVE_CURSES_SETUPTERM
+/*
+ * setupterm --
+ *     Set up terminal.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_SETUPTERM
+ * PUBLIC: void setupterm __P((char *, int, int *));
+ * PUBLIC: #endif
+ */
+void
+setupterm(ttype, fno, errp)
+       char *ttype;
+       int fno, *errp;
+{
+       static char buf[2048];
+       char *p;
+
+       if ((*errp = tgetent(buf, ttype)) > 0) {
+               if (ke != NULL)
+                       free(ke);
+               ke = ((p = tigetstr("rmkx")) == (char *)-1) ?
+                   NULL : strdup(p);
+               if (ks != NULL)
+                       free(ks);
+               ks = ((p = tigetstr("smkx")) == (char *)-1) ?
+                   NULL : strdup(p);
+               if (vb != NULL)
+                       free(vb);
+               vb = ((p = tigetstr("flash")) == (char *)-1) ?
+                   NULL : strdup(p);
+       }
+}
+#endif /* !HAVE_CURSES_SETUPTERM */
+
+#ifndef        HAVE_CURSES_TIGETSTR
+/* Terminfo-to-termcap translation table. */
+typedef struct _tl {
+       const char *terminfo;           /* Terminfo name. */
+       const char *termcap;            /* Termcap name. */
+} TL;
+static const TL list[] = {
+       { "cols",       "co", },        /* Terminal columns. */
+       { "cup",        "cm", },        /* Cursor up. */
+       { "cuu1",       "up", },        /* Cursor up. */
+       { "el",         "ce", },        /* Clear to end-of-line. */
+       { "flash",      "vb", },        /* Visible bell. */
+       { "kcub1",      "kl", },        /* Cursor left. */
+       { "kcud1",      "kd", },        /* Cursor down. */
+       { "kcuf1",      "kr", },        /* Cursor right. */
+       { "kcuu1",      "ku", },        /* Cursor up. */
+       { "kdch1",      "kD", },        /* Delete character. */
+       { "kdl1",       "kL", },        /* Delete line. */
+       { "ked",        "kS", },        /* Delete to end of screen. */
+       { "kel",        "kE", },        /* Delete to eol. */
+       { "kend",       "@7", },        /* Go to eol. */
+       { "khome",      "kh", },        /* Go to sol. */
+       { "kich1",      "kI", },        /* Insert at cursor. */
+       { "kil1",       "kA", },        /* Insert line. */
+       { "kind",       "kF", },        /* Scroll down. */
+       { "kll",        "kH", },        /* Go to eol. */
+       { "knp",        "kN", },        /* Page down. */
+       { "kpp",        "kP", },        /* Page up. */
+       { "kri",        "kR", },        /* Scroll up. */
+       { "lines",      "li", },        /* Terminal lines. */
+       { "rmcup",      "te", },        /* Terminal end string. */
+       { "rmkx",       "ke", },        /* Exit "keypad-transmit" mode. */
+       { "rmso",       "se", },        /* Standout end. */
+       { "smcup",      "ti", },        /* Terminal initialization string. */
+       { "smkx",       "ks", },        /* Enter "keypad-transmit" mode. */
+       { "smso",       "so", },        /* Standout begin. */
+};
+
+#ifdef _AIX
+/*
+ * AIX's implementation for function keys greater than 10 is different and
+ * only goes as far as 36.
+ */
+static const char codes[] = {
+/*  0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
+/* 11-20 */ '<', '>', '!', '@', '#', '$', '%', '^', '&', '*',
+/* 21-30 */ '(', ')', '-', '_', '+', ',', ':', '?', '[', ']',
+/* 31-36 */ '{', '}', '|', '~', '/', '='
+};
+
+#else
+
+/*
+ * !!!
+ * Historically, the 4BSD termcap code didn't support functions keys greater
+ * than 9.  This was silently enforced -- asking for key k12 would return the
+ * value for k1.  We try and get around this by using the tables specified in
+ * the terminfo(TI_ENV) man page from the 3rd Edition SVID.  This assumes the
+ * implementors of any System V compatibility code or an extended termcap used
+ * those codes.
+ */
+static const char codes[] = {
+/*  0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
+/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
+/* 20-63 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+           'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+           'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+           'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+};
+#endif /* _AIX */
+
+/*
+ * lcmp --
+ *     list comparison routine for bsearch.
+ */
+static int
+lcmp(const void *a, const void *b)
+{
+       return (strcmp(a, ((const TL *)b)->terminfo));
+}
+
+/*
+ * tigetstr --
+ *
+ * Vendors put the prototype for tigetstr into random include files, including
+ * <term.h>, which we can't include because it makes other systems unhappy.
+ * Try and work around the problem, since we only care about the return value.
+ *
+ * PUBLIC: #ifdef HAVE_CURSES_TIGETSTR
+ * PUBLIC: char *tigetstr();
+ * PUBLIC: #else
+ * PUBLIC: char *tigetstr __P((char *));
+ * PUBLIC: #endif
+ */
+char *
+tigetstr(name)
+       const char *name;
+{
+       static char sbuf[256];
+       TL *tlp;
+       int n;
+       char *p, mykeyname[3];
+
+       if ((tlp = bsearch(name,
+           list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) == NULL) {
+#ifdef _AIX
+               if (name[0] == 'k' &&
+                   name[1] == 'f' && (n = atoi(name + 2)) <= 36) {
+                       mykeyname[0] = 'k';
+                       mykeyname[1] = codes[n];
+                       mykeyname[2] = '\0';
+#else
+               if (name[0] == 'k' &&
+                   name[1] == 'f' && (n = atoi(name + 2)) <= 63) {
+                       mykeyname[0] = n <= 10 ? 'k' : 'F';
+                       mykeyname[1] = codes[n];
+                       mykeyname[2] = '\0';
+#endif
+                       name = mykeyname;
+               }
+       } else
+               name = tlp->termcap;
+
+       p = sbuf;
+#ifdef _AIX
+       return ((p = tgetstr(name, &p)) == NULL ? (char *)-1 : strcpy(sbuf, p));
+#else
+       return (tgetstr(name, &p) == NULL ? (char *)-1 : sbuf);
+#endif
+}
+
+/*
+ * tigetnum --
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_TIGETSTR
+ * PUBLIC: int tigetnum __P((char *));
+ * PUBLIC: #endif
+ */
+int
+tigetnum(name)
+       const char *name;
+{
+       TL *tlp;
+       int val;
+
+       if ((tlp = bsearch(name,
+           list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) != NULL) {
+               name = tlp->termcap;
+       }
+
+       return ((val = tgetnum(name)) == -1 ? -2 : val);
+}
+#endif /* !HAVE_CURSES_TIGETSTR */
+
diff --git a/dist/nvi/cl/cl_funcs.c b/dist/nvi/cl/cl_funcs.c
new file mode 100644 (file)
index 0000000..10ed2bc
--- /dev/null
@@ -0,0 +1,894 @@
+/*     $NetBSD: cl_funcs.c,v 1.4 2009/11/15 18:43:28 dsl Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cl_funcs.c,v 10.72 2002/03/02 23:18:33 skimo Exp (Berkeley) Date: 2002/03/02 23:18:33";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "cl.h"
+
+static void cl_rdiv __P((SCR *));
+
+static int 
+addstr4(SCR *sp, const void *str, size_t len, int wide)
+{
+       CL_PRIVATE *clp;
+       WINDOW *win;
+       size_t y, x;
+       int iv;
+
+       clp = CLP(sp);
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+
+       /*
+        * If ex isn't in control, it's the last line of the screen and
+        * it's a split screen, use inverse video.
+        */
+       iv = 0;
+       getyx(win, y, x);
+       if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
+           y == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) {
+               iv = 1;
+               (void)wstandout(win);
+       }
+
+#ifdef USE_WIDECHAR
+       if (wide) {
+           if (waddnwstr(win, str, len) == ERR)
+               return (1);
+       } else 
+#endif
+           if (waddnstr(win, str, len) == ERR)
+                   return (1);
+
+       if (iv)
+               (void)wstandend(win);
+       return (0);
+}
+
+/*
+ * cl_waddstr --
+ *     Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int cl_waddstr __P((SCR *, const CHAR_T *, size_t));
+ */
+int
+cl_waddstr(SCR *sp, const CHAR_T *str, size_t len)
+{
+    return addstr4(sp, (const void *)str, len, 1);
+}
+
+/*
+ * cl_addstr --
+ *     Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int cl_addstr __P((SCR *, const char *, size_t));
+ */
+int
+cl_addstr(SCR *sp, const char *str, size_t len)
+{
+    return addstr4(sp, (const void *)str, len, 0);
+}
+
+/*
+ * cl_attr --
+ *     Toggle a screen attribute on/off.
+ *
+ * PUBLIC: int cl_attr __P((SCR *, scr_attr_t, int));
+ */
+int
+cl_attr(SCR *sp, scr_attr_t attribute, int on)
+{
+       CL_PRIVATE *clp;
+       WINDOW *win;
+
+       clp = CLP(sp);
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+
+       switch (attribute) {
+       case SA_ALTERNATE:
+       /*
+        * !!!
+        * There's a major layering violation here.  The problem is that the
+        * X11 xterm screen has what's known as an "alternate" screen.  Some
+        * xterm termcap/terminfo entries include sequences to switch to/from
+        * that alternate screen as part of the ti/te (smcup/rmcup) strings.
+        * Vi runs in the alternate screen, so that you are returned to the
+        * same screen contents on exit from vi that you had when you entered
+        * vi.  Further, when you run :shell, or :!date or similar ex commands,
+        * you also see the original screen contents.  This wasn't deliberate
+        * on vi's part, it's just that it historically sent terminal init/end
+        * sequences at those times, and the addition of the alternate screen
+        * sequences to the strings changed the behavior of vi.  The problem
+        * caused by this is that we don't want to switch back to the alternate
+        * screen while getting a new command from the user, when the user is
+        * continuing to enter ex commands, e.g.:
+        *
+        *      :!date                          <<< switch to original screen
+        *      [Hit return to continue]        <<< prompt user to continue
+        *      :command                        <<< get command from user
+        *
+        * Note that the :command input is a true vi input mode, e.g., input
+        * maps and abbreviations are being done.  So, we need to be able to
+        * switch back into the vi screen mode, without flashing the screen. 
+        *
+        * To make matters worse, the curses initscr() and endwin() calls will
+        * do this automatically -- so, this attribute isn't as controlled by
+        * the higher level screen as closely as one might like.
+        */
+       if (on) {
+               if (clp->ti_te != TI_SENT) {
+                       clp->ti_te = TI_SENT;
+                       if (clp->smcup == NULL)
+                               (void)cl_getcap(sp, "smcup", &clp->smcup);
+                       if (clp->smcup != NULL)
+                               (void)tputs(clp->smcup, 1, cl_putchar);
+               }
+       } else
+               if (clp->ti_te != TE_SENT) {
+                       clp->ti_te = TE_SENT;
+                       if (clp->rmcup == NULL)
+                               (void)cl_getcap(sp, "rmcup", &clp->rmcup);
+                       if (clp->rmcup != NULL)
+                               (void)tputs(clp->rmcup, 1, cl_putchar);
+                       (void)fflush(stdout);
+               }
+               (void)fflush(stdout);
+               break;
+       case SA_INVERSE:
+               if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) {
+                       if (clp->smso == NULL)
+                               return (1);
+                       if (on)
+                               (void)tputs(clp->smso, 1, cl_putchar);
+                       else
+                               (void)tputs(clp->rmso, 1, cl_putchar);
+                       (void)fflush(stdout);
+               } else {
+                       if (on)
+                               (void)wstandout(win);
+                       else
+                               (void)wstandend(win);
+               }
+               break;
+       default:
+               abort();
+       }
+       return (0);
+}
+
+/*
+ * cl_baud --
+ *     Return the baud rate.
+ *
+ * PUBLIC: int cl_baud __P((SCR *, u_long *));
+ */
+int
+cl_baud(SCR *sp, u_long *ratep)
+{
+       CL_PRIVATE *clp;
+
+       /*
+        * XXX
+        * There's no portable way to get a "baud rate" -- cfgetospeed(3)
+        * returns the value associated with some #define, which we may
+        * never have heard of, or which may be a purely local speed.  Vi
+        * only cares if it's SLOW (w300), slow (w1200) or fast (w9600).
+        * Try and detect the slow ones, and default to fast.
+        */
+       clp = CLP(sp);
+       switch (cfgetospeed(&clp->orig)) {
+       case B50:
+       case B75:
+       case B110:
+       case B134:
+       case B150:
+       case B200:
+       case B300:
+       case B600:
+               *ratep = 600;
+               break;
+       case B1200:
+               *ratep = 1200;
+               break;
+       default:
+               *ratep = 9600;
+               break;
+       }
+       return (0);
+}
+
+/*
+ * cl_bell --
+ *     Ring the bell/flash the screen.
+ *
+ * PUBLIC: int cl_bell __P((SCR *));
+ */
+int
+cl_bell(SCR *sp)
+{
+       if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE | SC_SCR_EX))
+               (void)write(STDOUT_FILENO, "\07", 1);           /* \a */
+       else {
+               /*
+                * Vi has an edit option which determines if the terminal
+                * should be beeped or the screen flashed.
+                */
+               if (O_ISSET(sp, O_FLASH))
+                       (void)flash();
+               else
+                       (void)beep();
+       }
+       return (0);
+}
+
+/*
+ * cl_clrtoeol --
+ *     Clear from the current cursor to the end of the line.
+ *
+ * PUBLIC: int cl_clrtoeol __P((SCR *));
+ */
+int
+cl_clrtoeol(SCR *sp)
+{
+       WINDOW *win;
+#if 0
+       size_t spcnt, y, x;
+#endif
+
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+
+#if 0
+       if (IS_VSPLIT(sp)) {
+               /* The cursor must be returned to its original position. */
+               getyx(win, y, x);
+               for (spcnt = (sp->coff + sp->cols) - x; spcnt > 0; --spcnt)
+                       (void)waddch(win, ' ');
+               (void)wmove(win, y, x);
+               return (0);
+       } else
+#endif
+               return (wclrtoeol(win) == ERR);
+}
+
+/*
+ * cl_cursor --
+ *     Return the current cursor position.
+ *
+ * PUBLIC: int cl_cursor __P((SCR *, size_t *, size_t *));
+ */
+int
+cl_cursor(SCR *sp, size_t *yp, size_t *xp)
+{
+       WINDOW *win;
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+       /*
+        * The curses screen support splits a single underlying curses screen
+        * into multiple screens to support split screen semantics.  For this
+        * reason the returned value must be adjusted to be relative to the
+        * current screen, and not absolute.  Screens that implement the split
+        * using physically distinct screens won't need this hack.
+        */
+       getyx(win, *yp, *xp);
+       /*
+       *yp -= sp->roff;
+       *xp -= sp->coff;
+       */
+       return (0);
+}
+
+/*
+ * cl_deleteln --
+ *     Delete the current line, scrolling all lines below it.
+ *
+ * PUBLIC: int cl_deleteln __P((SCR *));
+ */
+int
+cl_deleteln(SCR *sp)
+{
+       CHAR_T ch;
+       CL_PRIVATE *clp;
+       WINDOW *win;
+       size_t col, lno, spcnt, y, x;
+
+       clp = CLP(sp);
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+
+       /*
+        * This clause is required because the curses screen uses reverse
+        * video to delimit split screens.  If the screen does not do this,
+        * this code won't be necessary.
+        *
+        * If the bottom line was in reverse video, rewrite it in normal
+        * video before it's scrolled.
+        *
+        * Check for the existence of a chgat function; XSI requires it, but
+        * historic implementations of System V curses don't.   If it's not
+        * a #define, we'll fall back to doing it by hand, which is slow but
+        * acceptable.
+        *
+        * By hand means walking through the line, retrieving and rewriting
+        * each character.  Curses has no EOL marker, so track strings of
+        * spaces, and copy the trailing spaces only if there's a non-space
+        * character following.
+        */
+       if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
+               getyx(win, y, x);
+#ifdef mvchgat
+               mvwchgat(win, RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL);
+#else
+               for (lno = RLNO(sp, LASTLINE(sp)), col = spcnt = 0;;) {
+                       (void)wmove(win, lno, col);
+                       ch = winch(win);
+                       if (isblank(ch))
+                               ++spcnt;
+                       else {
+                               (void)wmove(win, lno, col - spcnt);
+                               for (; spcnt > 0; --spcnt)
+                                       (void)waddch(win, ' ');
+                               (void)waddch(win, ch);
+                       }
+                       if (++col >= sp->cols)
+                               break;
+               }
+#endif
+               (void)wmove(win, y, x);
+       }
+
+       /*
+        * The bottom line is expected to be blank after this operation,
+        * and other screens must support that semantic.
+        */
+       return (wdeleteln(win) == ERR);
+}
+
+/* 
+ * cl_discard --
+ *     Discard a screen.
+ *
+ * PUBLIC: int cl_discard __P((SCR *, SCR **));
+ */
+int
+cl_discard(SCR *discardp, SCR **acquirep)
+{
+       CL_PRIVATE *clp;
+       SCR*    tsp;
+
+       if (discardp) {
+           clp = CLP(discardp);
+           F_SET(clp, CL_LAYOUT);
+
+           if (CLSP(discardp)) {
+                   delwin(CLSP(discardp));
+                   discardp->cl_private = NULL;
+           }
+       }
+
+       /* no screens got a piece; we're done */
+       if (!acquirep) 
+               return 0;
+
+       for (; (tsp = *acquirep) != NULL; ++acquirep) {
+               clp = CLP(tsp);
+               F_SET(clp, CL_LAYOUT);
+
+               if (CLSP(tsp))
+                       delwin(CLSP(tsp));
+               tsp->cl_private = subwin(stdscr, tsp->rows, tsp->cols,
+                                          tsp->roff, tsp->coff);
+       }
+
+       /* discardp is going away, acquirep is taking up its space. */
+       return (0);
+}
+
+/* 
+ * cl_ex_adjust --
+ *     Adjust the screen for ex.  This routine is purely for standalone
+ *     ex programs.  All special purpose, all special case.
+ *
+ * PUBLIC: int cl_ex_adjust __P((SCR *, exadj_t));
+ */
+int
+cl_ex_adjust(SCR *sp, exadj_t action)
+{
+       CL_PRIVATE *clp;
+       int cnt;
+
+       clp = CLP(sp);
+       switch (action) {
+       case EX_TERM_SCROLL:
+               /* Move the cursor up one line if that's possible. */
+               if (clp->cuu1 != NULL)
+                       (void)tputs(clp->cuu1, 1, cl_putchar);
+               else if (clp->cup != NULL)
+                       (void)tputs(tgoto(clp->cup,
+                           0, LINES - 2), 1, cl_putchar);
+               else
+                       return (0);
+               /* FALLTHROUGH */
+       case EX_TERM_CE:
+               /* Clear the line. */
+               if (clp->el != NULL) {
+                       (void)putchar('\r');
+                       (void)tputs(clp->el, 1, cl_putchar);
+               } else {
+                       /*
+                        * Historically, ex didn't erase the line, so, if the
+                        * displayed line was only a single glyph, and <eof>
+                        * was more than one glyph, the output would not fully
+                        * overwrite the user's input.  To fix this, output
+                        * the maxiumum character number of spaces.  Note,
+                        * this won't help if the user entered extra prompt
+                        * or <blank> characters before the command character.
+                        * We'd have to do a lot of work to make that work, and
+                        * it's almost certainly not worth the effort.
+                        */
+                       for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt)
+                               (void)putchar('\b');
+                       for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt)
+                               (void)putchar(' ');
+                       (void)putchar('\r');
+                       (void)fflush(stdout);
+               }
+               break;
+       default:
+               abort();
+       }
+       return (0);
+}
+
+/*
+ * cl_insertln --
+ *     Push down the current line, discarding the bottom line.
+ *
+ * PUBLIC: int cl_insertln __P((SCR *));
+ */
+int
+cl_insertln(SCR *sp)
+{
+       WINDOW *win;
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+       /*
+        * The current line is expected to be blank after this operation,
+        * and the screen must support that semantic.
+        */
+       return (winsertln(win) == ERR);
+}
+
+/*
+ * cl_keyval --
+ *     Return the value for a special key.
+ *
+ * PUBLIC: int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ */
+int
+cl_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep)
+{
+       CL_PRIVATE *clp;
+
+       /*
+        * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
+        * VWERASE is a 4BSD extension.
+        */
+       clp = CLP(sp);
+       switch (val) {
+       case KEY_VEOF:
+               *dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE;
+               break;
+       case KEY_VERASE:
+               *dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE;
+               break;
+       case KEY_VKILL:
+               *dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE;
+               break;
+#ifdef VWERASE
+       case KEY_VWERASE:
+               *dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE;
+               break;
+#endif
+       default:
+               *dnep = 1;
+               break;
+       }
+       return (0);
+}
+
+/*
+ * cl_move --
+ *     Move the cursor.
+ *
+ * PUBLIC: int cl_move __P((SCR *, size_t, size_t));
+ */
+int
+cl_move(SCR *sp, size_t lno, size_t cno)
+{
+       WINDOW *win;
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+       /* See the comment in cl_cursor. */
+       if (wmove(win, RLNO(sp, lno), RCNO(sp, cno)) == ERR) {
+               msgq(sp, M_ERR, "Error: move: l(%zu + %zu) c(%zu + %zu)",
+                   lno, sp->roff, cno, sp->coff);
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * cl_refresh --
+ *     Refresh the screen.
+ *
+ * PUBLIC: int cl_refresh __P((SCR *, int));
+ */
+int
+cl_refresh(SCR *sp, int repaint)
+{
+       GS *gp;
+       CL_PRIVATE *clp;
+       WINDOW *win;
+       SCR *psp, *tsp;
+       size_t y, x;
+
+       gp = sp->gp;
+       clp = CLP(sp);
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+
+       /*
+        * If we received a killer signal, we're done, there's no point
+        * in refreshing the screen.
+        */
+       if (clp->killersig)
+               return (0);
+
+       /*
+        * If repaint is set, the editor is telling us that we don't know
+        * what's on the screen, so we have to repaint from scratch.
+        *
+        * If repaint set or the screen layout changed, we need to redraw
+        * any lines separating vertically split screens.  If the horizontal
+        * offsets are the same, then the split was vertical, and need to
+        * draw a dividing line.
+        */
+       if (repaint || F_ISSET(clp, CL_LAYOUT)) {
+               getyx(stdscr, y, x);
+               for (psp = sp; 
+                   psp != (void *)&sp->wp->scrq; psp = psp->q.cqe_next)
+                       for (tsp = psp->q.cqe_next;
+                           tsp != (void *)&sp->wp->scrq; 
+                           tsp = tsp->q.cqe_next)
+                               if (psp->roff == tsp->roff) {
+                                   if (psp->coff + psp->cols + 1 == tsp->coff)
+                                       cl_rdiv(psp);
+                                   else 
+                                   if (tsp->coff + tsp->cols + 1 == psp->coff)
+                                       cl_rdiv(tsp);
+                               }
+               (void)wmove(stdscr, y, x);
+               F_CLR(clp, CL_LAYOUT);
+       }
+
+       /*
+        * In the curses library, doing wrefresh(curscr) is okay, but the
+        * screen flashes when we then apply the refresh() to bring it up
+        * to date.  So, use clearok().
+        */
+       if (repaint)
+               clearok(curscr, 1);
+       /*
+        * Only do an actual refresh, when this is the focus window,
+        * i.e. the one holding the cursor. This assumes that refresh
+        * is called for that window after refreshing the others.
+        * This prevents the cursor being drawn in the other windows.
+        */
+       return (wnoutrefresh(stdscr) == ERR || 
+               wnoutrefresh(win) == ERR || 
+               (sp == clp->focus && doupdate() == ERR));
+}
+
+/*
+ * cl_rdiv --
+ *     Draw a dividing line between two vertically split screens.
+ */
+static void
+cl_rdiv(SCR *sp)
+{
+       size_t cnt;
+
+       for (cnt = 0; cnt < sp->rows - 1; ++cnt) {
+               wmove(stdscr, sp->roff + cnt, sp->cols + sp->coff);
+               waddch(stdscr, '|');
+       }
+}
+
+/*
+ * cl_rename --
+ *     Rename the file.
+ *
+ * PUBLIC: int cl_rename __P((SCR *, char *, int));
+ */
+int
+cl_rename(SCR *sp, char *name, int on)
+{
+       CL_PRIVATE *clp;
+       FILE *pfp;
+       GS *gp;
+       char buf[256], *p;
+
+       gp = sp->gp;
+       clp = CLP(sp);
+
+       if (on) {
+               clp->focus = sp;
+               if (!F_ISSET(clp, CL_RENAME_OK))
+                       return (0);
+
+               /*
+                * XXX
+                * We can only rename windows for xterm.
+                */
+               if (strncmp(OG_STR(gp, GO_TERM), "xterm", sizeof("xterm") - 1))
+                       return (0);
+
+               /*
+                * XXX
+                * Try and figure out the current name of this window.  There
+                * are two forms of the xwininfo output I've seen:
+                *
+                * Window id: 0x400000d "name"
+                * Window id: 0x140000d (name)
+                */
+#define        COMMAND \
+       "expr \"`xwininfo -id $WINDOWID | grep id:`\" : '.* [\"(]\\(.*\\)[\")]'"
+
+               if (clp->oname == NULL &&
+                   (pfp = popen(COMMAND, "r")) != NULL) {
+                       if (fgets(buf, sizeof(buf), pfp) != NULL &&
+                           (p = strchr(buf, '\n')) != NULL) {
+                               *p = '\0';
+                               clp->oname = strdup(buf);
+                       }
+                       (void)fclose(pfp);
+               }
+
+               cl_setname(gp, name);
+
+               F_SET(clp, CL_RENAME);
+       } else
+               if (F_ISSET(clp, CL_RENAME)) {
+                       cl_setname(gp, clp->oname);
+
+                       F_CLR(clp, CL_RENAME);
+               }
+       return (0);
+}
+
+/*
+ * cl_setname --
+ *     Set a X11 icon/window name.
+ *
+ * PUBLIC: void cl_setname __P((GS *, char *));
+ */
+void
+cl_setname(GS *gp, char *name)
+{
+/* X11 xterm escape sequence to rename the icon/window. */
+#define        XTERM_RENAME    "\033]0;%s\007"
+
+       (void)printf(XTERM_RENAME, name == NULL ? OG_STR(gp, GO_TERM) : name);
+       (void)fflush(stdout);
+}
+
+/* 
+ * cl_split --
+ *     Split a screen.
+ *
+ * PUBLIC: int cl_split __P((SCR *, SCR *));
+ */
+int
+cl_split(SCR *origp, SCR *newp)
+{
+       CL_PRIVATE *clp;
+
+       clp = CLP(origp);
+       F_SET(clp, CL_LAYOUT);
+
+       if (CLSP(origp))
+               delwin(CLSP(origp));
+
+       origp->cl_private = subwin(stdscr, origp->rows, origp->cols,
+                                    origp->roff, origp->coff);
+       newp->cl_private = subwin(stdscr, newp->rows, newp->cols,
+                                    newp->roff, newp->coff);
+
+       /* origp is the original screen, giving up space to newp. */
+       return (0);
+}
+
+/*
+ * cl_suspend --
+ *     Suspend a screen.
+ *
+ * PUBLIC: int cl_suspend __P((SCR *, int *));
+ */
+int
+cl_suspend(SCR *sp, int *allowedp)
+{
+       struct termios t;
+       CL_PRIVATE *clp;
+       WINDOW *win;
+       GS *gp;
+       size_t y, x;
+       int changed;
+
+       gp = sp->gp;
+       clp = CLP(sp);
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+       *allowedp = 1;
+
+       /*
+        * The ex implementation of this function isn't needed by screens not
+        * supporting ex commands that require full terminal canonical mode
+        * (e.g. :suspend).
+        *
+        * The vi implementation of this function isn't needed by screens not
+        * supporting vi process suspension, i.e. any screen that isn't backed
+        * by a UNIX shell.
+        *
+        * Setting allowedp to 0 will cause the editor to reject the command.
+        */
+       if (F_ISSET(sp, SC_EX)) { 
+               /* Save the terminal settings, and restore the original ones. */
+               if (F_ISSET(clp, CL_STDIN_TTY)) {
+                       (void)tcgetattr(STDIN_FILENO, &t);
+                       (void)tcsetattr(STDIN_FILENO,
+                           TCSASOFT | TCSADRAIN, &clp->orig);
+               }
+
+               /* Stop the process group. */
+               (void)kill(0, SIGTSTP);
+
+               /* Time passes ... */
+
+               /* Restore terminal settings. */
+               if (F_ISSET(clp, CL_STDIN_TTY))
+                       (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
+               return (0);
+       }
+
+       /*
+        * Move to the lower left-hand corner of the screen.
+        *
+        * XXX
+        * Not sure this is necessary in System V implementations, but it
+        * shouldn't hurt.
+        */
+       getyx(win, y, x);
+       (void)wmove(win, LINES - 1, 0);
+       (void)wrefresh(win);
+
+       /*
+        * Temporarily end the screen.  System V introduced a semantic where
+        * endwin() could be restarted.  We use it because restarting curses
+        * from scratch often fails in System V.  4BSD curses didn't support
+        * restarting after endwin(), so we have to do what clean up we can
+        * without calling it.
+        */
+       /* Save the terminal settings. */
+       (void)tcgetattr(STDIN_FILENO, &t);
+
+       /* Restore the cursor keys to normal mode. */
+       (void)keypad(stdscr, FALSE);
+
+       /* Restore the window name. */
+       (void)cl_rename(sp, NULL, 0);
+
+#ifdef HAVE_BSD_CURSES
+       (void)cl_attr(sp, SA_ALTERNATE, 0);
+#else
+       (void)endwin();
+#endif
+       /*
+        * XXX
+        * Restore the original terminal settings.  This is bad -- the
+        * reset can cause character loss from the tty queue.  However,
+        * we can't call endwin() in BSD curses implementations, and too
+        * many System V curses implementations don't get it right.
+        */
+       (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
+
+       /* Stop the process group. */
+       (void)kill(0, SIGTSTP);
+
+       /* Time passes ... */
+
+       /*
+        * If we received a killer signal, we're done.  Leave everything
+        * unchanged.  In addition, the terminal has already been reset
+        * correctly, so leave it alone.
+        */
+       if (clp->killersig) {
+               F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
+               return (0);
+       }
+
+       /* Restore terminal settings. */
+       wrefresh(win);                      /* Needed on SunOs/Solaris ? */
+       if (F_ISSET(clp, CL_STDIN_TTY))
+               (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
+
+#ifdef HAVE_BSD_CURSES
+       (void)cl_attr(sp, SA_ALTERNATE, 1);
+#endif
+
+       /* Set the window name. */
+       (void)cl_rename(sp, sp->frp->name, 1);
+
+       /* Put the cursor keys into application mode. */
+       (void)keypad(stdscr, TRUE);
+
+       /* Refresh and repaint the screen. */
+       (void)wmove(win, y, x);
+       (void)cl_refresh(sp, 1);
+
+       /* If the screen changed size, set the SIGWINCH bit. */
+       if (cl_ssize(sp, 1, NULL, NULL, &changed))
+               return (1);
+       if (changed)
+               F_SET(CLP(sp), CL_SIGWINCH);
+
+       return (0);
+}
+
+/*
+ * cl_usage --
+ *     Print out the curses usage messages.
+ * 
+ * PUBLIC: void cl_usage __P((void));
+ */
+void
+cl_usage(void)
+{
+#define        USAGE "\
+usage: ex [-eFRrSsv] [-c command] [-t tag] [-w size] [file ...]\n\
+usage: vi [-eFlRrSv] [-c command] [-t tag] [-w size] [file ...]\n"
+       (void)fprintf(stderr, "%s", USAGE);
+#undef USAGE
+}
+
+#ifdef DEBUG
+/*
+ * gdbrefresh --
+ *     Stub routine so can flush out curses screen changes using gdb.
+ */
+int
+gdbrefresh(void)
+{
+       refresh();
+       return (0);             /* XXX Convince gdb to run it. */
+}
+#endif
diff --git a/dist/nvi/cl/cl_main.c b/dist/nvi/cl/cl_main.c
new file mode 100644 (file)
index 0000000..84cad2f
--- /dev/null
@@ -0,0 +1,440 @@
+/*     $NetBSD: cl_main.c,v 1.4 2011/09/16 16:13:41 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cl_main.c,v 10.54 2001/07/29 19:07:27 skimo Exp (Berkeley) Date: 2001/07/29 19:07:27";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ip/extern.h"
+#include "cl.h"
+#include "pathnames.h"
+
+GS *__global_list;                             /* GLOBAL: List of screens. */
+sigset_t __sigblockset;                                /* GLOBAL: Blocked signals. */
+
+static void       cl_func_std __P((WIN *));
+#ifdef notused
+static void       cl_end __P((CL_PRIVATE *));
+#endif
+static CL_PRIVATE *cl_init __P((WIN *));
+__dead static void        perr __P((const char *, const char *));
+static int        setsig __P((int, struct sigaction *, void (*)(int)));
+static void       sig_end __P((GS *));
+static void       term_init __P((const char *, const char *));
+
+/*
+ * main --
+ *     This is the main loop for the standalone curses editor.
+ */
+int
+main(int argc, char **argv)
+{
+       static int reenter;
+       CL_PRIVATE *clp;
+       GS *gp;
+       WIN *wp;
+       size_t rows, cols;
+       int rval;
+       char **p_av, **t_av;
+       const char *ttype;
+
+       /* If loaded at 0 and jumping through a NULL pointer, stop. */
+       if (reenter++)
+               abort();
+
+       /* Create and initialize the global structure. */
+       __global_list = gp = gs_init(argv[0]);
+
+       /*
+        * Strip out any arguments that vi isn't going to understand.  There's
+        * no way to portably call getopt twice, so arguments parsed here must
+        * be removed from the argument list.
+        */
+       for (p_av = t_av = argv;;) {
+               if (*t_av == NULL) {
+                       *p_av = NULL;
+                       break;
+               }
+               if (!strcmp(*t_av, "--")) {
+                       while ((*p_av++ = *t_av++) != NULL);
+                       break;
+               }
+               *p_av++ = *t_av++;
+       }
+
+       /* Create new window */
+       wp = gs_new_win(gp);
+               
+       /* Create and initialize the CL_PRIVATE structure. */
+       clp = cl_init(wp);
+
+       /*
+        * Initialize the terminal information.
+        *
+        * We have to know what terminal it is from the start, since we may
+        * have to use termcap/terminfo to find out how big the screen is.
+        */
+       if ((ttype = getenv("TERM")) == NULL) {
+               if (isatty(STDIN_FILENO))
+                       fprintf(stderr, "%s: warning: TERM is not set\n",
+                           gp->progname);
+               ttype = "unknown";
+       }
+       term_init(gp->progname, ttype);
+
+       /* Add the terminal type to the global structure. */
+       if ((OG_D_STR(gp, GO_TERM) =
+           OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
+               perr(gp->progname, NULL);
+
+       /* Figure out how big the screen is. */
+       if (cl_ssize(NULL, 0, &rows, &cols, NULL))
+               exit (1);
+
+       /* Add the rows and columns to the global structure. */
+       OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
+       OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;
+
+       /* Ex wants stdout to be buffered. */
+       (void)setvbuf(stdout, NULL, _IOFBF, 0);
+
+       /* Start catching signals. */
+       if (sig_init(gp, NULL))
+               exit (1);
+
+       /* Run ex/vi. */
+       rval = editor(wp, argc, argv);
+
+       /* Clean out the global structure. */
+       gs_end(gp);
+
+       /* Clean up signals. */
+       sig_end(gp);
+
+       /* Clean up the terminal. */
+       (void)cl_quit(gp);
+
+       /*
+        * XXX
+        * Reset the O_MESG option.
+        */
+       if (clp->tgw != TGW_UNKNOWN)
+               (void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);
+
+       /*
+        * XXX
+        * Reset the X11 xterm icon/window name.
+        */
+       if (F_ISSET(clp, CL_RENAME))
+               cl_setname(gp, clp->oname);
+
+       /* If a killer signal arrived, pretend we just got it. */
+       if (clp->killersig) {
+               (void)signal(clp->killersig, SIG_DFL);
+               (void)kill(getpid(), clp->killersig);
+               /* NOTREACHED */
+       }
+
+       /* Free the global and CL private areas. */
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+       cl_end(clp);
+       free(gp);
+#endif
+
+       exit (rval);
+}
+
+/*
+ * cl_init --
+ *     Create and partially initialize the CL structure.
+ */
+static CL_PRIVATE *
+cl_init(WIN *wp)
+{
+       CL_PRIVATE *clp;
+       int fd;
+       GS *gp;
+
+       gp = wp->gp;
+
+       /* Allocate the CL private structure. */
+       CALLOC_NOMSG(NULL, clp, CL_PRIVATE *, 1, sizeof(CL_PRIVATE));
+       if (clp == NULL)
+               perr(gp->progname, NULL);
+       gp->cl_private = clp;
+
+       /*
+        * Set the CL_STDIN_TTY flag.  It's purpose is to avoid setting
+        * and resetting the tty if the input isn't from there.  We also
+        * use the same test to determine if we're running a script or
+        * not.
+        */
+       if (isatty(STDIN_FILENO))
+               F_SET(clp, CL_STDIN_TTY);
+       else
+               F_SET(gp, G_SCRIPTED);
+
+       /*
+        * We expect that if we've lost our controlling terminal that the
+        * open() (but not the tcgetattr()) will fail.
+        */
+       if (F_ISSET(clp, CL_STDIN_TTY)) {
+               if (tcgetattr(STDIN_FILENO, &clp->orig) == -1)
+                       goto tcfail;
+       } else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {
+               if (tcgetattr(fd, &clp->orig) == -1) {
+tcfail:                        perr(gp->progname, "tcgetattr");
+                       exit (1);
+               }
+               (void)close(fd);
+       }
+
+       /* Initialize the list of curses functions. */
+       cl_func_std(wp);
+
+       return (clp);
+}
+
+#ifdef notused
+/*
+ * cl_end --
+ *     Discard the CL structure.
+ */
+static void
+cl_end(CL_PRIVATE *clp)
+{
+       if (clp->oname != NULL)
+               free(clp->oname);
+       free(clp);
+}
+#endif
+
+/*
+ * term_init --
+ *     Initialize terminal information.
+ */
+static void
+term_init(const char *name, const char *ttype)
+{
+       int err;
+
+       /* Set up the terminal database information. */
+       setupterm(__UNCONST(ttype), STDOUT_FILENO, &err);
+       switch (err) {
+       case -1:
+               (void)fprintf(stderr,
+                   "%s: No terminal database found\n", name);
+               exit (1);
+       case 0:
+               (void)fprintf(stderr,
+                   "%s: %s: unknown terminal type\n", name, ttype);
+               exit (1);
+       }
+}
+
+#define        GLOBAL_CLP \
+       CL_PRIVATE *clp = GCLP(__global_list);
+static void
+h_hup(int signo)
+{
+       GLOBAL_CLP;
+
+       F_SET(clp, CL_SIGHUP);
+       clp->killersig = SIGHUP;
+}
+
+static void
+h_int(int signo)
+{
+       GLOBAL_CLP;
+
+       F_SET(clp, CL_SIGINT);
+}
+
+static void
+h_term(int signo)
+{
+       GLOBAL_CLP;
+
+       F_SET(clp, CL_SIGTERM);
+       clp->killersig = SIGTERM;
+}
+
+static void
+h_winch(int signo)
+{
+       GLOBAL_CLP;
+
+       F_SET(clp, CL_SIGWINCH);
+}
+#undef GLOBAL_CLP
+
+/*
+ * sig_init --
+ *     Initialize signals.
+ *
+ * PUBLIC: int sig_init __P((GS *, SCR *));
+ */
+int
+sig_init(GS *gp, SCR *sp)
+{
+       CL_PRIVATE *clp;
+
+       clp = GCLP(gp);
+
+       if (sp == NULL) {
+               (void)sigemptyset(&__sigblockset);
+               if (sigaddset(&__sigblockset, SIGHUP) ||
+                   setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) ||
+                   sigaddset(&__sigblockset, SIGINT) ||
+                   setsig(SIGINT, &clp->oact[INDX_INT], h_int) ||
+                   sigaddset(&__sigblockset, SIGTERM) ||
+                   setsig(SIGTERM, &clp->oact[INDX_TERM], h_term)
+#ifdef SIGWINCH
+                   ||
+                   sigaddset(&__sigblockset, SIGWINCH) ||
+                   setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch)
+#endif
+                   ) {
+                       perr(gp->progname, NULL);
+                       return (1);
+               }
+       } else
+               if (setsig(SIGHUP, NULL, h_hup) ||
+                   setsig(SIGINT, NULL, h_int) ||
+                   setsig(SIGTERM, NULL, h_term)
+#ifdef SIGWINCH
+                   ||
+                   setsig(SIGWINCH, NULL, h_winch)
+#endif
+                   ) {
+                       msgq(sp, M_SYSERR, "signal-reset");
+               }
+       return (0);
+}
+
+/*
+ * setsig --
+ *     Set a signal handler.
+ */
+static int
+setsig(int signo, struct sigaction *oactp, void (*handler) (int))
+{
+       struct sigaction act;
+
+       /*
+        * Use sigaction(2), not signal(3), since we don't always want to
+        * restart system calls.  The example is when waiting for a command
+        * mode keystroke and SIGWINCH arrives.  Besides, you can't portably
+        * restart system calls (thanks, POSIX!).  On the other hand, you
+        * can't portably NOT restart system calls (thanks, Sun!).  SunOS
+        * used SA_INTERRUPT as their extension to NOT restart read calls.
+        * We sure hope nobody else used it for anything else.  Mom told me
+        * there'd be days like this.  She just never told me that there'd
+        * be so many.
+        */
+       act.sa_handler = handler;
+       sigemptyset(&act.sa_mask);
+
+#ifdef SA_INTERRUPT
+       act.sa_flags = SA_INTERRUPT;
+#else
+       act.sa_flags = 0;
+#endif
+       return (sigaction(signo, &act, oactp));
+}
+
+/*
+ * sig_end --
+ *     End signal setup.
+ */
+static void
+sig_end(GS *gp)
+{
+       CL_PRIVATE *clp;
+
+       clp = GCLP(gp);
+       (void)sigaction(SIGHUP, NULL, &clp->oact[INDX_HUP]);
+       (void)sigaction(SIGINT, NULL, &clp->oact[INDX_INT]);
+       (void)sigaction(SIGTERM, NULL, &clp->oact[INDX_TERM]);
+#ifdef SIGWINCH
+       (void)sigaction(SIGWINCH, NULL, &clp->oact[INDX_WINCH]);
+#endif
+}
+
+/*
+ * cl_func_std --
+ *     Initialize the standard curses functions.
+ */
+static void
+cl_func_std(WIN *wp)
+{
+       GS *gp;
+
+       gp = wp->gp;
+
+       gp->scr_addstr = cl_addstr;
+       gp->scr_waddstr = cl_waddstr;
+       gp->scr_attr = cl_attr;
+       gp->scr_baud = cl_baud;
+       gp->scr_bell = cl_bell;
+       gp->scr_busy = NULL;
+       gp->scr_child = NULL;
+       gp->scr_clrtoeol = cl_clrtoeol;
+       gp->scr_cursor = cl_cursor;
+       gp->scr_deleteln = cl_deleteln;
+       gp->scr_reply = NULL;
+       gp->scr_discard = cl_discard;
+       gp->scr_event = cl_event;
+       gp->scr_ex_adjust = cl_ex_adjust;
+       gp->scr_fmap = cl_fmap;
+       gp->scr_insertln = cl_insertln;
+       gp->scr_keyval = cl_keyval;
+       gp->scr_move = cl_move;
+       wp->scr_msg = NULL;
+       gp->scr_optchange = cl_optchange;
+       gp->scr_refresh = cl_refresh;
+       gp->scr_rename = cl_rename;
+       gp->scr_screen = cl_screen;
+       gp->scr_split = cl_split;
+       gp->scr_suspend = cl_suspend;
+       gp->scr_usage = cl_usage;
+}
+
+/*
+ * perr --
+ *     Print system error.
+ */
+static void
+perr(const char *name, const char *msg)
+{
+       (void)fprintf(stderr, "%s:", name);
+       if (msg != NULL)
+               (void)fprintf(stderr, "%s:", msg);
+       (void)fprintf(stderr, "%s\n", strerror(errno));
+       exit(1);
+}
diff --git a/dist/nvi/cl/cl_read.c b/dist/nvi/cl/cl_read.c
new file mode 100644 (file)
index 0000000..8e5b876
--- /dev/null
@@ -0,0 +1,312 @@
+/*     $NetBSD: cl_read.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cl_read.c,v 10.29 2001/08/18 21:51:59 skimo Exp (Berkeley) Date: 2001/08/18 21:51:59";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ex/script.h"
+#include "cl.h"
+
+/* Pollution by Solaris curses. */
+#undef columns
+#undef lines  
+
+static input_t cl_read __P((SCR *,
+    u_int32_t, char *, size_t, int *, struct timeval *));
+static int     cl_resize __P((SCR *, size_t, size_t));
+
+/*
+ * cl_event --
+ *     Return a single event.
+ *
+ * PUBLIC: int cl_event __P((SCR *, EVENT *, u_int32_t, int));
+ */
+int
+cl_event(SCR *sp, EVENT *evp, u_int32_t flags, int ms)
+{
+       struct timeval t, *tp;
+       CL_PRIVATE *clp;
+       size_t lines, columns;
+       int changed, nr = 0;
+       const CHAR_T *wp;
+       size_t wlen;
+       int rc;
+
+       /*
+        * Queue signal based events.  We never clear SIGHUP or SIGTERM events,
+        * so that we just keep returning them until the editor dies.
+        */
+       clp = CLP(sp);
+retest:        if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) {
+               if (F_ISSET(clp, CL_SIGINT)) {
+                       F_CLR(clp, CL_SIGINT);
+                       evp->e_event = E_INTERRUPT;
+               } else
+                       evp->e_event = E_TIMEOUT;
+               return (0);
+       }
+       if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) {
+               if (F_ISSET(clp, CL_SIGHUP)) {
+                       evp->e_event = E_SIGHUP;
+                       return (0);
+               }
+               if (F_ISSET(clp, CL_SIGTERM)) {
+                       evp->e_event = E_SIGTERM;
+                       return (0);
+               }
+               if (F_ISSET(clp, CL_SIGWINCH)) {
+                       F_CLR(clp, CL_SIGWINCH);
+                       if (cl_ssize(sp, 1, &lines, &columns, &changed))
+                               return (1);
+                       if (changed) {
+                               (void)cl_resize(sp, lines, columns);
+                               evp->e_event = E_WRESIZE;
+                               return (0);
+                       }
+                       /* No real change, ignore the signal. */
+               }
+       }
+
+       /* Set timer. */
+       if (ms == 0)
+               tp = NULL;
+       else {
+               t.tv_sec = ms / 1000;
+               t.tv_usec = (ms % 1000) * 1000;
+               tp = &t;
+       }
+
+       /* Read input characters. */
+read:
+       switch (cl_read(sp, LF_ISSET(EC_QUOTED | EC_RAW),
+           clp->ibuf + clp->skip, SIZE(clp->ibuf) - clp->skip, &nr, tp)) {
+       case INP_OK:
+               rc = INPUT2INT5(sp, clp->cw, clp->ibuf, nr + clp->skip, 
+                               wp, wlen);
+               evp->e_csp = __UNCONST(wp);
+               evp->e_len = wlen;
+               evp->e_event = E_STRING;
+               if (rc < 0) {
+                   int n = -rc;
+                   memmove(clp->ibuf, clp->ibuf + nr + clp->skip - n, n);
+                   clp->skip = n;
+                   if (wlen == 0)
+                       goto read;
+               } else if (rc == 0)
+                   clp->skip = 0;
+               else
+                   msgq(sp, M_ERR, "323|Invalid input. Truncated.");
+               break;
+       case INP_ERR:
+               evp->e_event = E_ERR;
+               break;
+       case INP_EOF:
+               evp->e_event = E_EOF;
+               break;
+       case INP_INTR:
+               goto retest;
+       case INP_TIMEOUT:
+               evp->e_event = E_TIMEOUT;
+               break;
+       default:
+               abort();
+       }
+       return (0);
+}
+
+/*
+ * cl_read --
+ *     Read characters from the input.
+ */
+static input_t
+cl_read(SCR *sp, u_int32_t flags, char *bp, size_t blen, int *nrp, struct timeval *tp)
+{
+       struct termios term1, term2;
+       struct timeval poll;
+       CL_PRIVATE *clp;
+       GS *gp;
+       fd_set rdfd;
+       input_t rval;
+       int maxfd, nr, term_reset;
+
+       gp = sp->gp;
+       clp = CLP(sp);
+       term_reset = 0;
+
+       /*
+        * 1: A read from a file or a pipe.  In this case, the reads
+        *    never timeout regardless.  This means that we can hang
+        *    when trying to complete a map, but we're going to hang
+        *    on the next read anyway.
+        */
+       if (!F_ISSET(clp, CL_STDIN_TTY)) {
+               switch (nr = read(STDIN_FILENO, bp, blen)) {
+               case 0:
+                       return (INP_EOF);
+               case -1:
+                       goto err;
+               default:
+                       *nrp = nr;
+                       return (INP_OK);
+               }
+               /* NOTREACHED */
+       }
+
+       /*
+        * 2: A read with an associated timeout, e.g., trying to complete
+        *    a map sequence.  If input exists, we fall into #3.
+        */
+       FD_ZERO(&rdfd);
+       poll.tv_sec = 0;
+       poll.tv_usec = 0;
+       if (tp != NULL) {
+               FD_SET(STDIN_FILENO, &rdfd);
+               switch (select(STDIN_FILENO + 1,
+                   &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
+               case 0:
+                       return (INP_TIMEOUT);
+               case -1:
+                       goto err;
+               default:
+                       break;
+               }
+       }
+       
+       /*
+        * The user can enter a key in the editor to quote a character.  If we
+        * get here and the next key is supposed to be quoted, do what we can.
+        * Reset the tty so that the user can enter a ^C, ^Q, ^S.  There's an
+        * obvious race here, when the key has already been entered, but there's
+        * nothing that we can do to fix that problem.
+        *
+        * The editor can ask for the next literal character even thought it's
+        * generally running in line-at-a-time mode.  Do what we can.
+        */
+       if (LF_ISSET(EC_QUOTED | EC_RAW) && !tcgetattr(STDIN_FILENO, &term1)) {
+               term_reset = 1;
+               if (LF_ISSET(EC_QUOTED)) {
+                       term2 = term1;
+                       term2.c_lflag &= ~ISIG;
+                       term2.c_iflag &= ~(IXON | IXOFF);
+                       (void)tcsetattr(STDIN_FILENO,
+                           TCSASOFT | TCSADRAIN, &term2);
+               } else
+                       (void)tcsetattr(STDIN_FILENO,
+                           TCSASOFT | TCSADRAIN, &clp->vi_enter);
+       }
+
+       /*
+        * 3: Wait for input.
+        *
+        * Select on the command input and scripting window file descriptors.
+        * It's ugly that we wait on scripting file descriptors here, but it's
+        * the only way to keep from locking out scripting windows.
+        */
+       if (F_ISSET(gp, G_SCRWIN)) {
+               FD_ZERO(&rdfd);
+               FD_SET(STDIN_FILENO, &rdfd);
+               maxfd = STDIN_FILENO;
+               if (sscr_check_input(sp, &rdfd, maxfd))
+                       goto err;
+       }
+
+       /*
+        * 4: Read the input.
+        *
+        * !!!
+        * What's going on here is some scary stuff.  Ex runs the terminal in
+        * canonical mode.  So, the <newline> character terminating a line of
+        * input is returned in the buffer, but a trailing <EOF> character is
+        * not similarly included.  As ex uses 0<EOF> and ^<EOF> as autoindent
+        * commands, it has to see the trailing <EOF> characters to determine
+        * the difference between the user entering "0ab" and "0<EOF>ab".  We
+        * leave an extra slot in the buffer, so that we can add a trailing
+        * <EOF> character if the buffer isn't terminated by a <newline>.  We
+        * lose if the buffer is too small for the line and exactly N characters
+        * are entered followed by an <EOF> character.
+        */
+#define        ONE_FOR_EOF     1
+       switch (nr = read(STDIN_FILENO, bp, blen - ONE_FOR_EOF)) {
+       case  0:                                /* EOF. */
+               /*
+                * ^D in canonical mode returns a read of 0, i.e. EOF.  EOF is
+                * a valid command, but we don't want to loop forever because
+                * the terminal driver is returning EOF because the user has
+                * disconnected. The editor will almost certainly try to write
+                * something before this fires, which should kill us, but You
+                * Never Know.
+                */
+               if (++clp->eof_count < 50) {
+                       bp[0] = clp->orig.c_cc[VEOF];
+                       *nrp = 1;
+                       rval = INP_OK;
+
+               } else
+                       rval = INP_EOF;
+               break;
+       case -1:                                /* Error or interrupt. */
+err:           if (errno == EINTR)
+                       rval = INP_INTR;
+               else {
+                       rval = INP_ERR;
+                       msgq(sp, M_SYSERR, "input");
+               }
+               break;
+       default:                                /* Input characters. */
+               if (F_ISSET(sp, SC_EX) && bp[nr - 1] != '\n')
+                       bp[nr++] = clp->orig.c_cc[VEOF];
+               *nrp = nr;
+               clp->eof_count = 0;
+               rval = INP_OK;
+               break;
+       }
+
+       /* Restore the terminal state if it was modified. */
+       if (term_reset)
+               (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &term1);
+       return (rval);
+}
+
+/* 
+ * cl_resize --
+ *     Reset the options for a resize event.
+ */
+static int
+cl_resize(SCR *sp, size_t lines, size_t columns)
+{
+       int rval;
+
+       rval = api_opts_set(sp, L("lines"), NULL, lines, 0);
+       if (api_opts_set(sp, L("columns"), NULL, columns, 0))
+               rval = 1;
+       return (rval);
+}
diff --git a/dist/nvi/cl/cl_screen.c b/dist/nvi/cl/cl_screen.c
new file mode 100644 (file)
index 0000000..ef4ac3d
--- /dev/null
@@ -0,0 +1,580 @@
+/*     $NetBSD: cl_screen.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cl_screen.c,v 10.56 2002/05/03 19:59:44 skimo Exp (Berkeley) Date: 2002/05/03 19:59:44";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "cl.h"
+
+static int     cl_ex_end __P((GS *));
+static int     cl_ex_init __P((SCR *));
+static void    cl_freecap __P((CL_PRIVATE *));
+static int     cl_vi_end __P((GS *));
+static int     cl_vi_init __P((SCR *));
+static int     cl_putenv __P((SCR *, const char *, const char *, u_long));
+
+/*
+ * cl_screen --
+ *     Switch screen types.
+ *
+ * PUBLIC: int cl_screen __P((SCR *, u_int32_t));
+ */
+int
+cl_screen(SCR *sp, u_int32_t flags)
+{
+       CL_PRIVATE *clp;
+       WINDOW *win;
+       GS *gp;
+
+       gp = sp->gp;
+       clp = CLP(sp);
+       win = CLSP(sp) ? CLSP(sp) : stdscr;
+
+       /* See if the current information is incorrect. */
+       if (F_ISSET(gp, G_SRESTART)) {
+               if (CLSP(sp)) {
+                   delwin(CLSP(sp));
+                   sp->cl_private = NULL;
+               }
+               if (cl_quit(gp))
+                       return (1);
+               F_CLR(gp, G_SRESTART);
+       }
+       
+       /* See if we're already in the right mode. */
+       if ((LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX)) ||
+           (LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI)))
+               return (0);
+
+       /*
+        * Fake leaving ex mode.
+        *
+        * We don't actually exit ex or vi mode unless forced (e.g. by a window
+        * size change).  This is because many curses implementations can't be
+        * called twice in a single program.  Plus, it's faster.  If the editor
+        * "leaves" vi to enter ex, when it exits ex we'll just fall back into
+        * vi.
+        */
+       if (F_ISSET(sp, SC_SCR_EX))
+               F_CLR(sp, SC_SCR_EX);
+
+       /*
+        * Fake leaving vi mode.
+        *
+        * Clear out the rest of the screen if we're in the middle of a split
+        * screen.  Move to the last line in the current screen -- this makes
+        * terminal scrolling happen naturally.  Note: *don't* move past the
+        * end of the screen, as there are ex commands (e.g., :read ! cat file)
+        * that don't want to.  Don't clear the info line, its contents may be
+        * valid, e.g. :file|append.
+        */
+       if (F_ISSET(sp, SC_SCR_VI)) {
+               F_CLR(sp, SC_SCR_VI);
+
+               if (sp->q.cqe_next != (void *)&sp->wp->scrq) {
+                       (void)wmove(win, RLNO(sp, sp->rows), 0);
+                       wclrtobot(win);
+               }
+               (void)wmove(win, RLNO(sp, sp->rows) - 1, 0);
+               wrefresh(win);
+       }
+
+       /* Enter the requested mode. */
+       if (LF_ISSET(SC_EX)) {
+               if (cl_ex_init(sp))
+                       return (1);
+               F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);
+
+               /*
+                * If doing an ex screen for ex mode, move to the last line
+                * on the screen.
+                */
+               if (F_ISSET(sp, SC_EX) && clp->cup != NULL)
+                       tputs(tgoto(clp->cup,
+                           0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
+       } else {
+               if (cl_vi_init(sp))
+                       return (1);
+               F_CLR(clp, CL_IN_EX);
+               F_SET(clp, CL_SCR_VI_INIT);
+       }
+       return (0);
+}
+
+/*
+ * cl_quit --
+ *     Shutdown the screens.
+ *
+ * PUBLIC: int cl_quit __P((GS *));
+ */
+int
+cl_quit(GS *gp)
+{
+       CL_PRIVATE *clp;
+       int rval;
+
+       rval = 0;
+       clp = GCLP(gp);
+
+       /*
+        * If we weren't really running, ignore it.  This happens if the
+        * screen changes size before we've called curses.
+        */
+       if (!F_ISSET(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT))
+               return (0);
+
+       /* Clean up the terminal mappings. */
+       if (cl_term_end(gp))
+               rval = 1;
+
+       /* Really leave vi mode. */
+       if (F_ISSET(clp, CL_STDIN_TTY) &&
+           F_ISSET(clp, CL_SCR_VI_INIT) && cl_vi_end(gp))
+               rval = 1;
+
+       /* Really leave ex mode. */
+       if (F_ISSET(clp, CL_STDIN_TTY) &&
+           F_ISSET(clp, CL_SCR_EX_INIT) && cl_ex_end(gp))
+               rval = 1;
+
+       /*
+        * If we were running ex when we quit, or we're using an implementation
+        * of curses where endwin() doesn't get this right, restore the original
+        * terminal modes.
+        *
+        * XXX
+        * We always do this because it's too hard to figure out what curses
+        * implementations get it wrong.  It may discard type-ahead characters
+        * from the tty queue.
+        */
+       (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
+
+       F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
+       return (rval);
+}
+
+/*
+ * cl_vi_init --
+ *     Initialize the curses vi screen.
+ */
+static int
+cl_vi_init(SCR *sp)
+{
+       CL_PRIVATE *clp;
+       GS *gp;
+       char *o_cols, *o_lines, *o_term;
+       const char *ttype;
+
+       gp = sp->gp;
+       clp = CLP(sp);
+
+       /* If already initialized, just set the terminal modes. */
+       if (F_ISSET(clp, CL_SCR_VI_INIT))
+               goto fast;
+
+       /* Curses vi always reads from (and writes to) a terminal. */
+       if (!F_ISSET(clp, CL_STDIN_TTY) || !isatty(STDOUT_FILENO)) {
+               msgq(sp, M_ERR,
+                   "016|Vi's standard input and output must be a terminal");
+               return (1);
+       }
+
+       /* We'll need a terminal type. */
+       if (opts_empty(sp, O_TERM, 0))
+               return (1);
+       ttype = O_STR(sp, O_TERM);
+
+       /*
+        * XXX
+        * Changing the row/column and terminal values is done by putting them
+        * into the environment, which is then read by curses.  What this loses
+        * in ugliness, it makes up for in stupidity.  We can't simply put the
+        * values into the environment ourselves, because in the presence of a
+        * kernel mechanism for returning the window size, entering values into
+        * the environment will screw up future screen resizing events, e.g. if
+        * the user enters a :shell command and then resizes their window.  So,
+        * if they weren't already in the environment, we make sure to delete
+        * them immediately after setting them.
+        *
+        * XXX
+        * Putting the TERM variable into the environment is necessary, even
+        * though we're using newterm() here.  We may be using initscr() as
+        * the underlying function.
+        */
+       o_term = getenv("TERM");
+       cl_putenv(sp, "TERM", ttype, 0);
+       o_lines = getenv("LINES");
+       cl_putenv(sp, "LINES", NULL, (u_long)O_VAL(sp, O_LINES));
+       o_cols = getenv("COLUMNS");
+       cl_putenv(sp, "COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));
+
+       /*
+        * We don't care about the SCREEN reference returned by newterm, we
+        * never have more than one SCREEN at a time.
+        *
+        * XXX
+        * The SunOS initscr() can't be called twice.  Don't even think about
+        * using it.  It fails in subtle ways (e.g. select(2) on fileno(stdin)
+        * stops working).  (The SVID notes that applications should only call
+        * initscr() once.)
+        *
+        * XXX
+        * The HP/UX newterm doesn't support the NULL first argument, so we
+        * have to specify the terminal type.
+        */
+       errno = 0;
+       if (newterm(__UNCONST(ttype), stdout, stdin) == NULL) {
+               if (errno)
+                       msgq(sp, M_SYSERR, "%s", ttype);
+               else
+                       msgq(sp, M_ERR, "%s: unknown terminal type", ttype);
+               return (1);
+       }
+
+       if (o_term == NULL)
+               cl_unsetenv(sp, "TERM");
+       if (o_lines == NULL)
+               cl_unsetenv(sp, "LINES");
+       if (o_cols == NULL)
+               cl_unsetenv(sp, "COLUMNS");
+
+       /*
+        * XXX
+        * Someone got let out alone without adult supervision -- the SunOS
+        * newterm resets the signal handlers.  There's a race, but it's not
+        * worth closing.
+        */
+       (void)sig_init(sp->gp, sp);
+
+       /*
+        * We use raw mode.  What we want is 8-bit clean, however, signals
+        * and flow control should continue to work.  Admittedly, it sounds
+        * like cbreak, but it isn't.  Using cbreak() can get you additional
+        * things like IEXTEN, which turns on flags like DISCARD and LNEXT.
+        *
+        * !!!
+        * If raw isn't turning off echo and newlines, something's wrong.
+        * However, it shouldn't hurt.
+        */
+       noecho();                       /* No character echo. */
+       nonl();                         /* No CR/NL translation. */
+       raw();                          /* 8-bit clean. */
+       idlok(stdscr, 1);               /* Use hardware insert/delete line. */
+
+       /* Put the cursor keys into application mode. */
+       (void)keypad(stdscr, TRUE);
+
+       /*
+        * XXX
+        * The screen TI sequence just got sent.  See the comment in
+        * cl_funcs.c:cl_attr().
+        */
+       clp->ti_te = TI_SENT;
+
+       /*
+        * XXX
+        * Historic implementations of curses handled SIGTSTP signals
+        * in one of three ways.  They either:
+        *
+        *      1: Set their own handler, regardless.
+        *      2: Did not set a handler if a handler was already installed.
+        *      3: Set their own handler, but then called any previously set
+        *         handler after completing their own cleanup.
+        *
+        * We don't try and figure out which behavior is in place, we force
+        * it to SIG_DFL after initializing the curses interface, which means
+        * that curses isn't going to take the signal.  Since curses isn't
+        * reentrant (i.e., the whole curses SIGTSTP interface is a fantasy),
+        * we're doing The Right Thing.
+        */
+       (void)signal(SIGTSTP, SIG_DFL);
+
+       /*
+        * If flow control was on, turn it back on.  Turn signals on.  ISIG
+        * turns on VINTR, VQUIT, VDSUSP and VSUSP.   The main curses code
+        * already installed a handler for VINTR.  We're going to disable the
+        * other three.
+        *
+        * XXX
+        * We want to use ^Y as a vi scrolling command.  If the user has the
+        * DSUSP character set to ^Y (common practice) clean it up.  As it's
+        * equally possible that the user has VDSUSP set to 'a', we disable
+        * it regardless.  It doesn't make much sense to suspend vi at read,
+        * so I don't think anyone will care.  Alternatively, we could look
+        * it up in the table of legal command characters and turn it off if
+        * it matches one.  VDSUSP wasn't in POSIX 1003.1-1990, so we test for
+        * it.
+        *
+        * XXX
+        * We don't check to see if the user had signals enabled originally.
+        * If they didn't, it's unclear what we're supposed to do here, but
+        * it's also pretty unlikely.
+        */
+       if (tcgetattr(STDIN_FILENO, &clp->vi_enter)) {
+               msgq(sp, M_SYSERR, "tcgetattr");
+               goto err;
+       }
+       if (clp->orig.c_iflag & IXON)
+               clp->vi_enter.c_iflag |= IXON;
+       if (clp->orig.c_iflag & IXOFF)
+               clp->vi_enter.c_iflag |= IXOFF;
+
+       clp->vi_enter.c_lflag |= ISIG;
+#ifdef VDSUSP
+       clp->vi_enter.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+       clp->vi_enter.c_cc[VQUIT] = _POSIX_VDISABLE;
+       clp->vi_enter.c_cc[VSUSP] = _POSIX_VDISABLE;
+
+       /*
+        * XXX
+        * OSF/1 doesn't turn off the <discard>, <literal-next> or <status>
+        * characters when curses switches into raw mode.  It should be OK
+        * to do it explicitly for everyone.
+        */
+#ifdef VDISCARD
+       clp->vi_enter.c_cc[VDISCARD] = _POSIX_VDISABLE;
+#endif
+#ifdef VLNEXT
+       clp->vi_enter.c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+#ifdef VSTATUS
+       clp->vi_enter.c_cc[VSTATUS] = _POSIX_VDISABLE;
+#endif
+
+       /* Initialize terminal based information. */
+       if (cl_term_init(sp))
+               goto err;
+
+fast:  /* Set the terminal modes. */
+       if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
+               if (errno == EINTR)
+                       goto fast;
+               msgq(sp, M_SYSERR, "tcsetattr");
+err:           (void)cl_vi_end(sp->gp);
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * cl_vi_end --
+ *     Shutdown the vi screen.
+ */
+static int
+cl_vi_end(GS *gp)
+{
+       CL_PRIVATE *clp;
+
+       clp = GCLP(gp);
+
+       /* Restore the cursor keys to normal mode. */
+       (void)keypad(stdscr, FALSE);
+
+       /*
+        * If we were running vi when we quit, scroll the screen up a single
+        * line so we don't lose any information.
+        *
+        * Move to the bottom of the window (some endwin implementations don't
+        * do this for you).
+        */
+       if (!F_ISSET(clp, CL_IN_EX)) {
+               (void)move(0, 0);
+               (void)deleteln();
+               (void)move(LINES - 1, 0);
+               (void)refresh();
+       }
+
+       cl_freecap(clp);
+
+       /* End curses window. */
+       (void)endwin();
+
+       /*
+        * XXX
+        * The screen TE sequence just got sent.  See the comment in
+        * cl_funcs.c:cl_attr().
+        */
+       clp->ti_te = TE_SENT;
+
+       return (0);
+}
+
+/*
+ * cl_ex_init --
+ *     Initialize the ex screen.
+ */
+static int
+cl_ex_init(SCR *sp)
+{
+       CL_PRIVATE *clp;
+
+       clp = CLP(sp);
+
+       /* If already initialized, just set the terminal modes. */
+       if (F_ISSET(clp, CL_SCR_EX_INIT))
+               goto fast;
+
+       /* If not reading from a file, we're done. */
+       if (!F_ISSET(clp, CL_STDIN_TTY))
+               return (0);
+
+       /* Get the ex termcap/terminfo strings. */
+       (void)cl_getcap(sp, "cup", &clp->cup);
+       (void)cl_getcap(sp, "smso", &clp->smso);
+       (void)cl_getcap(sp, "rmso", &clp->rmso);
+       (void)cl_getcap(sp, "el", &clp->el);
+       (void)cl_getcap(sp, "cuu1", &clp->cuu1);
+
+       /* Enter_standout_mode and exit_standout_mode are paired. */
+       if (clp->smso == NULL || clp->rmso == NULL) {
+               if (clp->smso != NULL) {
+                       free(clp->smso);
+                       clp->smso = NULL;
+               }
+               if (clp->rmso != NULL) {
+                       free(clp->rmso);
+                       clp->rmso = NULL;
+               }
+       }
+
+       /*
+        * Turn on canonical mode, with normal input and output processing.
+        * Start with the original terminal settings as the user probably
+        * had them (including any local extensions) set correctly for the
+        * current terminal.
+        *
+        * !!!
+        * We can't get everything that we need portably; for example, ONLCR,
+        * mapping <newline> to <carriage-return> on output isn't required
+        * by POSIX 1003.1b-1993.  If this turns out to be a problem, then
+        * we'll either have to play some games on the mapping, or we'll have
+        * to make all ex printf's output \r\n instead of \n.
+        */
+       clp->ex_enter = clp->orig;
+       clp->ex_enter.c_lflag  |= ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
+#ifdef ECHOCTL
+       clp->ex_enter.c_lflag |= ECHOCTL;
+#endif
+#ifdef ECHOKE
+       clp->ex_enter.c_lflag |= ECHOKE;
+#endif
+       clp->ex_enter.c_iflag |= ICRNL;
+       clp->ex_enter.c_oflag |= OPOST;
+#ifdef ONLCR
+       clp->ex_enter.c_oflag |= ONLCR;
+#endif
+
+fast:  if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) {
+               if (errno == EINTR)
+                       goto fast;
+               msgq(sp, M_SYSERR, "tcsetattr");
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * cl_ex_end --
+ *     Shutdown the ex screen.
+ */
+static int
+cl_ex_end(GS *gp)
+{
+       CL_PRIVATE *clp;
+
+       clp = GCLP(gp);
+
+       cl_freecap(clp);
+
+       return (0);
+}
+
+/*
+ * cl_getcap --
+ *     Retrieve termcap/terminfo strings.
+ *
+ * PUBLIC: int cl_getcap __P((SCR *, char *, char **));
+ */
+int
+cl_getcap(SCR *sp, const char *name, char **elementp)
+{
+       size_t len;
+       char *t;
+
+       if ((t = tigetstr(name)) != NULL &&
+           t != (char *)-1 && (len = strlen(t)) != 0) {
+               MALLOC_RET(sp, *elementp, char *, len + 1);
+               memmove(*elementp, t, len + 1);
+       }
+       return (0);
+}
+
+/*
+ * cl_freecap --
+ *     Free any allocated termcap/terminfo strings.
+ */
+static void
+cl_freecap(CL_PRIVATE *clp)
+{
+       if (clp->el != NULL) {
+               free(clp->el);
+               clp->el = NULL;
+       }
+       if (clp->cup != NULL) {
+               free(clp->cup);
+               clp->cup = NULL;
+       }
+       if (clp->cuu1 != NULL) {
+               free(clp->cuu1);
+               clp->cuu1 = NULL;
+       }
+       if (clp->rmso != NULL) {
+               free(clp->rmso);
+               clp->rmso = NULL;
+       }
+       if (clp->smso != NULL) {
+               free(clp->smso);
+               clp->smso = NULL;
+       }
+}
+
+/*
+ * cl_putenv --
+ *     Put a value into the environment.
+ */
+static int
+cl_putenv(SCR *sp, const char *name, const char *str, u_long value)
+{
+       char buf[40];
+
+       if (str == NULL) {
+               (void)snprintf(buf, sizeof(buf), "%lu", value);
+               return (cl_setenv(sp, name, buf));
+       } else
+               return (cl_setenv(sp, name, str));
+}
diff --git a/dist/nvi/cl/cl_term.c b/dist/nvi/cl/cl_term.c
new file mode 100644 (file)
index 0000000..5655f77
--- /dev/null
@@ -0,0 +1,481 @@
+/*     $NetBSD: cl_term.c,v 1.4 2011/11/23 19:25:27 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cl_term.c,v 10.31 2001/07/08 13:06:56 skimo Exp (Berkeley) Date: 2001/07/08 13:06:56";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "cl.h"
+
+static int cl_pfmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+
+/*
+ * XXX
+ * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
+ */
+typedef struct _tklist {
+       const char      *ts;            /* Key's termcap string. */
+       const char      *output;        /* Corresponding vi command. */
+       const char      *name;          /* Name. */
+       u_char   value;                 /* Special value (for lookup). */
+} TKLIST;
+
+#define TKINIT(a, b, c) { a, b, c, 0 }
+
+static TKLIST const c_tklist[] = {     /* Command mappings. */
+       TKINIT("kil1",  "O",    "insert line"),
+       TKINIT("kdch1", "x",    "delete character"),
+       TKINIT("kcud1", "j",    "cursor down"),
+       TKINIT("kel",   "D",    "delete to eol"),
+       TKINIT("kind",  "\004", "scroll down"),                 /* ^D */
+       TKINIT("kll",   "$",    "go to eol"),
+       TKINIT("kend",  "$",    "go to eol"),
+       TKINIT("khome", "^",    "go to sol"),
+       TKINIT("kich1", "i",    "insert at cursor"),
+       TKINIT("kdl1",  "dd",   "delete line"),
+       TKINIT("kcub1", "h",    "cursor left"),
+       TKINIT("knp",   "\006", "page down"),                   /* ^F */
+       TKINIT("kpp",   "\002", "page up"),                     /* ^B */
+       TKINIT("kri",   "\025", "scroll up"),                   /* ^U */
+       TKINIT("ked",   "dG",   "delete to end of screen"),
+       TKINIT("kcuf1", "l",    "cursor right"),
+       TKINIT("kcuu1", "k",    "cursor up"),
+       TKINIT(NULL, NULL, NULL),
+};
+static TKLIST const m1_tklist[] = {    /* Input mappings (lookup). */
+       TKINIT(NULL, NULL, NULL),
+};
+static TKLIST const m2_tklist[] = {    /* Input mappings (set or delete). */
+       TKINIT("kcud1",  "\033ja",      "cursor down"),         /* ^[ja */
+       TKINIT("kcub1",  "\033ha",      "cursor left"),         /* ^[ha */
+       TKINIT("kcuu1",  "\033ka",      "cursor up"),           /* ^[ka */
+       TKINIT("kcuf1",  "\033la",      "cursor right"),        /* ^[la */
+       TKINIT(NULL, NULL, NULL),
+};
+
+/*
+ * cl_term_init --
+ *     Initialize the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int cl_term_init __P((SCR *));
+ */
+int
+cl_term_init(SCR *sp)
+{
+       KEYLIST *kp;
+       SEQ *qp;
+       TKLIST const *tkp;
+       char *t;
+       CHAR_T name[60];
+       CHAR_T output[5];
+       CHAR_T ts[20];
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /* Command mappings. */
+       for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
+               if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
+                       continue;
+               CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
+               MEMCPYW(name, wp, wlen);
+               CHAR2INT(sp, t, strlen(t), wp, wlen);
+               MEMCPYW(ts, wp, wlen);
+               CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
+               MEMCPYW(output, wp, wlen);
+               if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
+                   output, strlen(tkp->output), SEQ_COMMAND,
+                   SEQ_NOOVERWRITE | SEQ_SCREEN))
+                       return (1);
+       }
+
+       /* Input mappings needing to be looked up. */
+       for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
+               if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
+                       continue;
+               for (kp = keylist;; ++kp)
+                       if (kp->value == tkp->value)
+                               break;
+               if (kp == NULL)
+                       continue;
+               CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
+               MEMCPYW(name, wp, wlen);
+               CHAR2INT(sp, t, strlen(t), wp, wlen);
+               MEMCPYW(ts, wp, wlen);
+               output[0] = (UCHAR_T)kp->ch;
+               if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
+                   output, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
+                       return (1);
+       }
+
+       /* Input mappings that are already set or are text deletions. */
+       for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
+               if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
+                       continue;
+               /*
+                * !!!
+                * Some terminals' <cursor_left> keys send single <backspace>
+                * characters.  This is okay in command mapping, but not okay
+                * in input mapping.  That combination is the only one we'll
+                * ever see, hopefully, so kluge it here for now.
+                */
+               if (!strcmp(t, "\b"))
+                       continue;
+               if (tkp->output == NULL) {
+                       CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
+                       MEMCPYW(name, wp, wlen);
+                       CHAR2INT(sp, t, strlen(t), wp, wlen);
+                       MEMCPYW(ts, wp, wlen);
+                       if (seq_set(sp, name, strlen(tkp->name),
+                           ts, strlen(t), NULL, 0,
+                           SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
+                               return (1);
+               } else {
+                       CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
+                       MEMCPYW(name, wp, wlen);
+                       CHAR2INT(sp, t, strlen(t), wp, wlen);
+                       MEMCPYW(ts, wp, wlen);
+                       CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
+                       MEMCPYW(output, wp, wlen);
+                       if (seq_set(sp, name, strlen(tkp->name),
+                           ts, strlen(t), output, strlen(tkp->output),
+                           SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
+                               return (1);
+               }
+       }
+
+       /*
+        * Rework any function key mappings that were set before the
+        * screen was initialized.
+        */
+       for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
+               if (F_ISSET(qp, SEQ_FUNCMAP))
+                       (void)cl_pfmap(sp, qp->stype,
+                           qp->input, qp->ilen, qp->output, qp->olen);
+       return (0);
+}
+
+/*
+ * cl_term_end --
+ *     End the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int cl_term_end __P((GS *));
+ */
+int
+cl_term_end(GS *gp)
+{
+       SEQ *qp, *nqp;
+
+       /* Delete screen specific mappings. */
+       for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
+               nqp = qp->q.le_next;
+               if (F_ISSET(qp, SEQ_SCREEN))
+                       (void)seq_mdel(qp);
+       }
+       return (0);
+}
+
+/*
+ * cl_fmap --
+ *     Map a function key.
+ *
+ * PUBLIC: int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ */
+int
+cl_fmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
+{
+       /* Ignore until the screen is running, do the real work then. */
+       if (F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_SCR_VI))
+               return (0);
+       if (F_ISSET(sp, SC_EX) && !F_ISSET(sp, SC_SCR_EX))
+               return (0);
+
+       return (cl_pfmap(sp, stype, from, flen, to, tlen));
+}
+
+/*
+ * cl_pfmap --
+ *     Map a function key (private version).
+ */
+static int
+cl_pfmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
+{
+       size_t nlen;
+       char *p;
+       char name[64];
+       CHAR_T mykeyname[64];
+       CHAR_T ts[20];
+       const CHAR_T *wp;
+       size_t wlen;
+
+       (void)snprintf(name, sizeof(name), "kf%d", 
+                       (int)STRTOL(from+1,NULL,10));
+       if ((p = tigetstr(name)) == NULL ||
+           p == (char *)-1 || strlen(p) == 0)
+               p = NULL;
+       if (p == NULL) {
+               msgq_wstr(sp, M_ERR, from, "233|This terminal has no %s key");
+               return (1);
+       }
+
+       nlen = SPRINTF(mykeyname,
+           SIZE(mykeyname), L("function key %d"), 
+                       (int)STRTOL(from+1,NULL,10));
+       CHAR2INT(sp, p, strlen(p), wp, wlen);
+       MEMCPYW(ts, wp, wlen);
+       return (seq_set(sp, mykeyname, nlen,
+           ts, strlen(p), to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN));
+}
+
+/*
+ * cl_optchange --
+ *     Curses screen specific "option changed" routine.
+ *
+ * PUBLIC: int cl_optchange __P((SCR *, int, const char *, u_long *));
+ */
+int
+cl_optchange(SCR *sp, int opt, const char *str, u_long *valp)
+{
+       CL_PRIVATE *clp;
+
+       clp = CLP(sp);
+
+       switch (opt) {
+       case O_COLUMNS:
+       case O_LINES:
+       case O_TERM:
+               /*
+                * Changing the columns, lines or terminal require that
+                * we restart the screen.
+                */
+               F_SET(sp->gp, G_SRESTART);
+               F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+               break;
+       case O_MESG:
+               (void)cl_omesg(sp, clp, *valp);
+               break;
+       case O_WINDOWNAME:
+               if (*valp) {
+                       F_SET(clp, CL_RENAME_OK);
+
+                       /*
+                        * If the screen is live, i.e. we're not reading the
+                        * .exrc file, update the window.
+                        */
+                       if (sp->frp != NULL && sp->frp->name != NULL)
+                               (void)cl_rename(sp, sp->frp->name, 1);
+               } else {
+                       F_CLR(clp, CL_RENAME_OK);
+
+                       (void)cl_rename(sp, NULL, 0);
+               }
+               break;
+       }
+       return (0);
+}
+
+/*
+ * cl_omesg --
+ *     Turn the tty write permission on or off.
+ *
+ * PUBLIC: int cl_omesg __P((SCR *, CL_PRIVATE *, int));
+ */
+int
+cl_omesg(SCR *sp, CL_PRIVATE *clp, int on)
+{
+       struct stat sb;
+       char *tty;
+
+       /* Find the tty, get the current permissions. */
+       if ((tty = ttyname(STDERR_FILENO)) == NULL) {
+               if (sp != NULL)
+                       msgq(sp, M_SYSERR, "stderr");
+               return (1);
+       }
+       if (stat(tty, &sb) < 0) {
+               if (sp != NULL)
+                       msgq(sp, M_SYSERR, "%s", tty);
+               return (1);
+       }
+
+       /* Save the original status if it's unknown. */
+       if (clp->tgw == TGW_UNKNOWN)
+               clp->tgw = sb.st_mode & S_IWGRP ? TGW_SET : TGW_UNSET;
+
+       /* Toggle the permissions. */
+       if (on) {
+               if (chmod(tty, sb.st_mode | S_IWGRP) < 0) {
+                       if (sp != NULL)
+                               msgq(sp, M_SYSERR,
+                                   "046|messages not turned on: %s", tty);
+                       return (1);
+               }
+       } else
+               if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) {
+                       if (sp != NULL)
+                               msgq(sp, M_SYSERR,
+                                   "045|messages not turned off: %s", tty);
+                       return (1);
+               }
+       return (0);
+}
+
+/*
+ * cl_ssize --
+ *     Return the terminal size.
+ *
+ * PUBLIC: int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
+ */
+int
+cl_ssize(SCR *sp, int sigwinch, size_t *rowp, size_t *colp, int *changedp)
+{
+#ifdef TIOCGWINSZ
+       struct winsize win;
+#endif
+       size_t col, row;
+       int rval;
+       char *p;
+
+       /* Assume it's changed. */
+       if (changedp != NULL)
+               *changedp = 1;
+
+       /*
+        * !!!
+        * sp may be NULL.
+        *
+        * Get the screen rows and columns.  If the values are wrong, it's
+        * not a big deal -- as soon as the user sets them explicitly the
+        * environment will be set and the screen package will use the new
+        * values.
+        *
+        * Try TIOCGWINSZ.
+        */
+       row = col = 0;
+#ifdef TIOCGWINSZ
+       if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
+               row = win.ws_row;
+               col = win.ws_col;
+       }
+#endif
+       /* If here because of suspend or a signal, only trust TIOCGWINSZ. */
+       if (sigwinch) {
+               /*
+                * Somebody didn't get TIOCGWINSZ right, or has suspend
+                * without window resizing support.  The user just lost,
+                * but there's nothing we can do.
+                */
+               if (row == 0 || col == 0) {
+                       if (changedp != NULL)
+                               *changedp = 0;
+                       return (0);
+               }
+
+               /*
+                * SunOS systems deliver SIGWINCH when windows are uncovered
+                * as well as when they change size.  In addition, we call
+                * here when continuing after being suspended since the window
+                * may have changed size.  Since we don't want to background
+                * all of the screens just because the window was uncovered,
+                * ignore the signal if there's no change.
+                */
+               if (sp != NULL &&
+                   row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS)) {
+                       if (changedp != NULL)
+                               *changedp = 0;
+                       return (0);
+               }
+
+               if (rowp != NULL)
+                       *rowp = row;
+               if (colp != NULL)
+                       *colp = col;
+               resizeterm(row, col);
+               return (0);
+       }
+
+       /*
+        * !!!
+        * If TIOCGWINSZ failed, or had entries of 0, try termcap.  This
+        * routine is called before any termcap or terminal information
+        * has been set up.  If there's no TERM environmental variable set,
+        * let it go, at least ex can run.
+        */
+       if (row == 0 || col == 0) {
+               if ((p = getenv("TERM")) == NULL)
+                       goto noterm;
+               if (row == 0) {
+                       if ((rval = tigetnum("lines")) < 0)
+                               msgq(sp, M_SYSERR, "tigetnum: lines");
+                       else
+                               row = rval;
+               }
+               if (col == 0) {
+                       if ((rval = tigetnum("cols")) < 0)
+                               msgq(sp, M_SYSERR, "tigetnum: cols");
+                       else
+                               col = rval;
+               }
+       }
+
+       /* If nothing else, well, it's probably a VT100. */
+noterm:        if (row == 0)
+               row = 24;
+       if (col == 0)
+               col = 80;
+
+       /*
+        * !!!
+        * POSIX 1003.2 requires the environment to override everything.
+        * Often, people can get nvi to stop messing up their screen by
+        * deleting the LINES and COLUMNS environment variables from their
+        * dot-files.
+        */
+       if ((p = getenv("LINES")) != NULL)
+               row = strtol(p, NULL, 10);
+       if ((p = getenv("COLUMNS")) != NULL)
+               col = strtol(p, NULL, 10);
+
+       if (rowp != NULL)
+               *rowp = row;
+       if (colp != NULL)
+               *colp = col;
+       return (0);
+}
+
+/*
+ * cl_putchar --
+ *     Function version of putchar, for tputs.
+ *
+ * PUBLIC: int cl_putchar __P((int));
+ */
+int
+cl_putchar(int ch)
+{
+       return (putchar(ch));
+}
diff --git a/dist/nvi/cl/extern.h b/dist/nvi/cl/extern.h
new file mode 100644 (file)
index 0000000..8f91515
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: extern.h,v 1.3 2010/02/03 15:34:37 roy Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+#ifndef HAVE_CURSES_WADDNSTR
+int waddnstr __P((WINDOW*, char *, int));
+#endif
+#ifndef HAVE_CURSES_BEEP
+void beep __P((void));
+#endif
+#ifndef HAVE_CURSES_FLASH
+void flash __P((void));
+#endif
+#ifndef HAVE_CURSES_IDLOK
+void idlok __P((WINDOW *, int));
+#endif
+#ifndef HAVE_CURSES_KEYPAD
+int keypad __P((void *, int));
+#endif
+#ifndef HAVE_CURSES_NEWTERM
+void *newterm __P((const char *, FILE *, FILE *));
+#endif
+#ifndef HAVE_CURSES_SETUPTERM
+void setupterm __P((char *, int, int *));
+#endif
+#ifndef HAVE_CURSES_TIGETSTR
+char *tigetstr __P((const char *));
+int tigetnum __P((const char *));
+#endif
+int cl_waddstr __P((SCR *, const CHAR_T *, size_t));
+int cl_addstr __P((SCR *, const char *, size_t));
+int cl_attr __P((SCR *, scr_attr_t, int));
+int cl_baud __P((SCR *, u_long *));
+int cl_bell __P((SCR *));
+int cl_clrtoeol __P((SCR *));
+int cl_cursor __P((SCR *, size_t *, size_t *));
+int cl_deleteln __P((SCR *));
+int cl_discard __P((SCR *, SCR **));
+int cl_ex_adjust __P((SCR *, exadj_t));
+int cl_insertln __P((SCR *));
+int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+int cl_move __P((SCR *, size_t, size_t));
+int cl_refresh __P((SCR *, int));
+int cl_rename __P((SCR *, char *, int));
+void cl_setname __P((GS *, char *));
+int cl_split __P((SCR *, SCR *));
+int cl_suspend __P((SCR *, int *));
+void cl_usage __P((void));
+int sig_init __P((GS *, SCR *));
+int cl_event __P((SCR *, EVENT *, u_int32_t, int));
+int cl_screen __P((SCR *, u_int32_t));
+int cl_quit __P((GS *));
+int cl_getcap __P((SCR *, const char *, char **));
+int cl_term_init __P((SCR *));
+int cl_term_end __P((GS *));
+int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+int cl_optchange __P((SCR *, int, const char *, u_long *));
+int cl_omesg __P((SCR *, CL_PRIVATE *, int));
+int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
+int cl_putchar __P((int));
diff --git a/dist/nvi/clib/bsearch.c b/dist/nvi/clib/bsearch.c
new file mode 100644 (file)
index 0000000..e311614
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD: bsearch.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)bsearch.c    8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "port.h"
+
+/*
+ * Perform a binary search.
+ *
+ * The code below is a bit sneaky.  After a comparison fails, we
+ * divide the work in half by moving either left or right. If lim
+ * is odd, moving left simply involves halving lim: e.g., when lim
+ * is 5 we look at item 2, so we change lim to 2 so that we will
+ * look at items 0 & 1.  If lim is even, the same applies.  If lim
+ * is odd, moving right again involes halving lim, this time moving
+ * the base up one item past p: e.g., when lim is 5 we change base
+ * to item 3 and make lim 2 so that we will look at items 3 and 4.
+ * If lim is even, however, we have to shrink it by one before
+ * halving: e.g., when lim is 4, we still looked at item 2, so we
+ * have to make lim 3, then halve, obtaining 1, so that we will only
+ * look at item 3.
+ *
+ * PUBLIC: #ifndef HAVE_BSEARCH
+ * PUBLIC: void        *bsearch __P((const void *, const void *, size_t,
+ * PUBLIC:    size_t, int (*)(const void *, const void *)));
+ * PUBLIC: #endif
+ */
+void *
+bsearch(register const void *key, const void *base0, size_t nmemb, register size_t size, register int (*compar) (const void *, const void *))
+{
+       register const char *base = base0;
+       register size_t lim;
+       register int cmp;
+       register const void *p;
+
+       for (lim = nmemb; lim != 0; lim >>= 1) {
+               p = base + (lim >> 1) * size;
+               cmp = (*compar)(key, p);
+               if (cmp == 0)
+                       return ((void *)p);
+               if (cmp > 0) {  /* key > p: move right */
+                       base = (char *)p + size;
+                       lim--;
+               }               /* else move left */
+       }
+       return (NULL);
+}
diff --git a/dist/nvi/clib/env.c b/dist/nvi/clib/env.c
new file mode 100644 (file)
index 0000000..ccd3593
--- /dev/null
@@ -0,0 +1,160 @@
+/*     $NetBSD: env.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)getenv.c     8.1 (Berkeley) 6/4/93";
+static const char sccsid[] = "@(#)setenv.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * __findenv --
+ *     Returns pointer to value associated with name, if any, else NULL.
+ *     Sets offset to be the offset of the name/value combination in the
+ *     environmental array, for use by setenv(3) and unsetenv(3).
+ *     Explicitly removes '=' in argument name.
+ *
+ *     This routine *should* be a static; don't use it.
+ */
+static char *
+__findenv(register char *name, int *offset)
+{
+       extern char **environ;
+       register int len;
+       register char *np;
+       register char **p, *c;
+
+       if (name == NULL || environ == NULL)
+               return (NULL);
+       for (np = name; *np && *np != '='; ++np)
+               continue;
+       len = np - name;
+       for (p = environ; (c = *p) != NULL; ++p)
+               if (strncmp(c, name, len) == 0 && c[len] == '=') {
+                       *offset = p - environ;
+                       return (c + len + 1);
+               }
+       return (NULL);
+}
+
+#ifndef HAVE_SETENV
+/*
+ * setenv --
+ *     Set the value of the environmental variable "name" to be
+ *     "value".  If rewrite is set, replace any current value.
+ *
+ * PUBLIC: #ifndef HAVE_SETENV
+ * PUBLIC: int setenv __P((const char *, const char *, int));
+ * PUBLIC: #endif
+ */
+setenv(name, value, rewrite)
+       register char *name;
+       register char *value;
+       int rewrite;
+{
+       extern char **environ;
+       static int alloced;                     /* if allocated space before */
+       register char *c;
+       int l_value, offset;
+
+       if (*value == '=')                      /* no `=' in value */
+               ++value;
+       l_value = strlen(value);
+       if ((c = __findenv(name, &offset))) {   /* find if already exists */
+               if (!rewrite)
+                       return (0);
+               if (strlen(c) >= l_value) {     /* old larger; copy over */
+                       while (*c++ = *value++);
+                       return (0);
+               }
+       } else {                                        /* create new slot */
+               register int cnt;
+               register char **p;
+
+               for (p = environ, cnt = 0; *p; ++p, ++cnt);
+               if (alloced) {                  /* just increase size */
+                       environ = (char **)realloc((char *)environ,
+                           (size_t)(sizeof(char *) * (cnt + 2)));
+                       if (!environ)
+                               return (-1);
+               }
+               else {                          /* get new space */
+                       alloced = 1;            /* copy old entries into it */
+                       p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
+                       if (!p)
+                               return (-1);
+                       memmove(p, environ, cnt * sizeof(char *));
+                       environ = p;
+               }
+               environ[cnt + 1] = NULL;
+               offset = cnt;
+       }
+       for (c = (char *)name; *c && *c != '='; ++c);   /* no `=' in name */
+       if (!(environ[offset] =                 /* name + `=' + value */
+           malloc((size_t)((int)(c - name) + l_value + 2))))
+               return (-1);
+       for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
+       for (*c++ = '='; *c++ = *value++;);
+       return (0);
+}
+#endif
+
+#ifndef HAVE_UNSETENV
+/*
+ * unsetenv(name) --
+ *     Delete environmental variable "name".
+ *
+ * PUBLIC: #ifndef HAVE_UNSETENV
+ * PUBLIC: void unsetenv __P((const char *));
+ * PUBLIC: #endif
+ */
+void
+unsetenv(name)
+       char *name;
+{
+       extern char **environ;
+       register char **p;
+       int offset;
+
+       while (__findenv(name, &offset))        /* if set multiple times */
+               for (p = &environ[offset];; ++p)
+                       if (!(*p = *(p + 1)))
+                               break;
+}
+#endif
diff --git a/dist/nvi/clib/gethostname.c b/dist/nvi/clib/gethostname.c
new file mode 100644 (file)
index 0000000..d53dbf9
--- /dev/null
@@ -0,0 +1,24 @@
+/*     $NetBSD: gethostname.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+#include "config.h"
+
+/*
+ * Solaris doesn't include the gethostname call by default.
+ */
+#include <sys/utsname.h>
+#include <sys/systeminfo.h>
+
+#include <netdb.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_GETHOSTNAME
+ * PUBLIC: int gethostname __P((char *, int));
+ * PUBLIC: #endif
+ */
+int
+gethostname(host, len)
+       char *host;
+       int len;
+{
+       return (sysinfo(SI_HOSTNAME, host, len) == -1 ? -1 : 0);
+}
diff --git a/dist/nvi/clib/iswblank.c b/dist/nvi/clib/iswblank.c
new file mode 100644 (file)
index 0000000..930363e
--- /dev/null
@@ -0,0 +1,16 @@
+/*     $NetBSD: iswblank.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "Id: iswblank.c,v 1.1 2001/10/11 19:22:29 skimo Exp";
+#endif /* LIBC_SCCS and not lint */
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+iswblank (wint_t wc)
+{
+    return iswctype(wc, wctype("blank"));
+}
diff --git a/dist/nvi/clib/memchr.c b/dist/nvi/clib/memchr.c
new file mode 100644 (file)
index 0000000..ddeff5f
--- /dev/null
@@ -0,0 +1,64 @@
+/*     $NetBSD: memchr.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)memchr.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_MEMCHR
+ * PUBLIC: void *memchr __P((const void *, int, size_t));
+ * PUBLIC: #endif
+ */
+void *
+memchr(const void *s, register unsigned char c, register size_t n)
+{
+       if (n != 0) {
+               register const unsigned char *p = s;
+
+               do {
+                       if (*p++ == c)
+                               return ((void *)(p - 1));
+               } while (--n != 0);
+       }
+       return (NULL);
+}
diff --git a/dist/nvi/clib/memset.c b/dist/nvi/clib/memset.c
new file mode 100644 (file)
index 0000000..ae463db
--- /dev/null
@@ -0,0 +1,139 @@
+/*     $NetBSD: memset.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Hibler and Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)memset.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <string.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_MEMSET
+ * PUBLIC: void *memset __P((void *, int, size_t));
+ * PUBLIC: #endif
+ */
+#define        wsize   sizeof(u_int)
+#define        wmask   (wsize - 1)
+
+#ifdef BZERO
+#define        RETURN  return
+#define        VAL     0
+#define        WIDEVAL 0
+
+void
+bzero(dst0, length)
+       void *dst0;
+       register size_t length;
+#else
+#define        RETURN  return (dst0)
+#define        VAL     c0
+#define        WIDEVAL c
+
+void *
+memset(void *dst0, register int c0, register size_t length)
+                  
+                       
+                              
+#endif
+{
+       register size_t t;
+       register u_int c;
+       register u_char *dst;
+
+       dst = dst0;
+       /*
+        * If not enough words, just fill bytes.  A length >= 2 words
+        * guarantees that at least one of them is `complete' after
+        * any necessary alignment.  For instance:
+        *
+        *      |-----------|-----------|-----------|
+        *      |00|01|02|03|04|05|06|07|08|09|0A|00|
+        *                ^---------------------^
+        *               dst             dst+length-1
+        *
+        * but we use a minimum of 3 here since the overhead of the code
+        * to do word writes is substantial.
+        */ 
+       if (length < 3 * wsize) {
+               while (length != 0) {
+                       *dst++ = VAL;
+                       --length;
+               }
+               RETURN;
+       }
+
+#ifndef BZERO
+       if ((c = (u_char)c0) != 0) {    /* Fill the word. */
+               c = (c << 8) | c;       /* u_int is 16 bits. */
+#if UINT_MAX > 0xffff
+               c = (c << 16) | c;      /* u_int is 32 bits. */
+#endif
+#if UINT_MAX > 0xffffffff
+               c = (c << 32) | c;      /* u_int is 64 bits. */
+#endif
+       }
+#endif
+       /* Align destination by filling in bytes. */
+       if ((t = (int)dst & wmask) != 0) {
+               t = wsize - t;
+               length -= t;
+               do {
+                       *dst++ = VAL;
+               } while (--t != 0);
+       }
+
+       /* Fill words.  Length was >= 2*words so we know t >= 1 here. */
+       t = length / wsize;
+       do {
+               *(u_int *)dst = WIDEVAL;
+               dst += wsize;
+       } while (--t != 0);
+
+       /* Mop up trailing bytes, if any. */
+       t = length & wmask;
+       if (t != 0)
+               do {
+                       *dst++ = VAL;
+               } while (--t != 0);
+       RETURN;
+}
diff --git a/dist/nvi/clib/mkstemp.c b/dist/nvi/clib/mkstemp.c
new file mode 100644 (file)
index 0000000..d7a8060
--- /dev/null
@@ -0,0 +1,131 @@
+/*     $NetBSD: mkstemp.c,v 1.2 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)mktemp.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+
+static int _gettemp(char *path, register int *doopen);
+
+/*
+ * PUBLIC: #ifndef HAVE_MKSTEMP
+ * PUBLIC: int mkstemp __P((char *));
+ * PUBLIC: #endif
+ */
+mkstemp(char *path)
+{
+       int fd;
+
+       return (_gettemp(path, &fd) ? fd : -1);
+}
+
+char *
+mktemp(char *path)
+{
+       return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
+}
+
+static
+_gettemp(char *path, register int *doopen)
+{
+       extern int errno;
+       register char *start, *trv;
+       struct stat sbuf;
+       u_int pid;
+
+       pid = getpid();
+       for (trv = path; *trv; ++trv);          /* extra X's get set to 0's */
+       while (*--trv == 'X') {
+               *trv = (pid % 10) + '0';
+               pid /= 10;
+       }
+
+       /*
+        * check the target directory; if you have six X's and it
+        * doesn't exist this runs for a *very* long time.
+        */
+       for (start = trv + 1;; --trv) {
+               if (trv <= path)
+                       break;
+               if (*trv == '/') {
+                       *trv = '\0';
+                       if (stat(path, &sbuf))
+                               return(0);
+                       if (!S_ISDIR(sbuf.st_mode)) {
+                               errno = ENOTDIR;
+                               return(0);
+                       }
+                       *trv = '/';
+                       break;
+               }
+       }
+
+       for (;;) {
+               if (doopen) {
+                       if ((*doopen =
+                           open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+                               return(1);
+                       if (errno != EEXIST)
+                               return(0);
+               }
+               else if (stat(path, &sbuf))
+                       return(errno == ENOENT ? 1 : 0);
+
+               /* tricky little algorithm for backward compatibility */
+               for (trv = start;;) {
+                       if (!*trv)
+                               return(0);
+                       if (*trv == 'z')
+                               *trv++ = 'a';
+                       else {
+                               if (isdigit((unsigned char)*trv))
+                                       *trv = 'a';
+                               else
+                                       ++*trv;
+                               break;
+                       }
+               }
+       }
+       /*NOTREACHED*/
+}
diff --git a/dist/nvi/clib/mmap.c b/dist/nvi/clib/mmap.c
new file mode 100644 (file)
index 0000000..4cf6e55
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: mmap.c,v 1.1.1.2 2008/05/18 14:29:38 aymeric Exp $ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * This function fakes mmap() by reading `len' bytes from the file descriptor
+ * `fd' and returning a pointer to that memory.  The "mapped" region can later
+ * be deallocated with munmap().
+ *
+ * Note: ONLY reading is supported and only reading of the exact size of the
+ * file will work.
+ *
+ * PUBLIC: #ifndef HAVE_MMAP
+ * PUBLIC: char *mmap __P((char *, size_t, int, int, int, off_t));
+ * PUBLIC: #endif
+ */
+char *
+mmap(char *addr, size_t len, int prot, int flags, int fd, off_t off)
+{
+       char *ptr;
+
+       if ((ptr = (char *)malloc(len)) == 0)
+               return ((char *)-1);
+       if (read(fd, ptr, len) < 0) {
+               free(ptr);
+               return ((char *)-1);
+       }
+       return (ptr);
+}
+
+/*
+ * PUBLIC: #ifndef HAVE_MMAP
+ * PUBLIC: int munmap __P((char *, size_t));
+ * PUBLIC: #endif
+ */
+int
+munmap(char *addr, size_t len)
+{
+       free(addr);
+       return (0);
+}
diff --git a/dist/nvi/clib/snprintf.c b/dist/nvi/clib/snprintf.c
new file mode 100644 (file)
index 0000000..b814660
--- /dev/null
@@ -0,0 +1,47 @@
+/*     $NetBSD: snprintf.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/*
+ * PUBLIC: #ifndef HAVE_SNPRINTF
+ * PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
+ * PUBLIC: #endif
+ */
+int
+#ifdef __STDC__
+snprintf(char *str, size_t n, const char *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+       char *str;
+       size_t n;
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+       int rval;
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+#ifdef SPRINTF_RET_CHARPNT
+       (void)vsprintf(str, fmt, ap);
+       va_end(ap);
+       return (strlen(str));
+#else
+       rval = vsprintf(str, fmt, ap);
+       va_end(ap);
+       return (rval);
+#endif
+}
diff --git a/dist/nvi/clib/strdup.c b/dist/nvi/clib/strdup.c
new file mode 100644 (file)
index 0000000..342a64d
--- /dev/null
@@ -0,0 +1,64 @@
+/*     $NetBSD: strdup.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strdup.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_STRDUP
+ * PUBLIC: char *strdup __P((const char *));
+ * PUBLIC: #endif
+ */
+char *
+strdup(const char *str)
+{
+       size_t len;
+       char *copy;
+
+       len = strlen(str) + 1;
+       if (!(copy = malloc((u_int)len)))
+               return (NULL);
+       memcpy(copy, str, len);
+       return (copy);
+}
diff --git a/dist/nvi/clib/strpbrk.c b/dist/nvi/clib/strpbrk.c
new file mode 100644 (file)
index 0000000..e6cc953
--- /dev/null
@@ -0,0 +1,63 @@
+/*     $NetBSD: strpbrk.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+/*
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strpbrk.c    8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+/*
+ * Find the first occurrence in s1 of a character in s2 (excluding NUL).
+ *
+ * PUBLIC: #ifndef HAVE_STRPBRK
+ * PUBLIC: char *strpbrk __P((const char *, const char *));
+ * PUBLIC: #endif
+ */
+char *
+strpbrk(register const char *s1, register const char *s2)
+{
+       register const char *scanp;
+       register int c, sc;
+
+       while ((c = *s1++) != 0) {
+               for (scanp = s2; (sc = *scanp++) != 0;)
+                       if (sc == c)
+                               return ((char *)(s1 - 1));
+       }
+       return (NULL);
+}
diff --git a/dist/nvi/clib/strsep.c b/dist/nvi/clib/strsep.c
new file mode 100644 (file)
index 0000000..cf92a4c
--- /dev/null
@@ -0,0 +1,85 @@
+/*     $NetBSD: strsep.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strsep.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.  
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ *
+ * PUBLIC: #ifndef HAVE_STRSEP
+ * PUBLIC: char *strsep __P((char **, const char *));
+ * PUBLIC: #endif
+ */
+char *
+strsep(register char **stringp, register const char *delim)
+{
+       register char *s;
+       register const char *spanp;
+       register int c, sc;
+       char *tok;
+
+       if ((s = *stringp) == NULL)
+               return (NULL);
+       for (tok = s;;) {
+               c = *s++;
+               spanp = delim;
+               do {
+                       if ((sc = *spanp++) == c) {
+                               if (c == 0)
+                                       s = NULL;
+                               else
+                                       s[-1] = 0;
+                               *stringp = s;
+                               return (tok);
+                       }
+               } while (sc != 0);
+       }
+       /* NOTREACHED */
+}
diff --git a/dist/nvi/clib/strtol.c b/dist/nvi/clib/strtol.c
new file mode 100644 (file)
index 0000000..042e01f
--- /dev/null
@@ -0,0 +1,133 @@
+/*     $NetBSD: strtol.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strtol.c     8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ *
+ * PUBLIC: #ifndef HAVE_STRTOL
+ * PUBLIC: long strtol __P((const char *, char **, int));
+ * PUBLIC: #endif
+ */
+long
+strtol(const char *nptr, char **endptr, register int base)
+{
+       register const char *s = nptr;
+       register unsigned long acc;
+       register int c;
+       register unsigned long cutoff;
+       register int neg = 0, any, cutlim;
+
+       /*
+        * Skip white space and pick up leading +/- sign if any.
+        * If base is 0, allow 0x for hex and 0 for octal, else
+        * assume decimal; if base is already 16, allow 0x.
+        */
+       do {
+               c = *s++;
+       } while (isspace(c));
+       if (c == '-') {
+               neg = 1;
+               c = *s++;
+       } else if (c == '+')
+               c = *s++;
+       if ((base == 0 || base == 16) &&
+           c == '0' && (*s == 'x' || *s == 'X')) {
+               c = s[1];
+               s += 2;
+               base = 16;
+       }
+       if (base == 0)
+               base = c == '0' ? 8 : 10;
+
+       /*
+        * Compute the cutoff value between legal numbers and illegal
+        * numbers.  That is the largest legal value, divided by the
+        * base.  An input number that is greater than this value, if
+        * followed by a legal input character, is too big.  One that
+        * is equal to this value may be valid or not; the limit
+        * between valid and invalid numbers is then based on the last
+        * digit.  For instance, if the range for longs is
+        * [-2147483648..2147483647] and the input base is 10,
+        * cutoff will be set to 214748364 and cutlim to either
+        * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+        * a value > 214748364, or equal but the next digit is > 7 (or 8),
+        * the number is too big, and we will return a range error.
+        *
+        * Set any if any `digits' consumed; make it negative to indicate
+        * overflow.
+        */
+       cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+       cutlim = cutoff % (unsigned long)base;
+       cutoff /= (unsigned long)base;
+       for (acc = 0, any = 0;; c = *s++) {
+               if (isdigit(c))
+                       c -= '0';
+               else if (isalpha(c))
+                       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+               else
+                       break;
+               if (c >= base)
+                       break;
+               if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+                       any = -1;
+               else {
+                       any = 1;
+                       acc *= base;
+                       acc += c;
+               }
+       }
+       if (any < 0) {
+               acc = neg ? LONG_MIN : LONG_MAX;
+               errno = ERANGE;
+       } else if (neg)
+               acc = -acc;
+       if (endptr != 0)
+               *endptr = (char *)(any ? s - 1 : nptr);
+       return (acc);
+}
diff --git a/dist/nvi/clib/strtoul.c b/dist/nvi/clib/strtoul.c
new file mode 100644 (file)
index 0000000..c61030d
--- /dev/null
@@ -0,0 +1,112 @@
+/*     $NetBSD: strtoul.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strtoul.c    8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ *
+ * PUBLIC: #ifndef HAVE_STRTOUL
+ * PUBLIC: unsigned long strtoul __P((const char *, char **, int));
+ * PUBLIC: #endif
+ */
+unsigned long
+strtoul(const char *nptr, char **endptr, register int base)
+{
+       register const char *s = nptr;
+       register unsigned long acc;
+       register int c;
+       register unsigned long cutoff;
+       register int neg = 0, any, cutlim;
+
+       /*
+        * See strtol for comments as to the logic used.
+        */
+       do {
+               c = *s++;
+       } while (isspace(c));
+       if (c == '-') {
+               neg = 1;
+               c = *s++;
+       } else if (c == '+')
+               c = *s++;
+       if ((base == 0 || base == 16) &&
+           c == '0' && (*s == 'x' || *s == 'X')) {
+               c = s[1];
+               s += 2;
+               base = 16;
+       }
+       if (base == 0)
+               base = c == '0' ? 8 : 10;
+       cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+       cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+       for (acc = 0, any = 0;; c = *s++) {
+               if (isdigit(c))
+                       c -= '0';
+               else if (isalpha(c))
+                       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+               else
+                       break;
+               if (c >= base)
+                       break;
+               if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+                       any = -1;
+               else {
+                       any = 1;
+                       acc *= base;
+                       acc += c;
+               }
+       }
+       if (any < 0) {
+               acc = ULONG_MAX;
+               errno = ERANGE;
+       } else if (neg)
+               acc = -acc;
+       if (endptr != 0)
+               *endptr = (char *)(any ? s - 1 : nptr);
+       return (acc);
+}
diff --git a/dist/nvi/clib/vsnprintf.c b/dist/nvi/clib/vsnprintf.c
new file mode 100644 (file)
index 0000000..e9533e3
--- /dev/null
@@ -0,0 +1,33 @@
+/*     $NetBSD: vsnprintf.c,v 1.1.1.2 2008/05/18 14:29:39 aymeric Exp $ */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/*
+ * PUBLIC: #ifndef HAVE_VSNPRINTF
+ * PUBLIC: int vsnprintf __P((char *, size_t, const char *, ...));
+ * PUBLIC: #endif
+ */
+int
+vsnprintf(str, n, fmt, ap)
+       char *str;
+       size_t n;
+       const char *fmt;
+       va_list ap;
+{
+#ifdef SPRINTF_RET_CHARPNT
+       (void)vsprintf(str, fmt, ap);
+       return (strlen(str));
+#else
+       return (vsprintf(str, fmt, ap));
+#endif
+}
diff --git a/dist/nvi/common/api.c b/dist/nvi/common/api.c
new file mode 100644 (file)
index 0000000..9d2a272
--- /dev/null
@@ -0,0 +1,609 @@
+/*     $NetBSD: api.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1995
+ *     George V. Neville-Neil. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: api.c,v 8.40 2002/06/08 19:30:33 skimo Exp (Berkeley) Date: 2002/06/08 19:30:33";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ex/tag.h"
+
+extern GS *__global_list;                      /* XXX */
+
+/*
+ * api_fscreen --
+ *     Return a pointer to the screen specified by the screen id
+ *     or a file name.
+ *
+ * PUBLIC: SCR *api_fscreen __P((int, char *));
+ */
+SCR *
+api_fscreen(int id, char *name)
+{
+       GS *gp;
+       SCR *tsp;
+       WIN *wp;
+
+       gp = __global_list;
+
+       /* Search the displayed lists. */
+       for (wp = gp->dq.cqh_first;
+           wp != (void *)&gp->dq; wp = wp->q.cqe_next)
+               for (tsp = wp->scrq.cqh_first;
+                   tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
+               if (name == NULL) {
+                       if (id == tsp->id)
+                               return (tsp);
+               } else if (!strcmp(name, tsp->frp->name))
+                       return (tsp);
+
+       /* Search the hidden list. */
+       for (tsp = gp->hq.cqh_first;
+           tsp != (void *)&gp->hq; tsp = tsp->q.cqe_next)
+               if (name == NULL) {
+                       if (id == tsp->id)
+                               return (tsp);
+               } else if (!strcmp(name, tsp->frp->name))
+                       return (tsp);
+       return (NULL);
+}
+
+/*
+ * api_aline --
+ *     Append a line.
+ *
+ * PUBLIC: int api_aline __P((SCR *, db_recno_t, char *, size_t));
+ */
+int
+api_aline(SCR *sp, db_recno_t lno, char *line, size_t len)
+{
+       size_t wblen;
+       const CHAR_T *wbp;
+
+       CHAR2INT(sp, line, len, wbp, wblen);
+
+       return (db_append(sp, 1, lno, wbp, wblen));
+}
+
+/*
+ * api_extend --
+ *     Extend file.
+ *
+ * PUBLIC: int api_extend __P((SCR *, db_recno_t));
+ */
+int 
+api_extend(SCR *sp, db_recno_t lno)
+{
+       db_recno_t lastlno;
+       if (db_last(sp, &lastlno))
+           return 1;
+       while(lastlno < lno)
+           if (db_append(sp, 1, lastlno++, NULL, 0))
+               return 1;
+       return 0;
+}
+
+/*
+ * api_dline --
+ *     Delete a line.
+ *
+ * PUBLIC: int api_dline __P((SCR *, db_recno_t));
+ */
+int
+api_dline(SCR *sp, db_recno_t lno)
+{
+       if (db_delete(sp, lno))
+               return 1;
+       /* change current line if deleted line is that one
+        * or one berfore that
+        */
+       if (sp->lno >= lno && sp->lno > 1)
+               sp->lno--;
+       return 0;
+}
+
+/*
+ * api_gline --
+ *     Get a line.
+ *
+ * PUBLIC: int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *));
+ */
+int
+api_gline(SCR *sp, db_recno_t lno, CHAR_T **linepp, size_t *lenp)
+{
+       int isempty;
+
+       if (db_eget(sp, lno, linepp, lenp, &isempty)) {
+               if (isempty)
+                       msgq(sp, M_ERR, "209|The file is empty");
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * api_iline --
+ *     Insert a line.
+ *
+ * PUBLIC: int api_iline __P((SCR *, db_recno_t, CHAR_T *, size_t));
+ */
+int
+api_iline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len)
+{
+       return (db_insert(sp, lno, line, len));
+}
+
+/*
+ * api_lline --
+ *     Return the line number of the last line in the file.
+ *
+ * PUBLIC: int api_lline __P((SCR *, db_recno_t *));
+ */
+int
+api_lline(SCR *sp, db_recno_t *lnop)
+{
+       return (db_last(sp, lnop));
+}
+
+/*
+ * api_sline --
+ *     Set a line.
+ *
+ * PUBLIC: int api_sline __P((SCR *, db_recno_t, CHAR_T *, size_t));
+ */
+int
+api_sline(SCR *sp, db_recno_t lno, CHAR_T *line, size_t len)
+{
+       return (db_set(sp, lno, line, len));
+}
+
+/*
+ * api_getmark --
+ *     Get the mark.
+ *
+ * PUBLIC: int api_getmark __P((SCR *, int, MARK *));
+ */
+int
+api_getmark(SCR *sp, int markname, MARK *mp)
+{
+       return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
+}
+
+/*
+ * api_setmark --
+ *     Set the mark.
+ *
+ * PUBLIC: int api_setmark __P((SCR *, int, MARK *));
+ */
+int
+api_setmark(SCR *sp, int markname, MARK *mp)
+{
+       return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
+}
+
+/*
+ * api_nextmark --
+ *     Return the first mark if next not set, otherwise return the
+ *     subsequent mark.
+ *
+ * PUBLIC: int api_nextmark __P((SCR *, int, char *));
+ */
+int
+api_nextmark(SCR *sp, int next, char *namep)
+{
+       LMARK *mp;
+
+       mp = sp->ep->marks.lh_first;
+       if (next)
+               for (; mp != NULL; mp = mp->q.le_next)
+                       if (mp->name == *namep) {
+                               mp = mp->q.le_next;
+                               break;
+                       }
+       if (mp == NULL)
+               return (1);
+       *namep = mp->name;
+       return (0);
+}
+
+/*
+ * api_getcursor --
+ *     Get the cursor.
+ *
+ * PUBLIC: int api_getcursor __P((SCR *, MARK *));
+ */
+int
+api_getcursor(SCR *sp, MARK *mp)
+{
+       mp->lno = sp->lno;
+       mp->cno = sp->cno;
+       return (0);
+}
+
+/*
+ * api_setcursor --
+ *     Set the cursor.
+ *
+ * PUBLIC: int api_setcursor __P((SCR *, MARK *));
+ */
+int
+api_setcursor(SCR *sp, MARK *mp)
+{
+       size_t len;
+
+       if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
+               return (1);
+       if (mp->cno > len) {
+               msgq(sp, M_ERR, "Cursor set to nonexistent column");
+               return (1);
+       }
+
+       /* Set the cursor. */
+       sp->lno = mp->lno;
+       sp->cno = mp->cno;
+       return (0);
+}
+
+/*
+ * api_emessage --
+ *     Print an error message.
+ *
+ * PUBLIC: void api_emessage __P((SCR *, char *));
+ */
+void
+api_emessage(SCR *sp, char *text)
+{
+       msgq(sp, M_ERR, "%s", text);
+}
+
+/*
+ * api_imessage --
+ *     Print an informational message.
+ *
+ * PUBLIC: void api_imessage __P((SCR *, char *));
+ */
+void
+api_imessage(SCR *sp, char *text)
+{
+       msgq(sp, M_INFO, "%s", text);
+}
+
+/*
+ * api_edit
+ *     Create a new screen and return its id 
+ *     or edit a new file in the current screen.
+ *
+ * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
+ */
+int
+api_edit(SCR *sp, char *file, SCR **spp, int newscreen)
+{
+       EXCMD cmd;
+       size_t wlen;
+       const CHAR_T *wp;
+
+       if (file) {
+               ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
+               CHAR2INT(sp, file, strlen(file) + 1, wp, wlen);
+               argv_exp0(sp, &cmd, wp, wlen - 1 /* terminating 0 */);
+       } else
+               ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
+       if (newscreen)
+               cmd.flags |= E_NEWSCREEN;               /* XXX */
+       if (cmd.cmd->fn(sp, &cmd))
+               return (1);
+       *spp = sp->nextdisp;
+       return (0);
+}
+
+/*
+ * api_escreen
+ *     End a screen.
+ *
+ * PUBLIC: int api_escreen __P((SCR *));
+ */
+int
+api_escreen(SCR *sp)
+{
+       EXCMD cmd;
+
+       /*
+        * XXX
+        * If the interpreter exits anything other than the current
+        * screen, vi isn't going to update everything correctly.
+        */
+       ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
+       return (cmd.cmd->fn(sp, &cmd));
+}
+
+/*
+ * api_swscreen --
+ *    Switch to a new screen.
+ *
+ * PUBLIC: int api_swscreen __P((SCR *, SCR *));
+ */
+int
+api_swscreen(SCR *sp, SCR *new)
+{
+       /*
+        * XXX
+        * If the interpreter switches from anything other than the
+        * current screen, vi isn't going to update everything correctly.
+        */
+       sp->nextdisp = new;
+       F_SET(sp, SC_SSWITCH);
+
+       return (0);
+}
+
+/*
+ * api_map --
+ *     Map a key.
+ *
+ * PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
+ */
+int
+api_map(SCR *sp, char *name, char *map, size_t len)
+{
+       EXCMD cmd;
+       size_t wlen;
+       const CHAR_T *wp;
+
+       ex_cinit(sp, &cmd, C_MAP, 0, OOBLNO, OOBLNO, 0);
+       CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
+       argv_exp0(sp, &cmd, wp, wlen - 1);
+       CHAR2INT(sp, map, len, wp, wlen);
+       argv_exp0(sp, &cmd, wp, wlen);
+       return (cmd.cmd->fn(sp, &cmd));
+}
+
+/*
+ * api_unmap --
+ *     Unmap a key.
+ *
+ * PUBLIC: int api_unmap __P((SCR *, char *));
+ */
+int 
+api_unmap(SCR *sp, char *name)
+{
+       EXCMD cmd;
+       size_t wlen;
+       const CHAR_T *wp;
+
+       ex_cinit(sp, &cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0);
+       CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
+       argv_exp0(sp, &cmd, wp, wlen - 1);
+       return (cmd.cmd->fn(sp, &cmd));
+}
+
+/*
+ * api_opts_get --
+ *     Return a option value as a string, in allocated memory.
+ *     If the option is of type boolean, boolvalue is (un)set
+ *     according to the value; otherwise boolvalue is -1.
+ *
+ * PUBLIC: int api_opts_get __P((SCR *, CHAR_T *, char **, int *));
+ */
+int
+api_opts_get(SCR *sp, const CHAR_T *name, char **value, int *boolvalue)
+{
+       OPTLIST const *op;
+       int offset;
+
+       if ((op = opts_search(name)) == NULL) {
+               opts_nomatch(sp, name);
+               return (1);
+       }
+
+       offset = op - optlist;
+       if (boolvalue != NULL)
+               *boolvalue = -1;
+       switch (op->type) {
+       case OPT_0BOOL:
+       case OPT_1BOOL:
+               MALLOC_RET(sp, *value, char *, STRLEN(op->name) + 2 + 1);
+               (void)sprintf(*value,
+                   "%s"WS, O_ISSET(sp, offset) ? "" : "no", op->name);
+               if (boolvalue != NULL)
+                       *boolvalue = O_ISSET(sp, offset);
+               break;
+       case OPT_NUM:
+               MALLOC_RET(sp, *value, char *, 20);
+               (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
+               break;
+       case OPT_STR:
+               if (O_STR(sp, offset) == NULL) {
+                       MALLOC_RET(sp, *value, char *, 2);
+                       value[0] = '\0';
+               } else {
+                       MALLOC_RET(sp,
+                           *value, char *, strlen(O_STR(sp, offset)) + 1);
+                       (void)sprintf(*value, "%s", O_STR(sp, offset));
+               }
+               break;
+       }
+       return (0);
+}
+
+/*
+ * api_opts_set --
+ *     Set options.
+ *
+ * PUBLIC: int api_opts_set __P((SCR *, CHAR_T *, char *, u_long, int));
+ */
+int
+api_opts_set(SCR *sp, const CHAR_T *name, 
+            const char *str_value, u_long num_value, int bool_value)
+{
+       ARGS *ap[2], a, b;
+       OPTLIST const *op;
+       int rval;
+       size_t blen;
+       CHAR_T *bp;
+
+       if ((op = opts_search(name)) == NULL) {
+               opts_nomatch(sp, name);
+               return (1);
+       }
+
+       switch (op->type) {
+       case OPT_0BOOL:
+       case OPT_1BOOL:
+               GET_SPACE_RETW(sp, bp, blen, 64);
+               a.len = SPRINTF(bp, 64, L("%s"WS), bool_value ? "" : "no", name);
+               break;
+       case OPT_NUM:
+               GET_SPACE_RETW(sp, bp, blen, 64);
+               a.len = SPRINTF(bp, 64, L(""WS"=%lu"), name, num_value);
+               break;
+       case OPT_STR:
+               GET_SPACE_RETW(sp, bp, blen, 1024);
+               a.len = SPRINTF(bp, 1024, L(""WS"=%s"), name, str_value);
+               break;
+       default:
+               bp = NULL;
+               break;
+       }
+
+       a.bp = bp;
+       b.len = 0;
+       b.bp = NULL;
+       ap[0] = &a;
+       ap[1] = &b;
+       rval = opts_set(sp, ap, NULL);
+
+       FREE_SPACEW(sp, bp, blen);
+
+       return (rval);
+}
+
+/*
+ * api_run_str --
+ *      Execute a string as an ex command.
+ *
+ * PUBLIC: int api_run_str __P((SCR *, char *));
+ */
+int     
+api_run_str(SCR *sp, char *cmd)
+{
+       size_t wlen;
+       const CHAR_T *wp;
+
+       CHAR2INT(sp, cmd, strlen(cmd)+1, wp, wlen);
+       return (ex_run_str(sp, NULL, wp, wlen - 1, 0, 0));
+}
+
+/*
+ * PUBLIC: TAGQ * api_tagq_new __P((SCR*, char*));
+ */
+TAGQ *
+api_tagq_new(SCR *sp, char *tag)
+{
+       TAGQ *tqp;
+       size_t len;
+
+       /* Allocate and initialize the tag queue structure. */
+       len = strlen(tag);
+       CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
+       CIRCLEQ_INIT(&tqp->tagq);
+       tqp->tag = tqp->buf;
+       memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
+
+       return tqp;
+
+alloc_err:
+       return (NULL);
+}
+
+/*
+ * PUBLIC: void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *));
+ */
+void
+api_tagq_add(SCR *sp, TAGQ *tqp, char *filename, char *search, char *msg)
+{
+       TAG *tp;
+       const CHAR_T *wp;
+       size_t wlen;
+       size_t flen = strlen(filename);
+       size_t slen = strlen(search);
+       size_t mlen = strlen(msg);
+
+       CALLOC_GOTO(sp, tp, TAG *, 1, 
+                   sizeof(TAG) - 1 + flen + 1 + 
+                   (slen + 1 + mlen + 1) * sizeof(CHAR_T));
+       tp->fname = (char *)tp->buf;
+       memcpy(tp->fname, filename, flen + 1);
+       tp->fnlen = flen;
+       tp->search = (CHAR_T *)((char *)tp->fname + flen + 1);
+       CHAR2INT(sp, search, slen + 1, wp, wlen);
+       MEMCPYW(tp->search, wp, wlen);
+       tp->slen = slen;
+       tp->msg = tp->search + slen + 1;
+       CHAR2INT(sp, msg, mlen + 1, wp, wlen);
+       MEMCPYW(tp->msg, wp, wlen);
+       tp->mlen = mlen;
+       CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+
+alloc_err:
+       return;
+}
+
+/*
+ * PUBLIC: int api_tagq_push __P((SCR*, TAGQ**));
+ */
+int
+api_tagq_push(SCR *sp, TAGQ **tqpp)
+{
+       TAGQ *tqp;
+
+       tqp = *tqpp;
+
+       *tqpp = 0;
+
+       /* Check to see if we found anything. */
+       if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
+               free(tqp);
+               return 0;
+       }
+
+       tqp->current = tqp->tagq.cqh_first;
+
+       if (tagq_push(sp, tqp, 0, 0))
+               return 1;
+
+       return (0);
+}
+
+/*
+ * PUBLIC: void api_tagq_free __P((SCR*, TAGQ*));
+ */
+void
+api_tagq_free(SCR *sp, TAGQ *tqp)
+{
+       if (tqp)
+               tagq_free(sp, tqp);
+}
diff --git a/dist/nvi/common/args.h b/dist/nvi/common/args.h
new file mode 100644 (file)
index 0000000..92c461c
--- /dev/null
@@ -0,0 +1,31 @@
+/*     $NetBSD: args.h,v 1.1.1.2 2008/05/18 14:29:40 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: args.h,v 10.2 1996/03/06 19:50:07 bostic Exp (Berkeley) Date: 1996/03/06 19:50:07
+ */
+
+/*
+ * Structure for building "argc/argv" vector of arguments.
+ *
+ * !!!
+ * All arguments are nul terminated as well as having an associated length.
+ * The argument vector is NOT necessarily NULL terminated.  The proper way
+ * to check the number of arguments is to use the argc value in the EXCMDARG
+ * structure or to walk the array until an ARGS structure with a length of 0
+ * is found.
+ */
+typedef struct _args {
+       CHAR_T  *bp;            /* Argument. */
+       size_t   blen;          /* Buffer length. */
+       size_t   len;           /* Argument length. */
+
+#define        A_ALLOCATED     0x01    /* If allocated space. */
+       u_int8_t flags;
+} ARGS;
diff --git a/dist/nvi/common/common.h b/dist/nvi/common/common.h
new file mode 100644 (file)
index 0000000..8d1dc24
--- /dev/null
@@ -0,0 +1,112 @@
+/*     $NetBSD: common.h,v 1.3 2012/01/27 16:41:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: common.h,v 10.20 2002/03/02 23:36:22 skimo Exp (Berkeley) Date: 2002/03/02 23:36:22
+ */
+
+/*
+ * Avoid include sys/types.h after definition of pgno_t
+ */
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <bitstring.h>
+/*
+ * Porting information built at configuration time.  Included before
+ * any of nvi's include files.
+ */
+#include "port.h"
+
+/*
+ * Pseudo-local includes.  These are files that are unlikely to exist
+ * on most machines to which we're porting vi, and we want to include
+ * them in a very specific order, regardless.
+ */
+#include "db.h"
+#include <regex.h>
+
+/*
+ * Forward structure declarations.  Not pretty, but the include files
+ * are far too interrelated for a clean solution.
+ */
+typedef struct _cb             CB;
+typedef struct _csc            CSC;
+typedef struct _conv           CONV;
+typedef struct _conv_win       CONVWIN;
+typedef struct _event          EVENT;
+typedef struct _excmd          EXCMD;
+typedef struct _exf            EXF;
+typedef struct _fref           FREF;
+typedef struct _gs             GS;
+typedef struct _lmark          LMARK;
+typedef struct _mark           MARK;
+typedef struct _msg            MSGS;
+typedef struct _option         OPTION;
+typedef struct _optlist                OPTLIST;
+typedef struct _scr            SCR;
+typedef struct _script         SCRIPT;
+typedef struct _seq            SEQ;
+typedef struct _tag            TAG;
+typedef struct _tagf           TAGF;
+typedef struct _tagq           TAGQ;
+typedef struct _text           TEXT;
+typedef struct _win            WIN;
+
+/* Autoindent state. */
+typedef enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_t;
+
+/* Busy message types. */
+typedef enum { BUSY_ON = 1, BUSY_OFF, BUSY_UPDATE } busy_t;
+
+/*
+ * Routines that return a confirmation return:
+ *
+ *     CONF_NO         User answered no.
+ *     CONF_QUIT       User answered quit, eof or an error.
+ *     CONF_YES        User answered yes.
+ */
+typedef enum { CONF_NO, CONF_QUIT, CONF_YES } conf_t;
+
+/* Directions. */
+typedef enum { NOTSET, FORWARD, BACKWARD } dir_t;
+
+/* Line operations. */
+typedef enum { LINE_APPEND, LINE_DELETE, LINE_INSERT, LINE_RESET } lnop_t;
+
+/* Lock return values. */
+typedef enum { LOCK_FAILED, LOCK_SUCCESS, LOCK_UNAVAIL } lockr_t;
+
+/* Sequence types. */
+typedef enum { SEQ_ABBREV, SEQ_COMMAND, SEQ_INPUT } seq_t;
+
+#define        ENTIRE_LINE     ((size_t)-1)
+/*
+ * Local includes.
+ */
+#include "key.h"               /* Required by args.h. */
+#include "args.h"              /* Required by options.h. */
+#include "options.h"           /* Required by screen.h. */
+
+#include "msg.h"               /* Required by gs.h. */
+#include "cut.h"               /* Required by gs.h. */
+#include "seq.h"               /* Required by screen.h. */
+#include "util.h"              /* Required by ex.h. */
+#include "mark.h"              /* Required by gs.h. */
+#include "conv.h"              /* Required by ex.h and screen.h */
+#include "../ex/ex.h"          /* Required by gs.h. */
+#include "gs.h"                        /* Required by screen.h. */
+#include "log.h"               /* Required by screen.h */
+#include "screen.h"            /* Required by exf.h. */
+#include "exf.h"
+#include "mem.h"
+#if defined(USE_DB4_LOGGING)
+#include "vi_auto.h"
+#endif
+
+#include "extern.h"
diff --git a/dist/nvi/common/conv.c b/dist/nvi/common/conv.c
new file mode 100644 (file)
index 0000000..042af12
--- /dev/null
@@ -0,0 +1,414 @@
+/*     $NetBSD: conv.c,v 1.6 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: conv.c,v 1.27 2001/08/18 21:41:41 skimo Exp (Berkeley) Date: 2001/08/18 21:41:41";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+#ifdef USE_ICONV
+#include <langinfo.h>
+#include <iconv.h>
+
+#define LANGCODESET    nl_langinfo(CODESET)
+#else
+typedef int    iconv_t;
+
+#define LANGCODESET    ""
+#endif
+
+#include <locale.h>
+
+#ifdef USE_WIDECHAR
+static int 
+raw2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, size_t *tolen,
+       const CHAR_T **dst)
+{
+    int i;
+    CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1;
+    size_t  *blen = &cw->blen1;
+
+    BINC_RETW(NULL, *tostr, *blen, len);
+
+    *tolen = len;
+    for (i = 0; i < len; ++i)
+       (*tostr)[i] = (u_char) str[i];
+
+    *dst = cw->bp1;
+
+    return 0;
+}
+
+#define CONV_BUFFER_SIZE    512
+/* fill the buffer with codeset encoding of string pointed to by str
+ * left has the number of bytes left in str and is adjusted
+ * len contains the number of bytes put in the buffer
+ */
+#ifdef USE_ICONV
+#define CONVERT(str, left, src, len)                                   \
+    do {                                                               \
+       size_t outleft;                                                 \
+       char *bp = buffer;                                              \
+       outleft = CONV_BUFFER_SIZE;                                     \
+       errno = 0;                                                      \
+       if (iconv(id, (const char **)&str, &left, &bp, &outleft) == (size_t)-1 \
+               /* && errno != E2BIG */)                                \
+           goto err;                                                   \
+       if ((len = CONV_BUFFER_SIZE - outleft) == 0) {                  \
+           error = -left;                                              \
+           goto err;                                                   \
+       }                                                               \
+       src = buffer;                                                   \
+    } while (0)
+#else
+#define CONVERT(str, left, src, len)
+#endif
+
+static int 
+default_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, 
+               size_t *tolen, const CHAR_T **dst, const char *enc)
+{
+    int j;
+    size_t i = 0;
+    CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1;
+    size_t  *blen = &cw->blen1;
+    mbstate_t mbs;
+    size_t   n;
+    ssize_t  nlen = len;
+    const char *src = (const char *)str;
+    iconv_t    id = (iconv_t)-1;
+    char       buffer[CONV_BUFFER_SIZE];
+    size_t     left = len;
+    int                error = 1;
+
+    MEMSET(&mbs, 0, 1);
+    BINC_RETW(NULL, *tostr, *blen, nlen);
+
+#ifdef USE_ICONV
+    if (strcmp(nl_langinfo(CODESET), enc)) {
+       id = iconv_open(nl_langinfo(CODESET), enc);
+       if (id == (iconv_t)-1)
+           goto err;
+       CONVERT(str, left, src, len);
+    }
+#endif
+
+    for (i = 0, j = 0; j < len; ) {
+       n = mbrtowc((*tostr)+i, src+j, len-j, &mbs);
+       /* NULL character converted */
+       if (n == (size_t)-2) error = -(len-j);
+       if (n == (size_t)-1 || n == (size_t)-2) goto err;
+       if (n == 0) n = 1;
+       j += n;
+       if (++i >= *blen) {
+           nlen += 256;
+           BINC_RETW(NULL, *tostr, *blen, nlen);
+       }
+       if (id != (iconv_t)-1 && j == len && left) {
+           CONVERT(str, left, src, len);
+           j = 0;
+       }
+    }
+    *tolen = i;
+
+    if (id != (iconv_t)-1)
+       iconv_close(id);
+
+    *dst = cw->bp1;
+
+    return 0;
+err:
+    *tolen = i;
+    if (id != (iconv_t)-1)
+       iconv_close(id);
+    *dst = cw->bp1;
+
+    return error;
+}
+
+static int 
+fe_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, 
+           size_t *tolen, const CHAR_T **dst)
+{
+    return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING));
+}
+
+static int 
+ie_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, 
+           size_t *tolen, const CHAR_T **dst)
+{
+    return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_INPUTENCODING));
+}
+
+static int 
+cs_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, 
+           size_t *tolen, const CHAR_T **dst)
+{
+    return default_char2int(sp, str, len, cw, tolen, dst, LANGCODESET);
+}
+
+static int 
+CHAR_T_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, 
+       size_t *tolen, const char **dst)
+{
+    *tolen = len * sizeof(CHAR_T);
+    *dst = (const char *)(const void *)str;
+
+    return 0;
+}
+
+static int 
+CHAR_T_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, 
+       size_t *tolen, const CHAR_T **dst)
+{
+    *tolen = len / sizeof(CHAR_T);
+    *dst = (const CHAR_T*) str;
+
+    return 0;
+}
+
+static int 
+int2raw(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, size_t *tolen,
+       const char **dst)
+{
+    int i;
+    char **tostr = (char **)(void *)&cw->bp1;
+    size_t  *blen = &cw->blen1;
+
+    BINC_RETC(NULL, *tostr, *blen, len);
+
+    *tolen = len;
+    for (i = 0; i < len; ++i)
+       (*tostr)[i] = str[i];
+
+    *dst = cw->bp1;
+
+    return 0;
+}
+
+static int 
+default_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, 
+               size_t *tolen, const char **pdst, const char *enc)
+{
+    size_t i, j;
+    int offset = 0;
+    char **tostr = (char **)(void *)&cw->bp1;
+    size_t  *blen = &cw->blen1;
+    mbstate_t mbs;
+    size_t n;
+    ssize_t  nlen = len + MB_CUR_MAX;
+    char *dst;
+    size_t buflen;
+    char       buffer[CONV_BUFFER_SIZE];
+    iconv_t    id = (iconv_t)-1;
+
+/* convert first len bytes of buffer and append it to cw->bp
+ * len is adjusted => 0
+ * offset contains the offset in cw->bp and is adjusted
+ * cw->bp is grown as required
+ */
+#ifdef USE_ICONV
+#define CONVERT2(len, cw, offset)                                      \
+    do {                                                               \
+       const char *bp = buffer;                                        \
+       while (len != 0) {                                              \
+           size_t outleft = cw->blen1 - offset;                        \
+           char *obp = (char *)cw->bp1 + offset;                       \
+           if (cw->blen1 < offset + MB_CUR_MAX) {                      \
+               nlen += 256;                                            \
+               BINC_RETC(NULL, cw->bp1, cw->blen1, nlen);              \
+           }                                                           \
+           errno = 0;                                                  \
+           if (iconv(id, &bp, &len, &obp, &outleft) == (size_t)-1 &&   \
+                   errno != E2BIG)                                     \
+               goto err;                                               \
+           offset = cw->blen1 - outleft;                               \
+       }                                                               \
+    } while (0)
+#else
+#define CONVERT2(len, cw, offset)
+#endif
+
+
+    MEMSET(&mbs, 0, 1);
+    BINC_RETC(NULL, *tostr, *blen, nlen);
+    dst = *tostr; buflen = *blen;
+
+#ifdef USE_ICONV
+    if (strcmp(nl_langinfo(CODESET), enc)) {
+       id = iconv_open(enc, nl_langinfo(CODESET));
+       if (id == (iconv_t)-1)
+           goto err;
+       dst = buffer; buflen = CONV_BUFFER_SIZE;
+    }
+#endif
+
+    for (i = 0, j = 0; i < (size_t)len; ++i) {
+       n = wcrtomb(dst+j, str[i], &mbs);
+       if (n == (size_t)-1) goto err;
+       j += n;
+       if (buflen < j + MB_CUR_MAX) {
+           if (id != (iconv_t)-1) {
+               CONVERT2(j, cw, offset);
+           } else {
+               nlen += 256;
+               BINC_RETC(NULL, *tostr, *blen, nlen);
+               dst = *tostr; buflen = *blen;
+           }
+       }
+    }
+
+    n = wcrtomb(dst+j, L'\0', &mbs);
+    j += n - 1;                                /* don't count NUL at the end */
+    *tolen = j;
+
+    if (id != (iconv_t)-1) {
+       CONVERT2(j, cw, offset);
+       *tolen = offset;
+    }
+
+    *pdst = cw->bp1;
+
+    return 0;
+err:
+    *tolen = j;
+
+    *pdst = cw->bp1;
+
+    return 1;
+}
+
+static int 
+fe_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, 
+           size_t *tolen, const char **dst)
+{
+    return default_int2char(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING));
+}
+
+static int 
+cs_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, 
+           size_t *tolen, const char **dst)
+{
+    return default_int2char(sp, str, len, cw, tolen, dst, LANGCODESET);
+}
+
+#endif
+
+
+void
+conv_init (SCR *orig, SCR *sp)
+{
+    if (orig != NULL)
+       MEMCPY(&sp->conv, &orig->conv, 1);
+    else {
+       setlocale(LC_ALL, "");
+#ifdef USE_WIDECHAR
+       sp->conv.sys2int = cs_char2int;
+       sp->conv.int2sys = cs_int2char;
+       sp->conv.file2int = fe_char2int;
+       sp->conv.int2file = fe_int2char;
+       sp->conv.input2int = ie_char2int;
+#endif
+#ifdef USE_ICONV
+       o_set(sp, O_FILEENCODING, OS_STRDUP, nl_langinfo(CODESET), 0);
+       o_set(sp, O_INPUTENCODING, OS_STRDUP, nl_langinfo(CODESET), 0);
+#endif
+    }
+}
+
+int
+conv_enc (SCR *sp, int option, const char *enc)
+{
+#if defined(USE_WIDECHAR) && defined(USE_ICONV)
+    iconv_t id;
+    char2wchar_t    *c2w;
+    wchar2char_t    *w2c;
+
+    switch (option) {
+    case O_FILEENCODING:
+       c2w = &sp->conv.file2int;
+       w2c = &sp->conv.int2file;
+       break;
+    case O_INPUTENCODING:
+       c2w = &sp->conv.input2int;
+       w2c = NULL;
+       break;
+    default:
+       c2w = NULL;
+       w2c = NULL;
+       break;
+    }
+
+    if (!*enc) {
+       if (c2w) *c2w = raw2int;
+       if (w2c) *w2c = int2raw;
+       return 0;
+    }
+
+    if (!strcmp(enc, "WCHAR_T")) {
+       if (c2w) *c2w = CHAR_T_char2int;
+       if (w2c) *w2c = CHAR_T_int2char;
+       return 0;
+    }
+
+    id = iconv_open(enc, nl_langinfo(CODESET));
+    if (id == (iconv_t)-1)
+       goto err;
+    iconv_close(id);
+    id = iconv_open(nl_langinfo(CODESET), enc);
+    if (id == (iconv_t)-1)
+       goto err;
+    iconv_close(id);
+
+    switch (option) {
+    case O_FILEENCODING:
+       *c2w = fe_char2int;
+       *w2c = fe_int2char;
+       break;
+    case O_INPUTENCODING:
+       *c2w = ie_char2int;
+       break;
+    }
+
+    F_CLR(sp, SC_CONV_ERROR);
+    F_SET(sp, SC_SCR_REFORMAT);
+
+    return 0;
+err:
+    switch (option) {
+    case O_FILEENCODING:
+       msgq(sp, M_ERR,
+           "321|File encoding conversion not supported");
+       break;
+    case O_INPUTENCODING:
+       msgq(sp, M_ERR,
+           "322|Input encoding conversion not supported");
+       break;
+    }
+#endif
+    return 1;
+}
+
diff --git a/dist/nvi/common/conv.h b/dist/nvi/common/conv.h
new file mode 100644 (file)
index 0000000..f655ac3
--- /dev/null
@@ -0,0 +1,28 @@
+/*     $NetBSD: conv.h,v 1.4 2009/04/19 02:28:19 tnozaki Exp $ */
+
+#define KEY_COL(sp, ch)                                                        \
+       (INTISWIDE(ch) ?                                                \
+           (CHAR_WIDTH(sp, ch) >= 0) ?                                 \
+              (size_t)CHAR_WIDTH(sp, ch) : 1 /* extra space */         \
+           : KEY_LEN(sp,ch))
+
+struct _conv_win {
+    void    *bp1;
+    size_t   blen1;
+};
+
+typedef int (*char2wchar_t) 
+    (SCR *, const char *, ssize_t, struct _conv_win *, size_t *, const CHAR_T **);
+typedef int (*wchar2char_t) 
+    (SCR *, const CHAR_T *, ssize_t, struct _conv_win *, size_t *, const char **);
+
+struct _conv {
+       char2wchar_t    sys2int;
+       wchar2char_t    int2sys;
+       char2wchar_t    file2int;
+       wchar2char_t    int2file;
+       char2wchar_t    input2int;
+       wchar2char_t    int2disp;
+};
+void conv_init __P((SCR *, SCR *));
+int conv_enc __P((SCR *, int, const char *));
diff --git a/dist/nvi/common/cut.c b/dist/nvi/common/cut.c
new file mode 100644 (file)
index 0000000..971087f
--- /dev/null
@@ -0,0 +1,354 @@
+/*     $NetBSD: cut.c,v 1.9 2012/01/27 16:41:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: cut.c,v 10.18 2001/06/25 15:19:09 skimo Exp (Berkeley) Date: 2001/06/25 15:19:09";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+static void    cb_rotate __P((SCR *));
+
+/*
+ * cut --
+ *     Put a range of lines/columns into a TEXT buffer.
+ *
+ * There are two buffer areas, both found in the global structure.  The first
+ * is the linked list of all the buffers the user has named, the second is the
+ * unnamed buffer storage.  There is a pointer, too, which is the current
+ * default buffer, i.e. it may point to the unnamed buffer or a named buffer
+ * depending on into what buffer the last text was cut.  Logically, in both
+ * delete and yank operations, if the user names a buffer, the text is cut
+ * into it.  If it's a delete of information on more than a single line, the
+ * contents of the numbered buffers are rotated up one, the contents of the
+ * buffer named '9' are discarded, and the text is cut into the buffer named
+ * '1'.  The text is always cut into the unnamed buffer.
+ *
+ * In all cases, upper-case buffer names are the same as lower-case names,
+ * with the exception that they cause the buffer to be appended to instead
+ * of replaced.  Note, however, that if text is appended to a buffer, the
+ * default buffer only contains the appended text, not the entire contents
+ * of the buffer.
+ *
+ * !!!
+ * The contents of the default buffer would disappear after most operations
+ * in historic vi.  It's unclear that this is useful, so we don't bother.
+ *
+ * When users explicitly cut text into the numeric buffers, historic vi became
+ * genuinely strange.  I've never been able to figure out what was supposed to
+ * happen.  It behaved differently if you deleted text than if you yanked text,
+ * and, in the latter case, the text was appended to the buffer instead of
+ * replacing the contents.  Hopefully it's not worth getting right, and here
+ * we just treat the numeric buffers like any other named buffer.
+ *
+ * PUBLIC: int cut __P((SCR *, ARG_CHAR_T *, MARK *, MARK *, int));
+ */
+int
+cut(SCR *sp, ARG_CHAR_T *namep, MARK *fm, MARK *tm, int flags)
+{
+       CB *cbp;
+       ARG_CHAR_T name = '\0';
+       db_recno_t lno;
+       int append, copy_one, copy_def;
+
+       /*
+        * If the user specified a buffer, put it there.  (This may require
+        * a copy into the numeric buffers.  We do the copy so that we don't
+        * have to reference count and so we don't have to deal with things
+        * like appends to buffers that are used multiple times.)
+        *
+        * Otherwise, if it's supposed to be put in a numeric buffer (usually
+        * a delete) put it there.  The rules for putting things in numeric
+        * buffers were historically a little strange.  There were three cases.
+        *
+        *      1: Some motions are always line mode motions, which means
+        *         that the cut always goes into the numeric buffers.
+        *      2: Some motions aren't line mode motions, e.g. d10w, but
+        *         can cross line boundaries.  For these commands, if the
+        *         cut crosses a line boundary, it goes into the numeric
+        *         buffers.  This includes most of the commands.
+        *      3: Some motions aren't line mode motions, e.g. d`<char>,
+        *         but always go into the numeric buffers, regardless.  This
+        *         was the commands: % ` / ? ( ) N n { } -- and nvi adds ^A.
+        *
+        * Otherwise, put it in the unnamed buffer.
+        */
+       append = copy_one = copy_def = 0;
+       if (namep != NULL) {
+               name = *namep;
+               if (LF_ISSET(CUT_NUMREQ) || (LF_ISSET(CUT_NUMOPT) &&
+                   (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno))) {
+                       copy_one = 1;
+                       cb_rotate(sp);
+               }
+               if ((append = ISUPPER(name)) == 1) {
+                       if (!copy_one)
+                               copy_def = 1;
+                       name = TOLOWER(name);
+               }
+namecb:                CBNAME(sp, cbp, name);
+       } else if (LF_ISSET(CUT_NUMREQ) || (LF_ISSET(CUT_NUMOPT) &&
+           (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno))) {
+               name = '1';
+               cb_rotate(sp);
+               goto namecb;
+       } else
+               cbp = &sp->wp->dcb_store;
+
+copyloop:
+       /*
+        * If this is a new buffer, create it and add it into the list.
+        * Otherwise, if it's not an append, free its current contents.
+        */
+       if (cbp == NULL) {
+               CALLOC_RET(sp, cbp, CB *, 1, sizeof(CB));
+               cbp->name = name;
+               CIRCLEQ_INIT(&cbp->textq);
+               LIST_INSERT_HEAD(&sp->wp->cutq, cbp, q);
+       } else if (!append) {
+               text_lfree(&cbp->textq);
+               cbp->len = 0;
+               cbp->flags = 0;
+       }
+
+
+       /* In line mode, it's pretty easy, just cut the lines. */
+       if (LF_ISSET(CUT_LINEMODE)) {
+               cbp->flags |= CB_LMODE;
+               for (lno = fm->lno; lno <= tm->lno; ++lno)
+                       if (cut_line(sp, lno, 0, ENTIRE_LINE, cbp))
+                               goto cut_line_err;
+       } else {
+               /*
+                * Get the first line.  A length of ENTIRE_LINE causes cut_line
+                * to cut from the MARK to the end of the line.
+                */
+               if (cut_line(sp, fm->lno, fm->cno, fm->lno != tm->lno ?
+                   ENTIRE_LINE : (tm->cno - fm->cno) + 1, cbp))
+                       goto cut_line_err;
+
+               /* Get the intermediate lines. */
+               for (lno = fm->lno; ++lno < tm->lno;)
+                       if (cut_line(sp, lno, 0, ENTIRE_LINE, cbp))
+                               goto cut_line_err;
+
+               /* Get the last line. */
+               if (tm->lno != fm->lno &&
+                   cut_line(sp, lno, 0, tm->cno + 1, cbp))
+                       goto cut_line_err;
+       }
+
+       append = 0;             /* Only append to the named buffer. */
+       sp->wp->dcbp = cbp;     /* Repoint the default buffer on each pass. */
+
+       if (copy_one) {         /* Copy into numeric buffer 1. */
+               name = '1';
+               CBNAME(sp, cbp, name);
+               copy_one = 0;
+               goto copyloop;
+       }
+       if (copy_def) {         /* Copy into the default buffer. */
+               cbp = &sp->wp->dcb_store;
+               copy_def = 0;
+               goto copyloop;
+       }
+       return (0);
+
+cut_line_err:  
+       text_lfree(&cbp->textq);
+       cbp->len = 0;
+       cbp->flags = 0;
+       return (1);
+}
+
+/*
+ * cb_rotate --
+ *     Rotate the numbered buffers up one.
+ */
+static void
+cb_rotate(SCR *sp)
+{
+       CB *cbp, *del_cbp;
+
+       del_cbp = NULL;
+       for (cbp = sp->wp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next)
+               switch(cbp->name) {
+               case '1':
+                       cbp->name = '2';
+                       break;
+               case '2':
+                       cbp->name = '3';
+                       break;
+               case '3':
+                       cbp->name = '4';
+                       break;
+               case '4':
+                       cbp->name = '5';
+                       break;
+               case '5':
+                       cbp->name = '6';
+                       break;
+               case '6':
+                       cbp->name = '7';
+                       break;
+               case '7':
+                       cbp->name = '8';
+                       break;
+               case '8':
+                       cbp->name = '9';
+                       break;
+               case '9':
+                       del_cbp = cbp;
+                       break;
+               }
+       if (del_cbp != NULL) {
+               LIST_REMOVE(del_cbp, q);
+               text_lfree(&del_cbp->textq);
+               free(del_cbp);
+       }
+}
+
+/*
+ * cut_line --
+ *     Cut a portion of a single line.
+ *
+ * PUBLIC: int cut_line __P((SCR *, db_recno_t, size_t, size_t, CB *));
+ */
+int
+cut_line(SCR *sp, db_recno_t lno, size_t fcno, size_t clen, CB *cbp)
+{
+       TEXT *tp;
+       size_t len;
+       CHAR_T *p;
+
+       /* Get the line. */
+       if (db_get(sp, lno, DBG_FATAL, &p, &len))
+               return (1);
+
+       /* Create a TEXT structure that can hold the entire line. */
+       if ((tp = text_init(sp, NULL, 0, len)) == NULL)
+               return (1);
+
+       /*
+        * If the line isn't empty and it's not the entire line,
+        * copy the portion we want, and reset the TEXT length.
+        */
+       if (len != 0) {
+               if (clen == ENTIRE_LINE)
+                       clen = len - fcno;
+               MEMCPYW(tp->lb, p + fcno, clen);
+               tp->len = clen;
+       }
+
+       /* Append to the end of the cut buffer. */
+       CIRCLEQ_INSERT_TAIL(&cbp->textq, tp, q);
+       cbp->len += tp->len;
+
+       return (0);
+}
+
+/*
+ * cut_close --
+ *     Discard all cut buffers.
+ *
+ * PUBLIC: void cut_close __P((WIN *));
+ */
+void
+cut_close(WIN *wp)
+{
+       CB *cbp;
+
+       /* Free cut buffer list. */
+       while ((cbp = wp->cutq.lh_first) != NULL) {
+               if (cbp->textq.cqh_first != (void *)&cbp->textq)
+                       text_lfree(&cbp->textq);
+               LIST_REMOVE(cbp, q);
+               free(cbp);
+       }
+
+       /* Free default cut storage. */
+       cbp = &wp->dcb_store;
+       if (cbp->textq.cqh_first != (void *)&cbp->textq)
+               text_lfree(&cbp->textq);
+}
+
+/*
+ * text_init --
+ *     Allocate a new TEXT structure.
+ *
+ * PUBLIC: TEXT *text_init __P((SCR *, const CHAR_T *, size_t, size_t));
+ */
+TEXT *
+text_init(SCR *sp, const CHAR_T *p, size_t len, size_t total_len)
+{
+       TEXT *tp;
+
+       CALLOC(sp, tp, TEXT *, 1, sizeof(TEXT));
+       if (tp == NULL)
+               return (NULL);
+       /* ANSI C doesn't define a call to malloc(3) for 0 bytes. */
+       if ((tp->lb_len = total_len * sizeof(CHAR_T)) != 0) {
+               MALLOC(sp, tp->lb, CHAR_T *, tp->lb_len * sizeof(CHAR_T));
+               if (tp->lb == NULL) {
+                       free(tp);
+                       return (NULL);
+               }
+               if (p != NULL && len != 0)
+                       MEMCPYW(tp->lb, p, len);
+       }
+       tp->len = len;
+       return (tp);
+}
+
+/*
+ * text_lfree --
+ *     Free a chain of text structures.
+ *
+ * PUBLIC: void text_lfree __P((TEXTH *));
+ */
+void
+text_lfree(TEXTH *headp)
+{
+       TEXT *tp;
+
+       while ((tp = headp->cqh_first) != (void *)headp) {
+               CIRCLEQ_REMOVE(headp, tp, q);
+               text_free(tp);
+       }
+}
+
+/*
+ * text_free --
+ *     Free a text structure.
+ *
+ * PUBLIC: void text_free __P((TEXT *));
+ */
+void
+text_free(TEXT *tp)
+{
+       if (tp->lb != NULL)
+               free(tp->lb);
+       free(tp);
+}
diff --git a/dist/nvi/common/cut.h b/dist/nvi/common/cut.h
new file mode 100644 (file)
index 0000000..e4bcf6d
--- /dev/null
@@ -0,0 +1,81 @@
+/*     $NetBSD: cut.h,v 1.4 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: cut.h,v 10.9 2000/07/22 17:31:18 skimo Exp (Berkeley) Date: 2000/07/22 17:31:18
+ */
+
+typedef struct _texth TEXTH;           /* TEXT list head structure. */
+CIRCLEQ_HEAD(_texth, _text);
+
+/* Cut buffers. */
+struct _cb {
+       LIST_ENTRY(_cb) q;              /* Linked list of cut buffers. */
+       TEXTH    textq;                 /* Linked list of TEXT structures. */
+       /* XXXX Needed ? Can non ascii-chars be cut buffer names ? */
+       ARG_CHAR_T name;                /* Cut buffer name. */
+       size_t   len;                   /* Total length of cut text. */
+
+#define        CB_LMODE        0x01            /* Cut was in line mode. */
+       u_int8_t flags;
+};
+
+/* Lines/blocks of text. */
+struct _text {                         /* Text: a linked list of lines. */
+       CIRCLEQ_ENTRY(_text) q;         /* Linked list of text structures. */
+       CHAR_T  *lb;                    /* Line buffer. */
+       size_t   lb_len;                /* Line buffer length. */
+       size_t   len;                   /* Line length. */
+
+       /* These fields are used by the vi text input routine. */
+       db_recno_t       lno;                   /* 1-N: file line. */
+       size_t   cno;                   /* 0-N: file character in line. */
+       size_t   ai;                    /* 0-N: autoindent bytes. */
+       size_t   insert;                /* 0-N: bytes to insert (push). */
+       size_t   offset;                /* 0-N: initial, unerasable chars. */
+       size_t   owrite;                /* 0-N: chars to overwrite. */
+       size_t   R_erase;               /* 0-N: 'R' erase count. */
+       size_t   sv_cno;                /* 0-N: Saved line cursor. */
+       size_t   sv_len;                /* 0-N: Saved line length. */
+
+       /*
+        * These fields returns information from the vi text input routine.
+        *
+        * The termination condition.  Note, this field is only valid if the
+        * text input routine returns success.
+        *      TERM_BS:        User backspaced over the prompt.
+        *      TERM_CEDIT:     User entered <edit-char>.
+        *      TERM_CR:        User entered <carriage-return>; no data.
+        *      TERM_ESC:       User entered <escape>; no data.
+        *      TERM_OK:        Data available.
+        *      TERM_SEARCH:    Incremental search.
+        */
+       enum {
+           TERM_BS, TERM_CEDIT, TERM_CR, TERM_ESC, TERM_OK, TERM_SEARCH
+       } term;
+};
+
+/*
+ * Get named buffer 'name'.
+ * Translate upper-case buffer names to lower-case buffer names.
+ */
+#define        CBNAME(sp, cbp, nch) {                                          \
+       ARG_CHAR_T L__name;                                             \
+       L__name = ISUPPER(nch) ?                                        \
+           TOLOWER(nch) : (nch);                                       \
+       for (cbp = sp->wp->cutq.lh_first;                               \
+           cbp != NULL; cbp = cbp->q.le_next)                          \
+               if (cbp->name == L__name)                               \
+                       break;                                          \
+}
+
+/* Flags to the cut() routine. */
+#define        CUT_LINEMODE    0x01            /* Cut in line mode. */
+#define        CUT_NUMOPT      0x02            /* Numeric buffer: optional. */
+#define        CUT_NUMREQ      0x04            /* Numeric buffer: required. */
diff --git a/dist/nvi/common/db.c b/dist/nvi/common/db.c
new file mode 100644 (file)
index 0000000..f5f9c00
--- /dev/null
@@ -0,0 +1,690 @@
+/*     $NetBSD: db.c,v 1.3 2008/12/09 16:50:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: db.c,v 10.48 2002/06/08 19:32:52 skimo Exp (Berkeley) Date: 2002/06/08 19:32:52";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+
+static int append __P((SCR*, db_recno_t, const CHAR_T*, size_t, lnop_t, int));
+
+/*
+ * db_eget --
+ *     Front-end to db_get, special case handling for empty files.
+ *
+ * PUBLIC: int db_eget __P((SCR *, db_recno_t, CHAR_T **, size_t *, int *));
+ */
+int
+db_eget(SCR *sp, db_recno_t lno, CHAR_T **pp, size_t *lenp, int *isemptyp)
+               
+                                               /* Line number. */
+                                               /* Pointer store. */
+                                               /* Length store. */
+                     
+{
+       db_recno_t l1;
+
+       if (isemptyp != NULL)
+               *isemptyp = 0;
+
+       /* If the line exists, simply return it. */
+       if (!db_get(sp, lno, 0, pp, lenp))
+               return (0);
+
+       /*
+        * If the user asked for line 0 or line 1, i.e. the only possible
+        * line in an empty file, find the last line of the file; db_last
+        * fails loudly.
+        */
+       if ((lno == 0 || lno == 1) && db_last(sp, &l1))
+               return (1);
+
+       /* If the file isn't empty, fail loudly. */
+       if ((lno != 0 && lno != 1) || l1 != 0) {
+               db_err(sp, lno);
+               return (1);
+       }
+
+       if (isemptyp != NULL)
+               *isemptyp = 1;
+
+       return (1);
+}
+
+/*
+ * db_get --
+ *     Look in the text buffers for a line, followed by the cache, followed
+ *     by the database.
+ *
+ * PUBLIC: int db_get __P((SCR *, db_recno_t, u_int32_t, CHAR_T **, size_t *));
+ */
+int
+db_get(SCR *sp, db_recno_t lno, u_int32_t flags, CHAR_T **pp, size_t *lenp)
+               /* Line number. */ /* Pointer store. */ /* Length store. */
+{
+       DBT data, key;
+       EXF *ep;
+       TEXT *tp;
+       db_recno_t l1, l2;
+       const CHAR_T *wp;
+       size_t wlen;
+       size_t nlen;
+
+       /*
+        * The underlying recno stuff handles zero by returning NULL, but
+        * have to have an OOB condition for the look-aside into the input
+        * buffer anyway.
+        */
+       if (lno == 0)
+               goto err1;
+
+       /* Check for no underlying file. */
+       if ((ep = sp->ep) == NULL) {
+               ex_emsg(sp, NULL, EXM_NOFILEYET);
+               goto err3;
+       }
+
+       if (LF_ISSET(DBG_NOCACHE))
+               goto nocache;
+
+       /*
+        * Look-aside into the TEXT buffers and see if the line we want
+        * is there.
+        */
+       if (F_ISSET(sp, SC_TINPUT)) {
+               l1 = ((TEXT *)sp->tiq.cqh_first)->lno;
+               l2 = ((TEXT *)sp->tiq.cqh_last)->lno;
+               if (l1 <= lno && l2 >= lno) {
+#if defined(DEBUG) && 0
+                       vtrace(sp,
+                           "retrieve TEXT buffer line %lu\n", (u_long)lno);
+#endif
+                       for (tp = sp->tiq.cqh_first;
+                           tp->lno != lno; tp = tp->q.cqe_next);
+                       if (lenp != NULL)
+                               *lenp = tp->len;
+                       if (pp != NULL)
+                               *pp = tp->lb;
+                       return (0);
+               }
+               /*
+                * Adjust the line number for the number of lines used
+                * by the text input buffers.
+                */
+               if (lno > l2)
+                       lno -= l2 - l1;
+       }
+
+       /* Look-aside into the cache, and see if the line we want is there. */
+       if (lno == sp->c_lno) {
+#if defined(DEBUG) && 0
+               vtrace(sp, "retrieve cached line %lu\n", (u_long)lno);
+#endif
+               if (lenp != NULL)
+                       *lenp = sp->c_len;
+               if (pp != NULL)
+                       *pp = sp->c_lp;
+               return (0);
+       }
+       sp->c_lno = OOBLNO;
+
+nocache:
+       nlen = 1024;
+retry:
+       /* data.size contains length in bytes */
+       BINC_GOTO(sp, CHAR_T, sp->c_lp, sp->c_blen, nlen);
+
+       /* Get the line from the underlying database. */
+       memset(&key, 0, sizeof(key));
+       key.data = &lno;
+       key.size = sizeof(lno);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->c_lp;
+       data.ulen = sp->c_blen;
+       data.flags = DB_DBT_USERMEM;
+       switch (ep->db->get(ep->db, NULL, &key, &data, 0)) {
+       case DB_BUFFER_SMALL:
+               nlen = data.size;
+               goto retry;
+        default:
+               goto err2;
+       case DB_NOTFOUND:
+err1:          if (LF_ISSET(DBG_FATAL))
+err2:                  db_err(sp, lno);
+alloc_err:
+err3:          if (lenp != NULL)
+                       *lenp = 0;
+               if (pp != NULL)
+                       *pp = NULL;
+               return (1);
+       case 0:
+               ;
+       }
+
+       if (FILE2INT(sp, data.data, data.size, wp, wlen)) {
+           if (!F_ISSET(sp, SC_CONV_ERROR)) {
+               F_SET(sp, SC_CONV_ERROR);
+               msgq(sp, M_ERR, "324|Conversion error on line %d", lno);
+           }
+           goto err3;
+       }
+
+       /* Reset the cache. */
+       if (wp != data.data) {
+           BINC_GOTOW(sp, sp->c_lp, sp->c_blen, wlen);
+           MEMCPYW(sp->c_lp, wp, wlen);
+       }
+       sp->c_lno = lno;
+       sp->c_len = wlen;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "retrieve DB line %lu\n", (u_long)lno);
+#endif
+       if (lenp != NULL)
+               *lenp = wlen;
+       if (pp != NULL)
+               *pp = sp->c_lp;
+       return (0);
+}
+
+/*
+ * db_delete --
+ *     Delete a line from the file.
+ *
+ * PUBLIC: int db_delete __P((SCR *, db_recno_t));
+ */
+int
+db_delete(SCR *sp, db_recno_t lno)
+{
+       DBT key;
+       EXF *ep;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "delete line %lu\n", (u_long)lno);
+#endif
+       /* Check for no underlying file. */
+       if ((ep = sp->ep) == NULL) {
+               ex_emsg(sp, NULL, EXM_NOFILEYET);
+               return (1);
+       }
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+               
+       /* Update marks, @ and global commands. */
+       if (line_insdel(sp, LINE_DELETE, lno))
+               return 1;
+
+       /* Log before change. */
+       log_line(sp, lno, LOG_LINE_DELETE_B);
+
+       /* Update file. */
+       memset(&key, 0, sizeof(key));
+       key.data = &lno;
+       key.size = sizeof(lno);
+       if ((sp->db_error = ep->db->del(ep->db, NULL, &key, 0)) != 0) {
+               msgq(sp, M_DBERR, "003|unable to delete line %lu", 
+                   (u_long)lno);
+               return (1);
+       }
+
+       /* Flush the cache, update line count, before screen update. */
+       update_cache(sp, LINE_DELETE, lno);
+
+       /* File now modified. */
+       if (F_ISSET(ep, F_FIRSTMODIFY))
+               (void)rcv_init(sp);
+       F_SET(ep, F_MODIFIED);
+
+       /* Log after change. */
+       log_line(sp, lno, LOG_LINE_DELETE_F);
+
+       /* Update screen. */
+       return (scr_update(sp, lno, LINE_DELETE, 1));
+}
+
+/* maybe this could be simpler
+ *
+ * DB3 behaves differently from DB1
+ *
+ * if lno != 0 just go to lno and put the new line after it
+ * if lno == 0 then if there are any record, put in front of the first
+ *                 otherwise just append to the end thus creating the first
+ *                             line
+ */
+static int
+append(SCR *sp, db_recno_t lno, const CHAR_T *p, size_t len, lnop_t op, int update)
+{
+       DBT data, key;
+       DBC *dbcp_put;
+       EXF *ep;
+       const char *fp;
+       size_t flen;
+       int rval;
+
+       /* Check for no underlying file. */
+       if ((ep = sp->ep) == NULL) {
+               ex_emsg(sp, NULL, EXM_NOFILEYET);
+               return (1);
+       }
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+
+       /* Log before change. */
+       log_line(sp, lno + 1, LOG_LINE_APPEND_B);
+
+       /* Update file. */
+       memset(&key, 0, sizeof(key));
+       key.data = &lno;
+       key.size = sizeof(lno);
+       memset(&data, 0, sizeof(data));
+
+       if ((sp->db_error = ep->db->cursor(ep->db, NULL, &dbcp_put, 0)) != 0)
+           return 1;
+
+       INT2FILE(sp, p, len, fp, flen);
+
+       if (lno != 0) {
+           if ((sp->db_error = dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) 
+               goto err2;
+
+           data.data = __UNCONST(fp);
+           data.size = flen;
+           if ((sp->db_error = dbcp_put->c_put(dbcp_put, &key, &data, DB_AFTER)) != 0) {
+err2:
+               (void)dbcp_put->c_close(dbcp_put);
+               msgq(sp, M_DBERR, 
+                       (op == LINE_APPEND) 
+                           ? "004|unable to append to line %lu" 
+                           : "005|unable to insert at line %lu", 
+                       (u_long)lno);
+               return (1);
+           }
+       } else {
+           if ((sp->db_error = dbcp_put->c_get(dbcp_put, &key, &data, DB_FIRST)) != 0) {
+               if (sp->db_error != DB_NOTFOUND)
+                   goto err2;
+
+               data.data = __UNCONST(fp);
+               data.size = flen;
+               if ((sp->db_error = ep->db->put(ep->db, NULL, &key, &data, DB_APPEND)) != 0) {
+                   goto err2;
+               }
+           } else {
+               key.data = &lno;
+               key.size = sizeof(lno);
+               data.data = __UNCONST(fp);
+               data.size = flen;
+               if ((sp->db_error = dbcp_put->c_put(dbcp_put, &key, &data, DB_BEFORE)) != 0) {
+                   goto err2;
+               }
+           }
+       }
+
+       (void)dbcp_put->c_close(dbcp_put);
+
+       /* Flush the cache, update line count, before screen update. */
+       update_cache(sp, LINE_INSERT, lno);
+
+       /* File now dirty. */
+       if (F_ISSET(ep, F_FIRSTMODIFY))
+               (void)rcv_init(sp);
+       F_SET(ep, F_MODIFIED);
+
+       /* Log after change. */
+       log_line(sp, lno + 1, LOG_LINE_APPEND_F);
+
+       /* Update marks, @ and global commands. */
+       rval = line_insdel(sp, LINE_INSERT, lno + 1);
+
+       /*
+        * Update screen.
+        *
+        * comment copied from db_append
+        * XXX
+        * Nasty hack.  If multiple lines are input by the user, they aren't
+        * committed until an <ESC> is entered.  The problem is the screen was
+        * updated/scrolled as each line was entered.  So, when this routine
+        * is called to copy the new lines from the cut buffer into the file,
+        * it has to know not to update the screen again.
+        */
+       return (scr_update(sp, lno + 1, LINE_INSERT, update) || rval);
+}
+
+/*
+ * db_append --
+ *     Append a line into the file.
+ *
+ * PUBLIC: int db_append __P((SCR *, int, db_recno_t, CHAR_T *, size_t));
+ */
+int
+db_append(SCR *sp, int update, db_recno_t lno, const CHAR_T *p, size_t len)
+{
+#if defined(DEBUG) && 0
+       vtrace(sp, "append to %lu: len %u {%.*s}\n", lno, len, MIN(len, 20), p);
+#endif
+               
+       /* Update file. */
+       return append(sp, lno, p, len, LINE_APPEND, update);
+}
+
+/*
+ * db_insert --
+ *     Insert a line into the file.
+ *
+ * PUBLIC: int db_insert __P((SCR *, db_recno_t, CHAR_T *, size_t));
+ */
+int
+db_insert(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len)
+{
+#if defined(DEBUG) && 0
+       vtrace(sp, "insert before %lu: len %lu {%.*s}\n",
+           (u_long)lno, (u_long)len, MIN(len, 20), p);
+#endif
+       return append(sp, lno - 1, p, len, LINE_INSERT, 1);
+}
+
+/*
+ * db_set --
+ *     Store a line in the file.
+ *
+ * PUBLIC: int db_set __P((SCR *, db_recno_t, CHAR_T *, size_t));
+ */
+int
+db_set(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len)
+{
+       DBT data, key;
+       EXF *ep;
+       const char *fp;
+       size_t flen;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "replace line %lu: len %lu {%.*s}\n",
+           (u_long)lno, (u_long)len, MIN(len, 20), p);
+#endif
+       /* Check for no underlying file. */
+       if ((ep = sp->ep) == NULL) {
+               ex_emsg(sp, NULL, EXM_NOFILEYET);
+               return (1);
+       }
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+               
+       /* Log before change. */
+       log_line(sp, lno, LOG_LINE_RESET_B);
+
+       INT2FILE(sp, p, len, fp, flen);
+
+       /* Update file. */
+       memset(&key, 0, sizeof(key));
+       key.data = &lno;
+       key.size = sizeof(lno);
+       memset(&data, 0, sizeof(data));
+       data.data = __UNCONST(fp);
+       data.size = flen;
+       if ((sp->db_error = ep->db->put(ep->db, NULL, &key, &data, 0)) != 0) {
+               msgq(sp, M_DBERR, "006|unable to store line %lu", (u_long)lno);
+               return (1);
+       }
+
+       /* Flush the cache, update line count, before screen update. */
+       update_cache(sp, LINE_RESET, lno);
+
+       /* File now dirty. */
+       if (F_ISSET(ep, F_FIRSTMODIFY))
+               (void)rcv_init(sp);
+       F_SET(ep, F_MODIFIED);
+
+       /* Log after change. */
+       log_line(sp, lno, LOG_LINE_RESET_F);
+
+       /* Update screen. */
+       return (scr_update(sp, lno, LINE_RESET, 1));
+}
+
+/*
+ * db_exist --
+ *     Return if a line exists.
+ *
+ * PUBLIC: int db_exist __P((SCR *, db_recno_t));
+ */
+int
+db_exist(SCR *sp, db_recno_t lno)
+{
+       EXF *ep;
+
+       /* Check for no underlying file. */
+       if ((ep = sp->ep) == NULL) {
+               ex_emsg(sp, NULL, EXM_NOFILEYET);
+               return (1);
+       }
+
+       if (lno == OOBLNO)
+               return (0);
+               
+       /*
+        * Check the last-line number cache.  Adjust the cached line
+        * number for the lines used by the text input buffers.
+        */
+       if (ep->c_nlines != OOBLNO)
+               return (lno <= (F_ISSET(sp, SC_TINPUT) ?
+                   ep->c_nlines + (((TEXT *)sp->tiq.cqh_last)->lno -
+                   ((TEXT *)sp->tiq.cqh_first)->lno) : ep->c_nlines));
+
+       /* Go get the line. */
+       return (!db_get(sp, lno, 0, NULL, NULL));
+}
+
+/*
+ * db_last --
+ *     Return the number of lines in the file.
+ *
+ * PUBLIC: int db_last __P((SCR *, db_recno_t *));
+ */
+int
+db_last(SCR *sp, db_recno_t *lnop)
+{
+       DBT data, key;
+       DBC *dbcp;
+       EXF *ep;
+       db_recno_t lno;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /* Check for no underlying file. */
+       if ((ep = sp->ep) == NULL) {
+               ex_emsg(sp, NULL, EXM_NOFILEYET);
+               return (1);
+       }
+               
+       /*
+        * Check the last-line number cache.  Adjust the cached line
+        * number for the lines used by the text input buffers.
+        */
+       if (ep->c_nlines != OOBLNO) {
+               *lnop = ep->c_nlines;
+               if (F_ISSET(sp, SC_TINPUT))
+                       *lnop += ((TEXT *)sp->tiq.cqh_last)->lno -
+                           ((TEXT *)sp->tiq.cqh_first)->lno;
+               return (0);
+       }
+
+       memset(&key, 0, sizeof(key));
+       key.data = &lno;
+       key.size = sizeof(lno);
+       memset(&data, 0, sizeof(data));
+
+       if ((sp->db_error = ep->db->cursor(ep->db, NULL, &dbcp, 0)) != 0)
+           goto err1;
+       switch (sp->db_error = dbcp->c_get(dbcp, &key, &data, DB_LAST)) {
+        case DB_NOTFOUND:
+               *lnop = 0;
+               return (0);
+       default:
+               (void)dbcp->c_close(dbcp);
+alloc_err:
+err1:
+               msgq(sp, M_DBERR, "007|unable to get last line");
+               *lnop = 0;
+               return (1);
+        case 0:
+               ;
+       }
+
+       memcpy(&lno, key.data, sizeof(lno));
+
+       if (lno != sp->c_lno) {
+           FILE2INT(sp, data.data, data.size, wp, wlen);
+
+           /* Fill the cache. */
+           BINC_GOTOW(sp, sp->c_lp, sp->c_blen, wlen);
+           MEMCPYW(sp->c_lp, wp, wlen);
+           sp->c_lno = lno;
+           sp->c_len = wlen;
+       }
+       ep->c_nlines = lno;
+
+       (void)dbcp->c_close(dbcp);
+
+       /* Return the value. */
+       *lnop = (F_ISSET(sp, SC_TINPUT) &&
+           ((TEXT *)sp->tiq.cqh_last)->lno > lno ?
+           ((TEXT *)sp->tiq.cqh_last)->lno : lno);
+       return (0);
+}
+
+/*
+ * db_err --
+ *     Report a line error.
+ *
+ * PUBLIC: void db_err __P((SCR *, db_recno_t));
+ */
+void
+db_err(SCR *sp, db_recno_t lno)
+{
+       msgq(sp, M_ERR,
+           "008|Error: unable to retrieve line %lu", (u_long)lno);
+}
+
+/*
+ * scr_update --
+ *     Update all of the screens that are backed by the file that
+ *     just changed.
+ *
+ * PUBLIC: int scr_update __P((SCR *sp, db_recno_t lno, 
+ * PUBLIC:                     lnop_t op, int current));
+ */
+int
+scr_update(SCR *sp, db_recno_t lno, lnop_t op, int current)
+{
+       EXF *ep;
+       SCR *tsp;
+       WIN *wp;
+
+       if (F_ISSET(sp, SC_EX))
+               return (0);
+
+       /* XXXX goes outside of window */
+       ep = sp->ep;
+       if (ep->refcnt != 1)
+               for (wp = sp->gp->dq.cqh_first; wp != (void *)&sp->gp->dq; 
+                   wp = wp->q.cqe_next)
+                       for (tsp = wp->scrq.cqh_first;
+                           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
+                       if (sp != tsp && tsp->ep == ep)
+                               if (vs_change(tsp, lno, op))
+                                       return (1);
+       return (current ? vs_change(sp, lno, op) : 0);
+}
+
+/*
+ * PUBLIC: void update_cache __P((SCR *sp, lnop_t op, db_recno_t lno));
+ */
+void
+update_cache(SCR *sp, lnop_t op, db_recno_t lno)
+{
+       SCR* scrp;
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /* Flush the cache, update line count, before screen update. */
+       /* The flushing is probably not needed, since it was incorrect
+        * for db_insert.  It might be better to adjust it, like
+        * marks, @ and global
+        */
+       for (scrp = ep->scrq.cqh_first; scrp != (void *)&ep->scrq; 
+           scrp = scrp->eq.cqe_next)
+               switch (op) {
+               case LINE_INSERT:
+               case LINE_DELETE:
+                       if (lno <= scrp->c_lno)
+                               scrp->c_lno = OOBLNO;
+                       break;
+               case LINE_RESET:
+                       if (lno == scrp->c_lno)
+                               scrp->c_lno = OOBLNO;
+               /*FALLTHROUGH*/
+               case LINE_APPEND:
+                       break;
+               }
+
+       if (ep->c_nlines != OOBLNO)
+               switch (op) {
+               case LINE_INSERT:
+                       ++ep->c_nlines;
+                       break;
+               case LINE_DELETE:
+                       --ep->c_nlines;
+               /*FALLTHROUGH*/
+               case LINE_APPEND:
+               case LINE_RESET:
+                       break;
+               }
+}
+
+/*
+ * PUBLIC: int line_insdel __P((SCR *sp, lnop_t op, db_recno_t lno));
+ */
+int
+line_insdel(SCR *sp, lnop_t op, db_recno_t lno)
+{
+       int rval;
+
+       /* Update marks, @ and global commands. */
+       rval = 0;
+       if (mark_insdel(sp, op, lno))
+               rval = 1;
+       if (ex_g_insdel(sp, op, lno))
+               rval = 1;
+
+       return rval;
+}
diff --git a/dist/nvi/common/db.h b/dist/nvi/common/db.h
new file mode 100644 (file)
index 0000000..d3bef8e
--- /dev/null
@@ -0,0 +1,146 @@
+/*     $NetBSD: db.h,v 1.3 2008/08/05 15:49:18 aymeric Exp $ */
+
+#include <db.h>
+
+#ifndef DB_BUFFER_SMALL
+#define DB_BUFFER_SMALL                ENOMEM
+#endif
+
+#if USE_DB1 || (DB_VERSION_MAJOR >= 3 && DB_VERSION_MINOR >= 1)
+#define db_env_open(env,path,flags,mode)                               \
+    (env)->open(env, path, flags, mode)
+#define db_env_remove(env,path,flags)                                  \
+    (env)->remove(env, path, flags)
+#else
+#define db_env_open(env,path,flags,mode)                               \
+    (env)->open(env, path, NULL, flags, mode)
+#define db_env_remove(env,path,flags)                                  \
+    (env)->remove(env, path, NULL, flags)
+#endif
+
+#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
+#define db_open(db,file,type,flags,mode)                               \
+    (db)->open(db, NULL, file, NULL, type, flags, mode)
+#else
+#define db_open(db,file,type,flags,mode)                               \
+    (db)->open(db, file, NULL, type, flags, mode)
+#endif
+
+#ifdef USE_DYNAMIC_LOADING
+#define db_create      nvi_db_create
+#define db_env_create   nvi_db_env_create
+#define db_strerror    nvi_db_strerror
+
+extern int   (*nvi_db_create) __P((DB **, DB_ENV *, u_int32_t));
+extern int   (*nvi_db_env_create) __P((DB_ENV **, u_int32_t));
+extern char *(*nvi_db_strerror) __P((int));
+#endif
+
+#ifdef USE_DB1
+
+#define DB_AFTER       1
+#define DB_APPEND      2
+#define DB_BEFORE      3
+#define DB_FIRST       7
+#define DB_LAST                15
+#define DB_SET         25
+
+#define DB_NOTFOUND (-30989)
+
+/* DBT emulation */
+typedef DBT DBT_v1;
+#undef DBT
+#define DBT DBT_new
+
+typedef struct {
+       void *data;
+       size_t size;
+
+       u_int32_t ulen;
+
+#define DB_DBT_USERMEM 0x040
+       u_int32_t flags;
+} DBT;
+
+/* DB_ENV emulation */
+struct __db_env_new;
+typedef struct __db_env_new DB_ENV;
+
+struct __db_env_new {
+       int (*close)(DB_ENV *, u_int32_t);
+       int (*open)(DB_ENV *, char *, u_int32_t, int);
+#define DB_INIT_MPOOL  0x004000
+#define DB_PRIVATE     0x200000
+       int (*remove)(DB_ENV *, char *, u_int32_t);
+
+       char *base_path;
+       int mode;
+};
+
+/* DBC emulation */
+
+struct __dbc_new;
+typedef struct __dbc_new DBC;
+
+typedef recno_t db_recno_t;
+#define DB_MAX_RECORDS MAX_REC_NUMBER
+
+#define DB_UNKNOWN (-1)
+
+/* DB emulation */
+typedef DB DB_old;
+#undef DB
+#define DB DB_new
+typedef struct __db_new DB;
+
+#undef DB_TXN
+typedef void DB_TXN;
+
+#undef DB_LSN
+typedef struct {
+       int dummy;
+} DB_LSN;
+
+struct __db_new {
+       DB_old *actual_db;
+
+       int type;
+
+       int (*close)(DB *, u_int32_t);
+#define        DB_NOSYNC       26              /* close() */
+
+       int (*open)(DB *, const char *, const char *, DBTYPE, u_int32_t, int);
+#define        DB_CREATE       0x000001        /* Create file as necessary. */
+#define        DB_TRUNCATE     0x004000        /* Discard existing DB (O_TRUNC) */
+
+       int (*sync)(DB *, u_int32_t);
+       int (*get)(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
+       int (*put)(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
+       int (*del)(DB *, DB_TXN *, DBT *, u_int32_t);
+
+       int (*cursor)(DB *, DB_TXN *, DBC **, u_int32_t);
+
+       int (*set_flags)(DB *, u_int32_t);
+#define        DB_RENUMBER     0x0008          /* Recno: renumber on insert/delete. */
+#define        DB_SNAPSHOT     0x0020          /* Recno: snapshot the input. */
+
+       int (*set_pagesize)(DB *, u_int32_t);
+
+       int (*set_re_delim)(DB *, int);
+       int (*set_re_source)(DB *, const char *);
+
+       RECNOINFO _recno_info;
+       u_int32_t _pagesize;
+       u_int32_t _flags;
+};
+
+struct __dbc_new {
+       DB *db;
+       db_recno_t pos;
+       DBT_v1 pos_key;
+       int (*c_close)(DBC *);
+       int (*c_get)(DBC *, DBT *, DBT *, u_int32_t);
+       int (*c_put)(DBC *, DBT *, DBT *, u_int32_t);
+};
+
+#endif /* USE_DB1 */
diff --git a/dist/nvi/common/db1.c b/dist/nvi/common/db1.c
new file mode 100644 (file)
index 0000000..082e8be
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * DB1->3 compatibility layer
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+
+#include "../common/db.h"
+#include "../common/dbinternal.h"
+
+/*
+ * DB_ENV emulation
+ */
+
+static int db1_dbenv_close(DB_ENV *, u_int32_t);
+static int db1_dbenv_open(DB_ENV *, char *, u_int32_t, int);
+static int db1_dbenv_remove(DB_ENV *, char *, u_int32_t);
+
+int
+db_env_create(DB_ENV **dbenvp, u_int32_t flags) {
+       DB_ENV *dbenv;
+
+       assert(flags == 0);
+
+       dbenv = malloc(sizeof *dbenv);
+       if (dbenv == NULL)
+               return -1;
+
+       dbenv->close = db1_dbenv_close;
+       dbenv->open = db1_dbenv_open;
+       dbenv->remove = db1_dbenv_remove;
+
+       dbenv->base_path = NULL;
+       dbenv->mode = 0;
+
+       *dbenvp = dbenv;
+       return 0;
+}
+
+static int
+db1_dbenv_close(DB_ENV *dbenv, u_int32_t flags) {
+       assert(flags == 0);
+
+       if (dbenv->base_path != NULL)
+               free(dbenv->base_path);
+
+       free(dbenv);
+       return 0;
+}
+
+static int
+db1_dbenv_open(DB_ENV *dbenv, char *base_path, u_int32_t flags, int mode) {
+
+       /* We ignore flags on purpose */
+
+       dbenv->base_path = strdup(base_path);
+       if (dbenv->base_path == NULL)
+               return ENOSPC;
+
+       dbenv->mode = mode != 0? mode : 0660;
+       return 0;
+}
+
+static int
+db1_dbenv_remove(DB_ENV *dbenv_fake, char *base_path, u_int32_t flags) {
+       /* dbenv_fake is not a useful environment */
+       /* XXX check if we have to remove files here */
+
+       return 0;
+}
+
+/*
+ * DB emulation
+ */
+static int db1_db_close(DB *, u_int32_t);
+static int db1_db_open(DB *, const char *, const char *, DBTYPE, u_int32_t, int);
+static int db1_db_sync(DB *, u_int32_t);
+static int db1_db_get(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
+static int db1_db_put(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
+static int db1_db_del(DB *, DB_TXN *, DBT *, u_int32_t);
+static int db1_db_set_flags(DB *, u_int32_t);
+static int db1_db_set_pagesize(DB *, u_int32_t);
+static int db1_db_set_re_delim(DB *, int);
+static int db1_db_set_re_source(DB *, const char *);
+static int db1_db_cursor(DB *, DB_TXN *, DBC **, u_int32_t);
+
+int
+db_create(DB **dbp, DB_ENV *dbenv, u_int32_t flags) {
+       assert(flags == 0);
+
+       *dbp = malloc(sizeof **dbp);
+       if (*dbp == NULL)
+               return -1;
+
+       (*dbp)->type = DB_UNKNOWN;
+       (*dbp)->actual_db = NULL;
+       (*dbp)->_pagesize = 0;
+       (*dbp)->_flags = 0;
+       memset(&(*dbp)->_recno_info, 0, sizeof (RECNOINFO));
+
+       (*dbp)->close = db1_db_close;
+       (*dbp)->open = db1_db_open;
+       (*dbp)->sync = db1_db_sync;
+       (*dbp)->get = db1_db_get;
+       (*dbp)->put = db1_db_put;
+       (*dbp)->del = db1_db_del;
+       (*dbp)->set_flags = db1_db_set_flags;
+       (*dbp)->set_pagesize = db1_db_set_pagesize;
+       (*dbp)->set_re_delim = db1_db_set_re_delim;
+       (*dbp)->set_re_source = db1_db_set_re_source;
+       (*dbp)->cursor = db1_db_cursor;
+
+       return 0;
+}
+
+const char *
+db_strerror(int error) {
+       return error > 0? strerror(error) : "record not found";
+}
+
+static int
+db1_db_close(DB *db, u_int32_t flags) {
+       if (flags & DB_NOSYNC) {
+               /* XXX warn user? */
+       }
+       db->actual_db->close(db->actual_db);
+
+       db->type = DB_UNKNOWN;
+       db->actual_db = NULL;
+       db->_pagesize = 0;
+       db->_flags = 0;
+       memset(&db->_recno_info, 0, sizeof (RECNOINFO));
+
+       return 0;
+}
+
+static int
+db1_db_open(DB *db, const char *file, const char *database, DBTYPE type,
+                                               u_int32_t flags, int mode) {
+       int oldflags = 0;
+
+       assert(database == NULL && !(flags & ~(DB_CREATE | DB_TRUNCATE)));
+
+       db->type = type;
+
+       if (flags & DB_CREATE)
+               oldflags |= O_CREAT;
+       if (flags & DB_TRUNCATE)
+               oldflags |= O_TRUNC;
+
+       if (type == DB_RECNO) {
+               const char *tmp = file;
+
+               /* The interface is reversed in DB3 */
+               file = db->_recno_info.bfname;
+               db->_recno_info.bfname = __UNCONST(tmp);
+
+               /* ... and so, we should avoid to truncate the main file! */
+               oldflags &= ~O_TRUNC;
+
+               db->_recno_info.flags =
+                       db->_flags & DB_SNAPSHOT? R_SNAPSHOT : 0;
+               db->_recno_info.psize = db->_pagesize;
+       }
+
+       db->actual_db = dbopen(file, oldflags, mode, type,
+                               type == DB_RECNO? &db->_recno_info : NULL);
+
+       return db->actual_db == NULL? errno : 0;
+}
+
+static int
+db1_db_sync(DB *db, u_int32_t flags) {
+       assert(flags == 0);
+
+       return db->actual_db->sync(db->actual_db, db->type == DB_UNKNOWN?
+                                       R_RECNOSYNC : 0) == 0? 0 : errno;
+}
+
+static int
+db1_db_get(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) {
+       int err;
+       DBT_v1 data1;
+
+       assert(flags == 0 && txnid == NULL);
+
+       err = db->actual_db->get(db->actual_db, (DBT_v1 *) key, &data1, flags);
+       if (err == 1)
+               return DB_NOTFOUND;
+       else if (err == -1)
+               return errno;
+
+       if (data->flags & DB_DBT_USERMEM) {
+               data->size = data1.size;
+               if (data1.size > data->ulen)
+                       return DB_BUFFER_SMALL;
+
+               memcpy(data->data, data1.data, data1.size);
+       }
+
+       return 0;
+}
+
+static int
+db1_db_put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) {
+       int err;
+       DB_old *db_v1 = db->actual_db;
+       DBT data1;
+       DBT key1;
+       recno_t recno = 1;
+
+       assert((flags & ~DB_APPEND) == 0 && txnid == NULL);
+
+       key1 = *key;
+
+       if (flags & DB_APPEND) {
+               if (db_v1->seq(db_v1, (DBT_v1 *)(void *)key,
+                   (DBT_v1 *)(void *)&data1, R_LAST) == 1) {
+                       key1.data = &recno;
+                       key1.size = sizeof recno;
+               }
+       }
+       err = db_v1->put(db_v1, (DBT_v1 *)(void *)&key1, (DBT_v1 *)(void *)data,
+           0);
+
+       return err == -1? errno : err;
+}
+
+static int
+db1_db_del(DB *db, DB_TXN *txnid, DBT *key, u_int32_t flags) {
+       int err;
+       DB_old *db_v1 = db->actual_db;
+
+       assert(txnid == NULL && flags == 0);
+
+       err = db_v1->del(db_v1, (DBT_v1 *) key, 0);
+       return err == -1? errno : err;
+}
+
+static int
+db1_db_set_flags(DB *db, u_int32_t flags) {
+       assert((flags & ~(DB_RENUMBER | DB_SNAPSHOT)) == 0);
+
+       /* Can't prevent renumbering from happening with DB1 */
+       assert((flags | db->_flags) & DB_RENUMBER);
+
+
+       db->_flags |= flags;
+
+       return 0;
+}
+
+static int
+db1_db_set_pagesize(DB *db, u_int32_t pagesize) {
+       db->_pagesize = pagesize;
+
+       return 0;
+}
+
+static int
+db1_db_set_re_delim(DB *db, int re_delim) {
+       db->_recno_info.bval = re_delim;
+
+       return 0;
+}
+
+static int
+db1_db_set_re_source(DB *db, const char *re_source) {
+       db->_recno_info.bfname = __UNCONST(re_source);
+
+       return 0;
+}
+
+/* DBC emulation. Very basic, only one cursor at a time, enough for vi */
+
+static int db1_dbc_close(DBC *);
+static int db1_dbc_get(DBC *, DBT *, DBT *, u_int32_t);
+static int db1_dbc_put(DBC *, DBT *, DBT *, u_int32_t);
+
+static int
+db1_db_cursor(DB *db, DB_TXN *txn, DBC **cursorp, u_int32_t flags) {
+       DBC *cursor;
+
+       assert(txn == NULL && flags == 0);
+
+       cursor = malloc(sizeof *cursor);
+       if (cursor == NULL)
+               return -1;
+
+       cursor->db = db;
+       cursor->pos_key.data = &cursor->pos;
+       cursor->pos_key.size = sizeof cursor->pos;
+       cursor->c_close = db1_dbc_close;
+       cursor->c_get = db1_dbc_get;
+       cursor->c_put = db1_dbc_put;
+
+       *cursorp = cursor;
+
+       return 0;
+}
+
+static int
+db1_dbc_close(DBC *cursor) {
+       free(cursor);
+       return 0;
+}
+
+static int
+db1_dbc_get(DBC *cursor, DBT *key, DBT *data, u_int32_t flags) {
+       DB *db = cursor->db;
+       DB_old *db_v1 = db->actual_db;
+       int ret = 0;
+
+
+       switch(flags) {
+       case DB_SET:
+               ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data,
+                       R_CURSOR);
+               cursor->pos = * (db_recno_t *) key->data;
+               break;
+       case DB_FIRST:
+               ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data,
+                       R_FIRST);
+               if (ret == 1)
+                       ret = DB_NOTFOUND;
+               cursor->pos = * (db_recno_t *) key->data;
+               break;
+       case DB_LAST:
+               ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data,
+                       R_LAST);
+               if (ret == 1)
+                       ret = DB_NOTFOUND;
+               cursor->pos = * (db_recno_t *) key->data;
+               break;
+       default:
+               abort();
+       }
+
+       return ret;
+}
+
+static int
+db1_dbc_put(DBC *cursor, DBT *key, DBT *data, u_int32_t flags) {
+       DB *db = cursor->db;
+       DB_old *db_v1 = db->actual_db;
+       int ret = 0;
+
+       assert((flags & ~(DB_BEFORE | DB_AFTER)) == 0);
+
+       ret = db_v1->put(db_v1, &cursor->pos_key, (DBT_v1 *) data,
+               flags == DB_BEFORE? R_IBEFORE : R_IAFTER);
+
+       return ret == -1? errno : ret;
+}
diff --git a/dist/nvi/common/dbinternal.h b/dist/nvi/common/dbinternal.h
new file mode 100644 (file)
index 0000000..35856fc
--- /dev/null
@@ -0,0 +1,3 @@
+int db_env_create(DB_ENV **, u_int32_t);
+int db_create(DB **, DB_ENV *, u_int32_t);
+const char *db_strerror(int);
diff --git a/dist/nvi/common/delete.c b/dist/nvi/common/delete.c
new file mode 100644 (file)
index 0000000..36e52e9
--- /dev/null
@@ -0,0 +1,160 @@
+/*     $NetBSD: delete.c,v 1.6 2012/01/27 16:41:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: delete.c,v 10.17 2001/06/25 15:19:09 skimo Exp (Berkeley) Date: 2001/06/25 15:19:09";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+/*
+ * del --
+ *     Delete a range of text.
+ *
+ * PUBLIC: int del __P((SCR *, MARK *, MARK *, int));
+ */
+int
+del(SCR *sp, MARK *fm, MARK *tm, int lmode)
+{
+       db_recno_t lno;
+       size_t blen, len, nlen, tlen;
+       CHAR_T *bp, *p;
+       int eof, rval;
+
+       bp = NULL;
+
+       /* Case 1 -- delete in line mode. */
+       if (lmode) {
+               for (lno = tm->lno; lno >= fm->lno; --lno) {
+                       if (db_delete(sp, lno))
+                               return (1);
+                       ++sp->rptlines[L_DELETED];
+                       if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
+                               break;
+               }
+               goto done;
+       }
+
+       /*
+        * Case 2 -- delete to EOF.  This is a special case because it's
+        * easier to pick it off than try and find it in the other cases.
+        */
+       if (db_last(sp, &lno))
+               return (1);
+       if (tm->lno >= lno) {
+               if (tm->lno == lno) {
+                       if (db_get(sp, lno, DBG_FATAL, &p, &len))
+                               return (1);
+                       eof = tm->cno != ENTIRE_LINE && tm->cno >= len ? 1 : 0;
+               } else
+                       eof = 1;
+               if (eof) {
+                       for (lno = tm->lno; lno > fm->lno; --lno) {
+                               if (db_delete(sp, lno))
+                                       return (1);
+                               ++sp->rptlines[L_DELETED];
+                               if (lno %
+                                   INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
+                                       break;
+                       }
+                       if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
+                               return (1);
+                       GET_SPACE_RETW(sp, bp, blen, fm->cno);
+                       MEMCPYW(bp, p, fm->cno);
+                       if (db_set(sp, fm->lno, bp, fm->cno))
+                               return (1);
+                       goto done;
+               }
+       }
+
+       /* Case 3 -- delete within a single line. */
+       if (tm->lno == fm->lno) {
+               if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
+                       return (1);
+               GET_SPACE_RETW(sp, bp, blen, len);
+               if (fm->cno != 0)
+                       MEMCPYW(bp, p, fm->cno);
+               MEMCPYW(bp + fm->cno, p + (tm->cno + 1), 
+                       len - (tm->cno + 1));
+               if (db_set(sp, fm->lno,
+                   bp, len - ((tm->cno - fm->cno) + 1)))
+                       goto err;
+               goto done;
+       }
+
+       /*
+        * Case 4 -- delete over multiple lines.
+        *
+        * Copy the start partial line into place.
+        */
+       if ((tlen = fm->cno) != 0) {
+               if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL))
+                       return (1);
+               GET_SPACE_RETW(sp, bp, blen, tlen + 256);
+               MEMCPYW(bp, p, tlen);
+       }
+
+       /* Copy the end partial line into place. */
+       if (db_get(sp, tm->lno, DBG_FATAL, &p, &len))
+               goto err;
+       if (len != 0 && tm->cno != len - 1) {
+               /*
+                * XXX
+                * We can overflow memory here, if the total length is greater
+                * than SIZE_T_MAX.  The only portable way I've found to test
+                * is depending on the overflow being less than the value.
+                */
+               nlen = (len - (tm->cno + 1)) + tlen;
+               if (tlen > nlen) {
+                       msgq(sp, M_ERR, "002|Line length overflow");
+                       goto err;
+               }
+               if (tlen == 0) {
+                       GET_SPACE_RETW(sp, bp, blen, nlen);
+               } else
+                       ADD_SPACE_RETW(sp, bp, blen, nlen);
+
+               MEMCPYW(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
+               tlen += len - (tm->cno + 1);
+       }
+
+       /* Set the current line. */
+       if (db_set(sp, fm->lno, bp, tlen))
+               goto err;
+
+       /* Delete the last and intermediate lines. */
+       for (lno = tm->lno; lno > fm->lno; --lno) {
+               if (db_delete(sp, lno))
+                       goto err;
+               ++sp->rptlines[L_DELETED];
+               if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
+                       break;
+       }
+
+done:  rval = 0;
+       if (0)
+err:           rval = 1;
+       if (bp != NULL)
+               FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
diff --git a/dist/nvi/common/dldb.c b/dist/nvi/common/dldb.c
new file mode 100644 (file)
index 0000000..685079d
--- /dev/null
@@ -0,0 +1,47 @@
+/*     $NetBSD: dldb.c,v 1.1.1.2 2008/05/18 14:29:41 aymeric Exp $ */
+
+#include "config.h"
+
+#include <dlfcn.h>
+
+#include "common.h"
+#include "pathnames.h"
+
+static void relocate __P(());
+
+#define RELOC(func,returntype,args,proto,types) \
+    static returntype reloc_##func __P(proto); \
+    returntype (*nvi_##func) __P(proto) = reloc_##func; \
+    static returntype reloc_##func args \
+           types \
+    { \
+           relocate(); \
+           return nvi_##func args; \
+    }
+
+RELOC(db_create,int,(a,b,c),(DB **, DB_ENV *, u_int32_t),
+    DB**a;DB_ENV*b;u_int32_t c;)
+RELOC(db_env_create,int,(a,b),(DB_ENV **, u_int32_t),DB_ENV ** a;u_int32_t b;);
+RELOC(db_strerror,char *,(a),(int),int a;)
+
+#define LOADSYM(func) \
+    if ((nvi_##func = dlsym(handle, #func)) == NULL) \
+           goto error;
+
+static void 
+relocate()
+{
+       void *handle = dlopen(_PATH_DB3, RTLD_LAZY);
+
+       if (!handle)
+           goto error;
+
+       LOADSYM(db_create)
+       LOADSYM(db_env_create)
+       LOADSYM(db_strerror)
+
+       return;
+error:
+       fprintf(stderr, "Relocation error: %s\n", dlerror());
+       abort();
+}
diff --git a/dist/nvi/common/exf.c b/dist/nvi/common/exf.c
new file mode 100644 (file)
index 0000000..de9a186
--- /dev/null
@@ -0,0 +1,1650 @@
+/*     $NetBSD: exf.c,v 1.5 2012/07/15 09:13:59 spz Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: exf.c,v 10.72 2003/08/10 09:44:01 skimo Exp (Berkeley) Date: 2003/08/10 09:44:01";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>         /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+/*
+ * We include <sys/file.h>, because the flock(2) and open(2) #defines
+ * were found there on historical systems.  We also include <fcntl.h>
+ * because the open(2) #defines are found there on newer systems.
+ */
+#include <sys/file.h>
+
+#include <bitstring.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "common.h"
+#include "dbinternal.h"
+
+static int     file_backup __P((SCR *, const char *, const char *));
+static void    file_cinit __P((SCR *));
+static void    file_comment __P((SCR *));
+static int     file_spath __P((SCR *, FREF *, struct stat *, int *));
+static int     db_setup __P((SCR *sp, EXF *ep));
+
+/*
+ * file_add --
+ *     Insert a file name into the FREF list, if it doesn't already
+ *     appear in it.
+ *
+ * !!!
+ * The "if it doesn't already appear" changes vi's semantics slightly.  If
+ * you do a "vi foo bar", and then execute "next bar baz", the edit of bar
+ * will reflect the line/column of the previous edit session.  Historic nvi
+ * did not do this.  The change is a logical extension of the change where
+ * vi now remembers the last location in any file that it has ever edited,
+ * not just the previously edited file.
+ *
+ * PUBLIC: FREF *file_add __P((SCR *, char *));
+ */
+FREF *
+file_add(SCR *sp, const char *name)
+{
+       GS *gp;
+       FREF *frp, *tfrp;
+
+       /*
+        * Return it if it already exists.  Note that we test against the
+        * user's name, whatever that happens to be, including if it's a
+        * temporary file.
+        *
+        * If the user added a file but was unable to initialize it, there
+        * can be file list entries where the name field is NULL.  Discard
+        * them the next time we see them.
+        */
+       gp = sp->gp;
+       if (name != NULL)
+               for (frp = gp->frefq.cqh_first;
+                   frp != (FREF *)(void *)&gp->frefq; frp = frp->q.cqe_next) {
+                       if (frp->name == NULL) {
+                               tfrp = frp->q.cqe_next;
+                               CIRCLEQ_REMOVE(&gp->frefq, frp, q);
+                               if (frp->name != NULL)
+                                       free(frp->name);
+                               free(frp);
+                               frp = tfrp;
+                               continue;
+                       }
+                       if (!strcmp(frp->name, name))
+                               return (frp);
+               }
+
+       /* Allocate and initialize the FREF structure. */
+       CALLOC(sp, frp, FREF *, 1, sizeof(FREF));
+       if (frp == NULL)
+               return (NULL);
+
+       /*
+        * If no file name specified, or if the file name is a request
+        * for something temporary, file_init() will allocate the file
+        * name.  Temporary files are always ignored.
+        */
+       if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) &&
+           (frp->name = strdup(name)) == NULL) {
+               free(frp);
+               msgq(sp, M_SYSERR, NULL);
+               return (NULL);
+       }
+
+       /* Append into the chain of file names. */
+       CIRCLEQ_INSERT_TAIL(&gp->frefq, frp, q);
+
+       return (frp);
+}
+
+/*
+ * file_init --
+ *     Start editing a file, based on the FREF structure.  If successsful,
+ *     let go of any previous file.  Don't release the previous file until
+ *     absolutely sure we have the new one.
+ *
+ * PUBLIC: int file_init __P((SCR *, FREF *, char *, int));
+ */
+int
+file_init(SCR *sp, FREF *frp, char *rcv_name, int flags)
+{
+       EXF *ep;
+       struct stat sb;
+       size_t psize;
+       int fd, exists, open_err, readonly, stolen;
+       char *oname = NULL, tname[MAXPATHLEN];
+
+       stolen = open_err = readonly = 0;
+
+       /*
+        * If the file is a recovery file, let the recovery code handle it.
+        * Clear the FR_RECOVER flag first -- the recovery code does set up,
+        * and then calls us!  If the recovery call fails, it's probably
+        * because the named file doesn't exist.  So, move boldly forward,
+        * presuming that there's an error message the user will get to see.
+        */
+       if (F_ISSET(frp, FR_RECOVER)) {
+               F_CLR(frp, FR_RECOVER);
+               return (rcv_read(sp, frp));
+       }
+
+       /*
+        * Required FRP initialization; the only flag we keep is the
+        * cursor information.
+        */
+       F_CLR(frp, ~FR_CURSORSET);
+
+       /*
+        * Scan the user's path to find the file that we're going to
+        * try and open.
+        */
+       if (file_spath(sp, frp, &sb, &exists))
+               return (1);
+
+       /*
+        * Check whether we already have this file opened in some
+        * other screen.
+        */
+       if (exists) {
+               EXF *exfp;
+               for (exfp = sp->gp->exfq.cqh_first;
+                   exfp != (EXF *)&sp->gp->exfq; exfp = exfp->q.cqe_next) {
+                       if (exfp->mdev == sb.st_dev &&
+                           exfp->minode == sb.st_ino && 
+                           (exfp != sp->ep || exfp->refcnt > 1)) {
+                               ep = exfp;
+                               oname = ep->rcv_path;
+                               goto postinit;
+                       }
+               }
+       }
+
+       /*
+        * Required EXF initialization:
+        *      Flush the line caches.
+        *      Default recover mail file fd to -1.
+        *      Set initial EXF flag bits.
+        */
+       CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF));
+       CIRCLEQ_INIT(&ep->scrq);
+       sp->c_lno = ep->c_nlines = OOBLNO;
+       ep->fd = ep->rcv_fd = ep->fcntl_fd = -1;
+       F_SET(ep, F_FIRSTMODIFY);
+
+       /*
+        * If no name or backing file, for whatever reason, create a backing
+        * temporary file, saving the temp file name so we can later unlink
+        * it.  If the user never named this file, copy the temporary file name
+        * to the real name (we display that until the user renames it).
+        */
+       oname = frp->name;
+       if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) {
+               if (opts_empty(sp, O_TMP_DIRECTORY, 0))
+                       goto err;
+               (void)snprintf(tname, sizeof(tname),
+                   "%s/vi.XXXXXX", O_STR(sp, O_TMP_DIRECTORY));
+               if ((fd = mkstemp(tname)) == -1) {
+                       msgq(sp, M_SYSERR,
+                           "237|Unable to create temporary file");
+                       goto err;
+               }
+               (void)close(fd);
+
+               if (frp->name == NULL)
+                       F_SET(frp, FR_TMPFILE);
+               if ((frp->tname = strdup(tname)) == NULL ||
+                   (frp->name == NULL && 
+                    (frp->name = strdup(tname)) == NULL)) {
+                       if (frp->tname != NULL) {
+                               free(frp->tname);
+                       }
+                       msgq(sp, M_SYSERR, NULL);
+                       (void)unlink(tname);
+                       goto err;
+               }
+               oname = frp->tname;
+               psize = 1024;
+               if (!LF_ISSET(FS_OPENERR))
+                       F_SET(frp, FR_NEWFILE);
+
+               time(&ep->mtime);
+       } else {
+               /*
+                * XXX
+                * A seat of the pants calculation: try to keep the file in
+                * 15 pages or less.  Don't use a page size larger than 10K
+                * (vi should have good locality) or smaller than 1K.
+                */
+               psize = ((sb.st_size / 15) + 1023) / 1024;
+               if (psize > 10)
+                       psize = 10;
+               if (psize == 0)
+                       psize = 1;
+               psize *= 1024;
+
+               F_SET(ep, F_DEVSET);
+               ep->mdev = sb.st_dev;
+               ep->minode = sb.st_ino;
+
+               ep->mtime = sb.st_mtime;
+
+               if (!S_ISREG(sb.st_mode))
+                       msgq_str(sp, M_ERR, oname,
+                           "238|Warning: %s is not a regular file");
+       }
+
+       /* Set up recovery. */
+       if (rcv_name == NULL) {
+               /* ep->rcv_path NULL if rcv_tmp fails */
+               rcv_tmp(sp, ep, frp->name);
+       } else {
+               if ((ep->rcv_path = strdup(rcv_name)) == NULL) {
+                       msgq(sp, M_SYSERR, NULL);
+                       goto err;
+               }
+               F_SET(ep, F_MODIFIED);
+       }
+
+       if (db_setup(sp, ep))
+               goto err;
+
+       /* Open a db structure. */
+       if ((sp->db_error = db_create(&ep->db, 0, 0)) != 0) {
+               msgq(sp, M_DBERR, "db_create");
+               goto err;
+       }
+
+       ep->db->set_re_delim(ep->db, '\n');             /* Always set. */
+       ep->db->set_pagesize(ep->db, psize);
+       ep->db->set_flags(ep->db, DB_RENUMBER | DB_SNAPSHOT);
+       if (rcv_name == NULL)
+               ep->db->set_re_source(ep->db, oname);
+
+/* 
+ * Don't let db use mmap when using fcntl for locking
+ */
+#ifdef HAVE_LOCK_FCNTL
+#define NOMMAPIFFCNTL DB_NOMMAP
+#else
+#define NOMMAPIFFCNTL 0
+#endif
+
+#define _DB_OPEN_MODE  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+
+       if ((sp->db_error = db_open(ep->db, ep->rcv_path, DB_RECNO,
+           ((rcv_name == 0) ? DB_TRUNCATE : 0) | VI_DB_THREAD | NOMMAPIFFCNTL,
+           _DB_OPEN_MODE)) != 0) {
+               msgq_str(sp,
+                   M_DBERR, rcv_name == NULL ? oname : rcv_name, "%s");
+               /*
+                * !!!
+                * Historically, vi permitted users to edit files that couldn't
+                * be read.  This isn't useful for single files from a command
+                * line, but it's quite useful for "vi *.c", since you can skip
+                * past files that you can't read.
+                */ 
+               ep->db = NULL; /* Don't close it; it wasn't opened */
+
+               if (LF_ISSET(FS_OPENERR)) 
+                   goto err;
+
+               open_err = 1;
+               goto oerr;
+       }
+
+       /* re_source is loaded into the database.
+        * Close it and reopen it in the environment. 
+        */
+       if ((sp->db_error = ep->db->close(ep->db, 0))) {
+               msgq(sp, M_DBERR, "close");
+               goto err;
+       }
+       if ((sp->db_error = db_create(&ep->db, ep->env, 0)) != 0) {
+               msgq(sp, M_DBERR, "db_create 2");
+               goto err;
+       }
+       if ((sp->db_error = db_open(ep->db, ep->rcv_path, DB_RECNO,
+           VI_DB_THREAD | NOMMAPIFFCNTL, _DB_OPEN_MODE)) != 0) {
+               msgq_str(sp,
+                   M_DBERR, ep->rcv_path, "%s");
+               goto err;
+       }
+
+       /*
+        * Do the remaining things that can cause failure of the new file,
+        * mark and logging initialization.
+        */
+       if (mark_init(sp, ep) || log_init(sp, ep))
+               goto err;
+
+postinit:
+       /*
+        * Set the alternate file name to be the file we're discarding.
+        *
+        * !!!
+        * Temporary files can't become alternate files, so there's no file
+        * name.  This matches historical practice, although it could only
+        * happen in historical vi as the result of the initial command, i.e.
+        * if vi was executed without a file name.
+        */
+       if (LF_ISSET(FS_SETALT))
+               set_alt_name(sp, sp->frp == NULL ||
+                   F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name);
+
+       /*
+        * Close the previous file; if that fails, close the new one and run
+        * for the border.
+        *
+        * !!!
+        * There's a nasty special case.  If the user edits a temporary file,
+        * and then does an ":e! %", we need to re-initialize the backing
+        * file, but we can't change the name.  (It's worse -- we're dealing
+        * with *names* here, we can't even detect that it happened.)  Set a
+        * flag so that the file_end routine ignores the backing information
+        * of the old file if it happens to be the same as the new one.
+        *
+        * !!!
+        * Side-effect: after the call to file_end(), sp->frp may be NULL.
+        */
+       if (sp->ep != NULL) {
+               F_SET(frp, FR_DONTDELETE);
+               if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) {
+                       (void)file_end(sp, ep, 1);
+                       goto err;
+               }
+               sp->ep = NULL;
+               F_CLR(frp, FR_DONTDELETE);
+       }
+
+       /*
+        * Lock the file; if it's a recovery file, it should already be
+        * locked.  Note, we acquire the lock after the previous file
+        * has been ended, so that we don't get an "already locked" error
+        * for ":edit!".
+        *
+        * XXX
+        * While the user can't interrupt us between the open and here,
+        * there's a race between the dbopen() and the lock.  Not much
+        * we can do about it.
+        *
+        * XXX
+        * We don't make a big deal of not being able to lock the file.  As
+        * locking rarely works over NFS, and often fails if the file was
+        * mmap(2)'d, it's far too common to do anything like print an error
+        * message, let alone make the file readonly.  At some future time,
+        * when locking is a little more reliable, this should change to be
+        * an error.
+        */
+       if (rcv_name == NULL && ep->refcnt == 0) {
+               if ((ep->fd = open(oname, O_RDWR)) == -1)
+                   goto no_lock;
+
+               switch (file_lock(sp, oname, &ep->fcntl_fd, ep->fd, 1)) {
+               case LOCK_FAILED:
+no_lock:
+                       F_SET(frp, FR_UNLOCKED);
+                       break;
+               case LOCK_UNAVAIL:
+                       readonly = 1;
+                       msgq_str(sp, M_INFO, oname,
+                           "239|%s already locked, session is read-only");
+                       break;
+               case LOCK_SUCCESS:
+                       break;
+               }
+       }
+
+       /*
+         * Historically, the readonly edit option was set per edit buffer in
+         * vi, unless the -R command-line option was specified or the program
+         * was executed as "view".  (Well, to be truthful, if the letter 'w'
+         * occurred anywhere in the program name, but let's not get into that.)
+        * So, the persistant readonly state has to be stored in the screen
+        * structure, and the edit option value toggles with the contents of
+        * the edit buffer.  If the persistant readonly flag is set, set the
+        * readonly edit option.
+        *
+        * Otherwise, try and figure out if a file is readonly.  This is a
+        * dangerous thing to do.  The kernel is the only arbiter of whether
+        * or not a file is writeable, and the best that a user program can
+        * do is guess.  Obvious loopholes are files that are on a file system
+        * mounted readonly (access catches this one on a few systems), or
+        * alternate protection mechanisms, ACL's for example, that we can't
+        * portably check.  Lots of fun, and only here because users whined.
+        *
+        * !!!
+        * Historic vi displayed the readonly message if none of the file
+        * write bits were set, or if an an access(2) call on the path
+        * failed.  This seems reasonable.  If the file is mode 444, root
+        * users may want to know that the owner of the file did not expect
+        * it to be written.
+        *
+        * Historic vi set the readonly bit if no write bits were set for
+        * a file, even if the access call would have succeeded.  This makes
+        * the superuser force the write even when vi expects that it will
+        * succeed.  I'm less supportive of this semantic, but it's historic
+        * practice and the conservative approach to vi'ing files as root.
+        *
+        * It would be nice if there was some way to update this when the user
+        * does a "^Z; chmod ...".  The problem is that we'd first have to
+        * distinguish between readonly bits set because of file permissions
+        * and those set for other reasons.  That's not too hard, but deciding
+        * when to reevaluate the permissions is trickier.  An alternative
+        * might be to turn off the readonly bit if the user forces a write
+        * and it succeeds.
+        *
+        * XXX
+        * Access(2) doesn't consider the effective uid/gid values.  This
+        * probably isn't a problem for vi when it's running standalone.
+        */
+       if (readonly || F_ISSET(sp, SC_READONLY) ||
+           (!F_ISSET(frp, FR_NEWFILE) &&
+           (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) ||
+           access(frp->name, W_OK))))
+               O_SET(sp, O_READONLY);
+       else
+               O_CLR(sp, O_READONLY);
+
+       /* Switch... */
+       ++ep->refcnt;
+       CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq);
+       sp->ep = ep;
+       sp->frp = frp;
+
+       /* Set the initial cursor position, queue initial command. */
+       file_cinit(sp);
+
+       /* Report conversion errors again. */
+       F_CLR(sp, SC_CONV_ERROR);
+
+       /* Redraw the screen from scratch, schedule a welcome message. */
+       F_SET(sp, SC_SCR_REFORMAT | SC_STATUS);
+
+       if (frp->lno == OOBLNO)
+               F_SET(sp, SC_SCR_TOP);
+
+       /* Append into the chain of file structures. */
+       if (ep->refcnt == 1)
+               CIRCLEQ_INSERT_TAIL(&sp->gp->exfq, ep, q);
+
+       return (0);
+
+err:   if (frp->name != NULL) {
+               free(frp->name);
+               frp->name = NULL;
+       }
+       if (frp->tname != NULL) {
+               (void)unlink(frp->tname);
+               free(frp->tname);
+               frp->tname = NULL;
+       }
+
+oerr:  if (F_ISSET(ep, F_RCV_ON))
+               (void)unlink(ep->rcv_path);
+       if (ep->rcv_path != NULL) {
+               free(ep->rcv_path);
+               ep->rcv_path = NULL;
+       }
+       if (ep->db != NULL) {
+               (void)ep->db->close(ep->db, DB_NOSYNC);
+               ep->db = NULL;
+       }
+       free(ep);
+
+       return (open_err && !LF_ISSET(FS_OPENERR) ?
+           file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1);
+}
+
+/*
+ * file_spath --
+ *     Scan the user's path to find the file that we're going to
+ *     try and open.
+ */
+static int
+file_spath(SCR *sp, FREF *frp, struct stat *sbp, int *existsp)
+{
+       size_t len;
+       int found;
+       char *name, path[MAXPATHLEN];
+       const char *p, *t;
+
+       /*
+        * If the name is NULL or an explicit reference (i.e., the first
+        * component is . or ..) ignore the O_PATH option.
+        */
+       name = frp->name;
+       if (name == NULL) {
+               *existsp = 0;
+               return (0);
+       }
+       if (name[0] == '/' || (name[0] == '.' &&
+           (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) {
+               *existsp = !stat(name, sbp);
+               return (0);
+       }
+
+       /* Try . */
+       if (!stat(name, sbp)) {
+               *existsp = 1;
+               return (0);
+       }
+
+       /* Try the O_PATH option values. */
+       for (found = 0, p = t = O_STR(sp, O_PATH);; ++p)
+               if (*p == ':' || *p == '\0') {
+                       if (t < p - 1) {
+                               len = snprintf(path, sizeof(path), "%.*s/%s",
+                                   (int)(p - t), t, name);
+                               if (!stat(path, sbp)) {
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       t = p + 1;
+                       if (*p == '\0')
+                               break;
+               }
+
+       /* If we found it, build a new pathname and discard the old one. */
+       if (found) {
+               char *q;
+               MALLOC_RET(sp, q, char *, len + 1);
+               memcpy(q, path, len + 1);
+               free(frp->name);
+               frp->name = q;
+       }
+       *existsp = found;
+       return (0);
+}
+
+/*
+ * file_cinit --
+ *     Set up the initial cursor position.
+ */
+static void
+file_cinit(SCR *sp)
+{
+       GS *gp;
+       MARK m;
+       size_t len;
+       int nb;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /* Set some basic defaults. */
+       sp->lno = 1;
+       sp->cno = 0;
+
+       /*
+        * Historically, initial commands (the -c option) weren't executed
+        * until a file was loaded, e.g. "vi +10 nofile", followed by an
+        * :edit or :tag command, would execute the +10 on the file loaded
+        * by the subsequent command, (assuming that it existed).  This
+        * applied as well to files loaded using the tag commands, and we
+        * follow that historic practice.  Also, all initial commands were
+        * ex commands and were always executed on the last line of the file.
+        *
+        * Otherwise, if no initial command for this file:
+        *    If in ex mode, move to the last line, first nonblank character.
+        *    If the file has previously been edited, move to the last known
+        *        position, and check it for validity.
+        *    Otherwise, move to the first line, first nonblank.
+        *
+        * This gets called by the file init code, because we may be in a
+        * file of ex commands and we want to execute them from the right
+        * location in the file.
+        */
+       nb = 0;
+       gp = sp->gp;
+       if (gp->c_option != NULL && !F_ISSET(sp->frp, FR_NEWFILE)) {
+               if (db_last(sp, &sp->lno))
+                       return;
+               if (sp->lno == 0) {
+                       sp->lno = 1;
+                       sp->cno = 0;
+               }
+               CHAR2INT(sp, gp->c_option, strlen(gp->c_option) + 1,
+                        wp, wlen);
+               if (ex_run_str(sp, "-c option", wp, wlen - 1, 1, 1))
+                       return;
+               gp->c_option = NULL;
+       } else if (F_ISSET(sp, SC_EX)) {
+               if (db_last(sp, &sp->lno))
+                       return;
+               if (sp->lno == 0) {
+                       sp->lno = 1;
+                       sp->cno = 0;
+                       return;
+               }
+               nb = 1;
+       } else {
+               if (F_ISSET(sp->frp, FR_CURSORSET)) {
+                       sp->lno = sp->frp->lno;
+                       sp->cno = sp->frp->cno;
+
+                       /* If returning to a file in vi, center the line. */
+                        F_SET(sp, SC_SCR_CENTER);
+               } else {
+                       if (O_ISSET(sp, O_COMMENT))
+                               file_comment(sp);
+                       else
+                               sp->lno = 1;
+                       nb = 1;
+               }
+               if (db_get(sp, sp->lno, 0, NULL, &len)) {
+                       sp->lno = 1;
+                       sp->cno = 0;
+                       return;
+               }
+               if (!nb && sp->cno > len)
+                       nb = 1;
+       }
+       if (nb) {
+               sp->cno = 0;
+               (void)nonblank(sp, sp->lno, &sp->cno);
+       }
+
+       /*
+        * !!!
+        * The initial column is also the most attractive column.
+        */
+       sp->rcm = sp->cno;
+
+       /*
+        * !!!
+        * Historically, vi initialized the absolute mark, but ex did not.
+        * Which meant, that if the first command in ex mode was "visual",
+        * or if an ex command was executed first (e.g. vi +10 file) vi was
+        * entered without the mark being initialized.  For consistency, if
+        * the file isn't empty, we initialize it for everyone, believing
+        * that it can't hurt, and is generally useful.  Not initializing it
+        * if the file is empty is historic practice, although it has always
+        * been possible to set (and use) marks in empty vi files.
+        */
+       m.lno = sp->lno;
+       m.cno = sp->cno;
+       (void)mark_set(sp, ABSMARK1, &m, 0);
+}
+
+/*
+ * file_end --
+ *     Stop editing a file.
+ *
+ * PUBLIC: int file_end __P((SCR *, EXF *, int));
+ */
+int
+file_end(SCR *sp, EXF *ep, int force)
+{
+       FREF *frp;
+
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        * (If argument ep is NULL, use sp->ep.)
+        *
+        * If multiply referenced, just decrement the count and return.
+        */
+       if (ep == NULL)
+               ep = sp->ep;
+       CIRCLEQ_REMOVE(&ep->scrq, sp, eq);
+       if (--ep->refcnt != 0)
+               return (0);
+
+       /*
+        *
+        * Clean up the FREF structure.
+        *
+        * Save the cursor location.
+        *
+        * XXX
+        * It would be cleaner to do this somewhere else, but by the time
+        * ex or vi knows that we're changing files it's already happened.
+        */
+       frp = sp->frp;
+       frp->lno = sp->lno;
+       frp->cno = sp->cno;
+       F_SET(frp, FR_CURSORSET);
+
+       /*
+        * We may no longer need the temporary backing file, so clean it
+        * up.  We don't need the FREF structure either, if the file was
+        * never named, so lose it.
+        *
+        * !!!
+        * Re: FR_DONTDELETE, see the comment above in file_init().
+        */
+       if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) {
+               if (unlink(frp->tname))
+                       msgq_str(sp, M_SYSERR, frp->tname, "240|%s: remove");
+               free(frp->tname);
+               frp->tname = NULL;
+               if (F_ISSET(frp, FR_TMPFILE)) {
+                       CIRCLEQ_REMOVE(&sp->gp->frefq, frp, q);
+                       if (frp->name != NULL)
+                               free(frp->name);
+                       free(frp);
+               }
+               sp->frp = NULL;
+       }
+
+       /*
+        * Clean up the EXF structure.
+        *
+        * Close the db structure.
+        */
+       if (ep->db->close != NULL) {
+               if ((sp->db_error = ep->db->close(ep->db, DB_NOSYNC)) != 0 && 
+                   !force) {
+                       msgq_str(sp, M_DBERR, frp->name, "241|%s: close");
+                       CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq);
+                       ++ep->refcnt;
+                       return (1);
+               }
+               ep->db = NULL;
+       }
+
+       /* COMMITTED TO THE CLOSE.  THERE'S NO GOING BACK... */
+
+       /* Stop logging. */
+       (void)log_end(sp, ep);
+
+       /* Free up any marks. */
+       (void)mark_end(sp, ep);
+
+       if (ep->env) {
+               DB_ENV *env;
+
+               ep->env->close(ep->env, 0);
+               ep->env = 0;
+               if ((sp->db_error = db_env_create(&env, 0)))
+                       msgq(sp, M_DBERR, "env_create");
+               if ((sp->db_error = db_env_remove(env, ep->env_path, 0)))
+                       msgq(sp, M_DBERR, "env->remove");
+               if (ep->env_path != NULL && rmdir(ep->env_path))
+                       msgq_str(sp, M_SYSERR, ep->env_path, "242|%s: remove");
+       }
+
+       /*
+        * Delete recovery files, close the open descriptor, free recovery
+        * memory.  See recover.c for a description of the protocol.
+        *
+        * XXX
+        * Unlink backup file first, we can detect that the recovery file
+        * doesn't reference anything when the user tries to recover it.
+        * There's a race, here, obviously, but it's fairly small.
+        */
+       if (!F_ISSET(ep, F_RCV_NORM)) {
+               if (ep->rcv_path != NULL && unlink(ep->rcv_path))
+                       msgq_str(sp, M_SYSERR, ep->rcv_path, "242|%s: remove");
+               if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath))
+                       msgq_str(sp, M_SYSERR, ep->rcv_mpath, "243|%s: remove");
+       }
+       CIRCLEQ_REMOVE(&sp->gp->exfq, ep, q);
+       if (ep->fd != -1)
+               (void)close(ep->fd);
+       if (ep->fcntl_fd != -1)
+               (void)close(ep->fcntl_fd);
+       if (ep->rcv_fd != -1)
+               (void)close(ep->rcv_fd);
+       if (ep->env_path != NULL)
+               free(ep->env_path);
+       if (ep->rcv_path != NULL) {
+               free(ep->rcv_path);
+               ep->rcv_path = NULL;
+       }
+       if (ep->rcv_mpath != NULL)
+               free(ep->rcv_mpath);
+
+       free(ep);
+       return (0);
+}
+
+/*
+ * file_write --
+ *     Write the file to disk.  Historic vi had fairly convoluted
+ *     semantics for whether or not writes would happen.  That's
+ *     why all the flags.
+ *
+ * PUBLIC: int file_write __P((SCR *, MARK *, MARK *, char *, int));
+ */
+int
+file_write(SCR *sp, MARK *fm, MARK *tm, char *name, int flags)
+{
+       enum { NEWFILE, OLDFILE } mtype;
+       struct stat sb;
+       EXF *ep;
+       FILE *fp;
+       FREF *frp;
+       MARK from, to;
+       size_t len;
+       u_long nlno, nch;
+       int fd, nf, noname, oflags, rval;
+       char *p, *s, *t, buf[MAXPATHLEN + 64];
+       const char *msgstr;
+
+       ep = sp->ep;
+       frp = sp->frp;
+
+       /*
+        * Writing '%', or naming the current file explicitly, has the
+        * same semantics as writing without a name.
+        */
+       if (name == NULL || !strcmp(name, frp->name)) {
+               noname = 1;
+               name = frp->name;
+       } else
+               noname = 0;
+
+       /* Can't write files marked read-only, unless forced. */
+       if (!LF_ISSET(FS_FORCE) && noname && O_ISSET(sp, O_READONLY)) {
+               msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
+                   "244|Read-only file, not written; use ! to override" :
+                   "245|Read-only file, not written");
+               return (1);
+       }
+
+       /* If not forced, not appending, and "writeany" not set ... */
+       if (!LF_ISSET(FS_FORCE | FS_APPEND) && !O_ISSET(sp, O_WRITEANY)) {
+               /* Don't overwrite anything but the original file. */
+               if ((!noname || F_ISSET(frp, FR_NAMECHANGE)) &&
+                   !stat(name, &sb)) {
+                       msgq_str(sp, M_ERR, name,
+                           LF_ISSET(FS_POSSIBLE) ?
+                           "246|%s exists, not written; use ! to override" :
+                           "247|%s exists, not written");
+                       return (1);
+               }
+
+               /*
+                * Don't write part of any existing file.  Only test for the
+                * original file, the previous test catches anything else.
+                */
+               if (!LF_ISSET(FS_ALL) && noname && !stat(name, &sb)) {
+                       msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
+                           "248|Partial file, not written; use ! to override" :
+                           "249|Partial file, not written");
+                       return (1);
+               }
+       }
+
+       /*
+        * Figure out if the file already exists -- if it doesn't, we display
+        * the "new file" message.  The stat might not be necessary, but we
+        * just repeat it because it's easier than hacking the previous tests.
+        * The information is only used for the user message and modification
+        * time test, so we can ignore the obvious race condition.
+        *
+        * One final test.  If we're not forcing or appending the current file,
+        * and we have a saved modification time, object if the file changed
+        * since we last edited or wrote it, and make them force it.
+        */
+       if (stat(name, &sb))
+               mtype = NEWFILE;
+       else {
+               if (noname && !LF_ISSET(FS_FORCE | FS_APPEND) &&
+                   ((F_ISSET(ep, F_DEVSET) &&
+                   (sb.st_dev != ep->mdev || sb.st_ino != ep->minode)) ||
+                   sb.st_mtime != ep->mtime)) {
+                       msgq_str(sp, M_ERR, name, LF_ISSET(FS_POSSIBLE) ?
+"250|%s: file modified more recently than this copy; use ! to override" :
+"251|%s: file modified more recently than this copy");
+                       return (1);
+               }
+
+               mtype = OLDFILE;
+       }
+
+       /* Set flags to create, write, and either append or truncate. */
+       oflags = O_CREAT | O_WRONLY |
+           (LF_ISSET(FS_APPEND) ? O_APPEND : O_TRUNC);
+
+       /* Backup the file if requested. */
+       if (!opts_empty(sp, O_BACKUP, 1) &&
+           file_backup(sp, name, O_STR(sp, O_BACKUP)) && !LF_ISSET(FS_FORCE))
+               return (1);
+
+       /* Open the file. */
+       SIGBLOCK;
+       if ((fd = open(name, oflags,
+           S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0) {
+               msgq_str(sp, M_SYSERR, name, "%s");
+               SIGUNBLOCK;
+               return (1);
+       }
+       SIGUNBLOCK;
+
+       /* Try and get a lock. */
+       if (!noname && file_lock(sp, NULL, NULL, fd, 0) == LOCK_UNAVAIL)
+               msgq_str(sp, M_ERR, name,
+                   "252|%s: write lock was unavailable");
+
+#if __linux__
+       /*
+        * XXX
+        * In libc 4.5.x, fdopen(fd, "w") clears the O_APPEND flag (if set).
+        * This bug is fixed in libc 4.6.x.
+        *
+        * This code works around this problem for libc 4.5.x users.
+        * Note that this code is harmless if you're using libc 4.6.x.
+        */
+       if (LF_ISSET(FS_APPEND) && lseek(fd, (off_t)0, SEEK_END) < 0) {
+               msgq(sp, M_SYSERR, "%s", name);
+               return (1);
+       }
+#endif
+
+       /*
+        * Use stdio for buffering.
+        *
+        * XXX
+        * SVR4.2 requires the fdopen mode exactly match the original open
+        * mode, i.e. you have to open with "a" if appending.
+        */
+       if ((fp = fdopen(fd, LF_ISSET(FS_APPEND) ? "a" : "w")) == NULL) {
+               msgq_str(sp, M_SYSERR, name, "%s");
+               (void)close(fd);
+               return (1);
+       }
+
+       /* Build fake addresses, if necessary. */
+       if (fm == NULL) {
+               from.lno = 1;
+               from.cno = 0;
+               fm = &from;
+               if (db_last(sp, &to.lno))
+                       return (1);
+               to.cno = 0;
+               tm = &to;
+       }
+
+       rval = ex_writefp(sp, name, fp, fm, tm, &nlno, &nch, 0);
+
+       /*
+        * Save the new last modification time -- even if the write fails
+        * we re-init the time.  That way the user can clean up the disk
+        * and rewrite without having to force it.
+        */
+       if (noname) {
+               if (stat(name, &sb))
+                       time(&ep->mtime);
+               else {
+                       F_SET(ep, F_DEVSET);
+                       ep->mdev = sb.st_dev;
+                       ep->minode = sb.st_ino;
+
+                       ep->mtime = sb.st_mtime;
+               }
+       }
+
+       /*
+        * If the write failed, complain loudly.  ex_writefp() has already
+        * complained about the actual error, reinforce it if data was lost.
+        */
+       if (rval) {
+               if (!LF_ISSET(FS_APPEND))
+                       msgq_str(sp, M_ERR, name,
+                           "254|%s: WARNING: FILE TRUNCATED");
+               return (1);
+       }
+
+       /*
+        * Once we've actually written the file, it doesn't matter that the
+        * file name was changed -- if it was, we've already whacked it.
+        */
+       F_CLR(frp, FR_NAMECHANGE);
+
+       /*
+        * If wrote the entire file, and it wasn't by appending it to a file,
+        * clear the modified bit.  If the file was written to the original
+        * file name and the file is a temporary, set the "no exit" bit.  This
+        * permits the user to write the file and use it in the context of the
+        * filesystem, but still keeps them from discarding their changes by
+        * exiting.
+        */
+       if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) {
+               F_CLR(ep, F_MODIFIED);
+               if (F_ISSET(frp, FR_TMPFILE)) {
+                       if (noname)
+                               F_SET(frp, FR_TMPEXIT);
+                       else
+                               F_CLR(frp, FR_TMPEXIT);
+               }
+       }
+
+       p = msg_print(sp, name, &nf);
+       switch (mtype) {
+       case NEWFILE:
+               msgstr = msg_cat(sp,
+                   "256|%s: new file: %lu lines, %lu characters", NULL);
+               len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
+               break;
+       case OLDFILE:
+               msgstr = msg_cat(sp, LF_ISSET(FS_APPEND) ?
+                   "315|%s: appended: %lu lines, %lu characters" :
+                   "257|%s: %lu lines, %lu characters", NULL);
+               len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
+               break;
+       default:
+               abort();
+       }
+
+       /*
+        * There's a nasty problem with long path names.  Cscope and tags files
+        * can result in long paths and vi will request a continuation key from
+        * the user.  Unfortunately, the user has typed ahead, and chaos will
+        * result.  If we assume that the characters in the filenames only take
+        * a single screen column each, we can trim the filename.
+        */
+       s = buf;
+       if (len >= sp->cols) {
+               for (s = buf, t = buf + strlen(p); s < t &&
+                   (*s != '/' || len >= sp->cols - 3); ++s, --len);
+               if (s == t)
+                       s = buf;
+               else {
+                       *--s = '.';             /* Leading ellipses. */
+                       *--s = '.';
+                       *--s = '.';
+               }
+       }
+       msgq(sp, M_INFO, "%s", s);
+       if (nf)
+               FREE_SPACE(sp, p, 0);
+       return (0);
+}
+
+/*
+ * file_backup --
+ *     Backup the about-to-be-written file.
+ *
+ * XXX
+ * We do the backup by copying the entire file.  It would be nice to do
+ * a rename instead, but: (1) both files may not fit and we want to fail
+ * before doing the rename; (2) the backup file may not be on the same
+ * disk partition as the file being written; (3) there may be optional
+ * file information (MACs, DACs, whatever) that we won't get right if we
+ * recreate the file.  So, let's not risk it.
+ */
+static int
+file_backup(SCR *sp, const char *name, const char *bname)
+{
+       struct dirent *dp;
+       struct stat sb;
+       DIR *dirp;
+       EXCMD cmd;
+       off_t off;
+       size_t blen;
+       int flags, maxnum, nr, num, nw, rfd, wfd, version;
+       char *bp, *pct, *slash, *t, buf[8192];
+       const char *p, *estr, *wfname;
+       const CHAR_T *wp;
+       size_t wlen;
+       size_t nlen;
+       char *d = NULL;
+
+       rfd = wfd = -1;
+       estr = wfname = NULL;
+       bp = NULL;
+
+       /*
+        * Open the current file for reading.  Do this first, so that
+        * we don't exec a shell before the most likely failure point.
+        * If it doesn't exist, it's okay, there's just nothing to back
+        * up.
+        */
+       errno = 0;
+       if ((rfd = open(name, O_RDONLY, 0)) < 0) {
+               if (errno == ENOENT)
+                       return (0);
+               estr = name;
+               goto err;
+       }
+
+       /*
+        * If the name starts with an 'N' character, add a version number
+        * to the name.  Strip the leading N from the string passed to the
+        * expansion routines, for no particular reason.  It would be nice
+        * to permit users to put the version number anywhere in the backup
+        * name, but there isn't a special character that we can use in the
+        * name, and giving a new character a special meaning leads to ugly
+        * hacks both here and in the supporting ex routines.
+        *
+        * Shell and file name expand the option's value.
+        */
+       ex_cinit(sp, &cmd, 0, 0, 0, 0, 0);
+       if (bname[0] == 'N') {
+               version = 1;
+               ++bname;
+       } else
+               version = 0;
+       CHAR2INT(sp, bname, strlen(bname) + 1, wp, wlen);
+       if (argv_exp2(sp, &cmd, wp, wlen - 1))
+               return (1);
+
+       /*
+        *  0 args: impossible.
+        *  1 args: use it.
+        * >1 args: object, too many args.
+        */
+       if (cmd.argc != 1) {
+               msgq_str(sp, M_ERR, bname,
+                   "258|%s expanded into too many file names");
+               (void)close(rfd);
+               return (1);
+       }
+
+       /*
+        * If appending a version number, read through the directory, looking
+        * for file names that match the name followed by a number.  Make all
+        * of the other % characters in name literal, so the user doesn't get
+        * surprised and sscanf doesn't drop core indirecting through pointers
+        * that don't exist.  If any such files are found, increment its number
+        * by one.
+        */
+       if (version) {
+               GET_SPACE_GOTOC(sp, bp, blen, cmd.argv[0]->len * 2 + 50);
+               INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
+                        p, nlen); 
+               d = strdup(p);
+               p = d;
+               for (t = bp, slash = NULL;
+                    p[0] != '\0'; *t++ = *p++)
+                       if (p[0] == '%') {
+                               if (p[1] != '%')
+                                       *t++ = '%';
+                       } else if (p[0] == '/')
+                               slash = t;
+               pct = t;
+               *t++ = '%';
+               *t++ = 'd';
+               *t = '\0';
+
+               if (slash == NULL) {
+                       dirp = opendir(".");
+                       p = bp;
+               } else {
+                       *slash = '\0';
+                       dirp = opendir(bp);
+                       *slash = '/';
+                       p = slash + 1;
+               }
+               if (dirp == NULL) {
+                       INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
+                               estr, nlen);
+                       goto err;
+               }
+
+               for (maxnum = 0; (dp = readdir(dirp)) != NULL;)
+                       if (sscanf(dp->d_name, p, &num) == 1 && num > maxnum)
+                               maxnum = num;
+               (void)closedir(dirp);
+
+               /* Format the backup file name. */
+               (void)snprintf(pct, blen - (pct - bp), "%d", maxnum + 1);
+               wfname = bp;
+       } else {
+               bp = NULL;
+               INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
+                       wfname, nlen);
+       }
+       
+       /* Open the backup file, avoiding lurkers. */
+       if (stat(wfname, &sb) == 0) {
+               if (!S_ISREG(sb.st_mode)) {
+                       msgq_str(sp, M_ERR, bname,
+                           "259|%s: not a regular file");
+                       goto err;
+               }
+               if (sb.st_uid != getuid()) {
+                       msgq_str(sp, M_ERR, bname, "260|%s: not owned by you");
+                       goto err;
+               }
+               if (sb.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) {
+                       msgq_str(sp, M_ERR, bname,
+                          "261|%s: accessible by a user other than the owner");
+                       goto err;
+               }
+               flags = O_TRUNC;
+       } else
+               flags = O_CREAT | O_EXCL;
+       if ((wfd = open(wfname, flags | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
+               estr = bname;
+               goto err;
+       }
+
+       /* Copy the file's current contents to its backup value. */
+       while ((nr = read(rfd, buf, sizeof(buf))) > 0)
+               for (off = 0; nr != 0; nr -= nw, off += nw)
+                       if ((nw = write(wfd, buf + off, nr)) < 0) {
+                               estr = wfname;
+                               goto err;
+                       }
+       if (nr < 0) {
+               estr = name;
+               goto err;
+       }
+
+       if (close(rfd)) {
+               estr = name;
+               goto err;
+       }
+       if (close(wfd)) {
+               estr = wfname;
+               goto err;
+       }
+       if (bp != NULL)
+               FREE_SPACE(sp, bp, blen);
+       if (d != NULL)
+               free(d);
+       return (0);
+
+alloc_err:
+err:   if (rfd != -1)
+               (void)close(rfd);
+       if (wfd != -1) {
+               (void)unlink(wfname);
+               (void)close(wfd);
+       }
+       if (estr)
+               msgq_str(sp, M_SYSERR, estr, "%s");
+       if (d != NULL)
+               free(d);
+       if (bp != NULL)
+               FREE_SPACE(sp, bp, blen);
+       return (1);
+}
+
+/*
+ * file_comment --
+ *     Skip the first comment.
+ */
+static void
+file_comment(SCR *sp)
+{
+       db_recno_t lno;
+       size_t len;
+       CHAR_T *p;
+
+       for (lno = 1; !db_get(sp, lno, 0, &p, &len) && len == 0; ++lno);
+       if (p == NULL)
+               return;
+       if (p[0] == '#') {
+               F_SET(sp, SC_SCR_TOP);
+               while (!db_get(sp, ++lno, 0, &p, &len))
+                       if (len < 1 || p[0] != '#') {
+                               sp->lno = lno;
+                               return;
+                       }
+       } else if (len > 1 && p[0] == '/' && p[1] == '*') {
+               F_SET(sp, SC_SCR_TOP);
+               do {
+                       for (; len > 1; --len, ++p)
+                               if (p[0] == '*' && p[1] == '/') {
+                                       sp->lno = lno;
+                                       return;
+                               }
+               } while (!db_get(sp, ++lno, 0, &p, &len));
+       } else if (len > 1 && p[0] == '/' && p[1] == '/') {
+               F_SET(sp, SC_SCR_TOP);
+               while (!db_get(sp, ++lno, 0, &p, &len))
+                       if (len < 1 || p[0] != '/' || p[1] != '/') {
+                               sp->lno = lno;
+                               return;
+                       }
+       }
+}
+
+/*
+ * file_m1 --
+ *     First modification check routine.  The :next, :prev, :rewind, :tag,
+ *     :tagpush, :tagpop, ^^ modifications check.
+ *
+ * PUBLIC: int file_m1 __P((SCR *, int, int));
+ */
+int
+file_m1(SCR *sp, int force, int flags)
+{
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /* If no file loaded, return no modifications. */
+       if (ep == NULL)
+               return (0);
+
+       /*
+        * If the file has been modified, we'll want to write it back or
+        * fail.  If autowrite is set, we'll write it back automatically,
+        * unless force is also set.  Otherwise, we fail unless forced or
+        * there's another open screen on this file.
+        */
+       if (F_ISSET(ep, F_MODIFIED)) {
+               if (O_ISSET(sp, O_AUTOWRITE)) {
+                       if (!force && file_aw(sp, flags))
+                               return (1);
+               } else if (ep->refcnt <= 1 && !force) {
+                       msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
+"262|File modified since last complete write; write or use ! to override" :
+"263|File modified since last complete write; write or use :edit! to override");
+                       return (1);
+               }
+       }
+
+       return (file_m3(sp, force));
+}
+
+/*
+ * file_m2 --
+ *     Second modification check routine.  The :edit, :quit, :recover
+ *     modifications check.
+ *
+ * PUBLIC: int file_m2 __P((SCR *, int));
+ */
+int
+file_m2(SCR *sp, int force)
+{
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /* If no file loaded, return no modifications. */
+       if (ep == NULL)
+               return (0);
+
+       /*
+        * If the file has been modified, we'll want to fail, unless forced
+        * or there's another open screen on this file.
+        */
+       if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) {
+               msgq(sp, M_ERR,
+"264|File modified since last complete write; write or use ! to override");
+               return (1);
+       }
+
+       return (file_m3(sp, force));
+}
+
+/*
+ * file_m3 --
+ *     Third modification check routine.
+ *
+ * PUBLIC: int file_m3 __P((SCR *, int));
+ */
+int
+file_m3(SCR *sp, int force)
+{
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /* If no file loaded, return no modifications. */
+       if (ep == NULL)
+               return (0);
+
+       /*
+        * Don't exit while in a temporary files if the file was ever modified.
+        * The problem is that if the user does a ":wq", we write and quit,
+        * unlinking the temporary file.  Not what the user had in mind at all.
+        * We permit writing to temporary files, so that user maps using file
+        * system names work with temporary files.
+        */
+       if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) {
+               msgq(sp, M_ERR,
+                   "265|File is a temporary; exit will discard modifications");
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * file_aw --
+ *     Autowrite routine.  If modified, autowrite is set and the readonly bit
+ *     is not set, write the file.  A routine so there's a place to put the
+ *     comment.
+ *
+ * PUBLIC: int file_aw __P((SCR *, int));
+ */
+int
+file_aw(SCR *sp, int flags)
+{
+       if (!F_ISSET(sp->ep, F_MODIFIED))
+               return (0);
+       if (!O_ISSET(sp, O_AUTOWRITE))
+               return (0);
+
+       /*
+        * !!!
+        * Historic 4BSD vi attempted to write the file if autowrite was set,
+        * regardless of the writeability of the file (as defined by the file
+        * readonly flag).  System V changed this as some point, not attempting
+        * autowrite if the file was readonly.  This feels like a bug fix to
+        * me (e.g. the principle of least surprise is violated if readonly is
+        * set and vi writes the file), so I'm compatible with System V.
+        */
+       if (O_ISSET(sp, O_READONLY)) {
+               msgq(sp, M_INFO,
+                   "266|File readonly, modifications not auto-written");
+               return (1);
+       }
+       return (file_write(sp, NULL, NULL, NULL, flags));
+}
+
+/*
+ * set_alt_name --
+ *     Set the alternate pathname.
+ *
+ * Set the alternate pathname.  It's a routine because I wanted some place
+ * to hang this comment.  The alternate pathname (normally referenced using
+ * the special character '#' during file expansion and in the vi ^^ command)
+ * is set by almost all ex commands that take file names as arguments.  The
+ * rules go something like this:
+ *
+ *    1: If any ex command takes a file name as an argument (except for the
+ *      :next command), the alternate pathname is set to that file name.
+ *      This excludes the command ":e" and ":w !command" as no file name
+ *       was specified.  Note, historically, the :source command did not set
+ *      the alternate pathname.  It does in nvi, for consistency.
+ *
+ *    2: However, if any ex command sets the current pathname, e.g. the
+ *      ":e file" or ":rew" commands succeed, then the alternate pathname
+ *      is set to the previous file's current pathname, if it had one.
+ *      This includes the ":file" command and excludes the ":e" command.
+ *      So, by rule #1 and rule #2, if ":edit foo" fails, the alternate
+ *      pathname will be "foo", if it succeeds, the alternate pathname will
+ *      be the previous current pathname.  The ":e" command will not set
+ *       the alternate or current pathnames regardless.
+ *
+ *    3: However, if it's a read or write command with a file argument and
+ *      the current pathname has not yet been set, the file name becomes
+ *      the current pathname, and the alternate pathname is unchanged.
+ *
+ * If the user edits a temporary file, there may be times when there is no
+ * alternative file name.  A name argument of NULL turns it off.
+ *
+ * PUBLIC: void set_alt_name __P((SCR *, char *));
+ */
+void
+set_alt_name(SCR *sp, const char *name)
+{
+       if (sp->alt_name != NULL)
+               free(sp->alt_name);
+       if (name == NULL)
+               sp->alt_name = NULL;
+       else if ((sp->alt_name = strdup(name)) == NULL)
+               msgq(sp, M_SYSERR, NULL);
+}
+
+/*
+ * file_lock --
+ *     Get an exclusive lock on a file and set close-on-exec flag
+ *
+ * XXX
+ * The default locking is flock(2) style, not fcntl(2).  The latter is
+ * known to fail badly on some systems, and its only advantage is that
+ * it occasionally works over NFS.
+ *
+ * Furthermore, the semantics of fcntl(2) are wrong.  The problems are
+ * two-fold: you can't close any file descriptor associated with the file
+ * without losing all of the locks, and you can't get an exclusive lock
+ * unless you have the file open for writing.  Someone ought to be shot,
+ * but it's probably too late, they may already have reproduced.  To get
+ * around these problems, nvi opens the files for writing when it can and
+ * acquires a second file descriptor when it can't.  The recovery files
+ * are examples of the former, they're always opened for writing.  The DB
+ * files can't be opened for writing because the semantics of DB are that
+ * files opened for writing are flushed back to disk when the DB session
+ * is ended. So, in that case we have to acquire an extra file descriptor.
+ *
+ * PUBLIC: lockr_t file_lock __P((SCR *, char *, int *, int, int));
+ */
+lockr_t
+file_lock(SCR *sp, char *name, int *fdp, int fd, int iswrite)
+{
+       fcntl(fd, F_SETFD, 1);
+
+       if (!O_ISSET(sp, O_LOCKFILES))
+               return (LOCK_SUCCESS);
+       
+#ifdef HAVE_LOCK_FLOCK                 /* Hurrah!  We've got flock(2). */
+       /*
+        * !!!
+        * We need to distinguish a lock not being available for the file
+        * from the file system not supporting locking.  Flock is documented
+        * as returning EWOULDBLOCK; add EAGAIN for good measure, and assume
+        * they are the former.  There's no portable way to do this.
+        */
+       errno = 0;
+       return (flock(fd, LOCK_EX | LOCK_NB) ? errno == EAGAIN
+#ifdef EWOULDBLOCK
+           || errno == EWOULDBLOCK
+#endif
+           ? LOCK_UNAVAIL : LOCK_FAILED : LOCK_SUCCESS);
+#endif
+#ifdef HAVE_LOCK_FCNTL                 /* Gag me.  We've got fcntl(2). */
+{
+       struct flock arg;
+       int didopen, sverrno;
+
+       arg.l_type = F_WRLCK;
+       arg.l_whence = 0;               /* SEEK_SET */
+       arg.l_start = arg.l_len = 0;
+       arg.l_pid = 0;
+
+       /*
+        * If the file descriptor isn't opened for writing, it must fail.
+        * If we fail because we can't get a read/write file descriptor,
+        * we return LOCK_SUCCESS, believing that the file is readonly
+        * and that will be sufficient to warn the user.
+        */
+       if (!iswrite) {
+               if (name == NULL || fdp == NULL)
+                       return (LOCK_FAILED);
+               if ((fd = open(name, O_RDWR, 0)) == -1)
+                       return (LOCK_SUCCESS);
+               *fdp = fd;
+               didopen = 1;
+       }
+
+       errno = 0;
+       if (!fcntl(fd, F_SETLK, &arg))
+               return (LOCK_SUCCESS);
+       if (didopen) {
+               sverrno = errno;
+               (void)close(fd);
+               errno = sverrno;
+       }
+
+       /*
+        * !!!
+        * We need to distinguish a lock not being available for the file
+        * from the file system not supporting locking.  Fcntl is documented
+        * as returning EACCESS and EAGAIN; add EWOULDBLOCK for good measure,
+        * and assume they are the former.  There's no portable way to do this.
+        */
+       return (errno == EACCES || errno == EAGAIN
+#ifdef EWOULDBLOCK
+       || errno == EWOULDBLOCK
+#endif
+       ?  LOCK_UNAVAIL : LOCK_FAILED);
+}
+#endif
+#if !defined(HAVE_LOCK_FLOCK) && !defined(HAVE_LOCK_FCNTL)
+       return (LOCK_SUCCESS);
+#endif
+}
+
+#ifdef USE_DB4_LOGGING
+#define VI_DB_INIT_LOG DB_INIT_LOG
+#else
+#define VI_DB_INIT_LOG 0
+#endif
+
+static int
+db_setup(SCR *sp, EXF *ep)
+{
+       char path[MAXPATHLEN];
+       int fd;
+       DB_ENV  *env;
+
+       (void)snprintf(path, sizeof(path), "%s/vi.XXXXXX", O_STR(sp, O_RECDIR));
+       if ((fd = mkstemp(path)) == -1) {
+               msgq(sp, M_SYSERR, "%s", path);
+               goto err;
+       }
+       (void)close(fd);
+       (void)unlink(path);
+       if (mkdir(path, S_IRWXU)) {
+               msgq(sp, M_SYSERR, "%s", path);
+               goto err;
+       }
+       if (db_env_create(&env, 0)) {
+               msgq(sp, M_ERR, "env_create");
+               goto err;
+       }
+#ifdef USE_DB4_LOGGING
+       if ((sp->db_error = vi_db_init_recover(env))) {
+               msgq(sp, M_DBERR, "init_recover");
+               goto err;
+       }
+       if ((sp->db_error = __vi_init_recover(env))) {
+               msgq(sp, M_DBERR, "init_recover");
+               goto err;
+       }
+#endif
+       if ((sp->db_error = db_env_open(env, path, 
+           DB_PRIVATE | DB_CREATE | DB_INIT_MPOOL | VI_DB_THREAD 
+           | VI_DB_INIT_LOG, 0)) != 0) {
+               msgq(sp, M_DBERR, "env->open");
+               goto err;
+       }
+
+       if ((ep->env_path = strdup(path)) == NULL) {
+               msgq(sp, M_SYSERR, NULL);
+               (void)rmdir(path);
+               goto err;
+       }
+       ep->env = env;
+       return 0;
+err:
+       return 1;
+}
diff --git a/dist/nvi/common/exf.h b/dist/nvi/common/exf.h
new file mode 100644 (file)
index 0000000..7d5b41d
--- /dev/null
@@ -0,0 +1,92 @@
+/*     $NetBSD: exf.h,v 1.1.1.2 2008/05/18 14:29:45 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: exf.h,v 10.19 2002/03/02 23:36:23 skimo Exp (Berkeley) Date: 2002/03/02 23:36:23
+ */
+                                       /* Undo direction. */
+/*
+ * exf --
+ *     The file structure.
+ */
+struct _exf {
+       CIRCLEQ_ENTRY(_exf) q;          /* Linked list of file structures. */
+       int      refcnt;                /* Reference count. */
+
+       CIRCLEQ_HEAD(_escrh, _scr)   scrq;   /* Attached screens */
+                                       /* Underlying database state. */
+       DB_ENV  *env;                   /* The DB environment. */
+       char    *env_path;              /* DB environment directory. */
+       DB      *db;                    /* File db structure. */
+       db_recno_t       c_nlines;      /* Cached lines in the file. */
+
+       DB      *log;                   /* Log db structure. */
+       db_recno_t       l_high;        /* Log last + 1 record number. */
+       db_recno_t       l_cur;         /* Log current record number. */
+#ifdef USE_DB4_LOGGING
+       DB_LSN  lsn_first;
+       DB_LSN  lsn_high;               /* LSN of last record. */
+       DB_LSN  lsn_cur;                /* LSN of first record to undo. */
+#endif
+       MARK     l_cursor;              /* Log cursor position. */
+       dir_t    lundo;                 /* Last undo direction. */
+       WIN     *l_win;                 /* Window owning transaction. */
+
+       LIST_HEAD(_markh, _lmark) marks;/* Linked list of file MARK's. */
+
+       /*
+        * XXX
+        * Mtime should be a struct timespec, but time_t is more portable.
+        */
+       dev_t    mdev;                  /* Device. */
+       ino_t    minode;                /* Inode. */
+       time_t   mtime;                 /* Last modification time. */
+
+       int      fcntl_fd;              /* Fcntl locking fd; see exf.c. */
+       int      fd;                    /* File descriptor */
+
+       /*
+        * Recovery in general, and these fields specifically, are described
+        * in recover.c.
+        */
+#define        RCV_PERIOD      120             /* Sync every two minutes. */
+       char    *rcv_path;              /* Recover file name. */
+       char    *rcv_mpath;             /* Recover mail file name. */
+       int      rcv_fd;                /* Locked mail file descriptor. */
+
+       void    *lock;                  /* Lock for log. */
+
+#define        F_DEVSET        0x001           /* mdev/minode fields initialized. */
+#define        F_FIRSTMODIFY   0x002           /* File not yet modified. */
+#define        F_MODIFIED      0x004           /* File is currently dirty. */
+#define        F_MULTILOCK     0x008           /* Multiple processes running, lock. */
+#define        F_NOLOG         0x010           /* Logging turned off. */
+#define        F_RCV_NORM      0x020           /* Don't delete recovery files. */
+#define        F_RCV_ON        0x040           /* Recovery is possible. */
+#define        F_UNDO          0x080           /* No change since last undo. */
+       u_int8_t flags;
+};
+
+/* Flags to db_get(). */
+#define        DBG_FATAL       0x001   /* If DNE, error message. */
+#define        DBG_NOCACHE     0x002   /* Ignore the front-end cache. */
+
+/* Flags to file_init() and file_write(). */
+#define        FS_ALL          0x001   /* Write the entire file. */
+#define        FS_APPEND       0x002   /* Append to the file. */
+#define        FS_FORCE        0x004   /* Force is set. */
+#define        FS_OPENERR      0x008   /* Open failed, try it again. */
+#define        FS_POSSIBLE     0x010   /* Force could have been set. */
+#define        FS_SETALT       0x020   /* Set alternate file name. */
+
+/* Flags to rcv_sync(). */
+#define        RCV_EMAIL       0x01    /* Send the user email, IFF file modified. */
+#define        RCV_ENDSESSION  0x02    /* End the file session. */
+#define        RCV_PRESERVE    0x04    /* Preserve backup file, IFF file modified. */
+#define        RCV_SNAPSHOT    0x08    /* Snapshot the recovery, and send email. */
diff --git a/dist/nvi/common/extern.h b/dist/nvi/common/extern.h
new file mode 100644 (file)
index 0000000..b65e0b4
--- /dev/null
@@ -0,0 +1,218 @@
+/*     $NetBSD: extern.h,v 1.5 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+SCR *api_fscreen __P((int, char *));
+int api_aline __P((SCR *, db_recno_t, char *, size_t));
+int api_extend __P((SCR *, db_recno_t));
+int api_dline __P((SCR *, db_recno_t));
+int api_gline __P((SCR *, db_recno_t, CHAR_T **, size_t *));
+int api_iline __P((SCR *, db_recno_t, CHAR_T *, size_t));
+int api_lline __P((SCR *, db_recno_t *));
+int api_sline __P((SCR *, db_recno_t, CHAR_T *, size_t));
+int api_getmark __P((SCR *, int, MARK *));
+int api_setmark __P((SCR *, int, MARK *));
+int api_nextmark __P((SCR *, int, char *));
+int api_getcursor __P((SCR *, MARK *));
+int api_setcursor __P((SCR *, MARK *));
+void api_emessage __P((SCR *, char *));
+void api_imessage __P((SCR *, char *));
+int api_edit __P((SCR *, char *, SCR **, int));
+int api_escreen __P((SCR *));
+int api_swscreen __P((SCR *, SCR *));
+int api_map __P((SCR *, char *, char *, size_t));
+int api_unmap __P((SCR *, char *));
+int api_opts_get __P((SCR *, const CHAR_T *, char **, int *));
+int api_opts_set __P((SCR *, const CHAR_T *, const char *, u_long, int));
+int api_run_str __P((SCR *, char *));
+TAGQ * api_tagq_new __P((SCR*, char*));
+void api_tagq_add __P((SCR*, TAGQ*, char*, char *, char *));
+int api_tagq_push __P((SCR*, TAGQ**));
+void api_tagq_free __P((SCR*, TAGQ*));
+int cut __P((SCR *, ARG_CHAR_T *, MARK *, MARK *, int));
+int cut_line __P((SCR *, db_recno_t, size_t, size_t, CB *));
+void cut_close __P((WIN *));
+TEXT *text_init __P((SCR *, const CHAR_T *, size_t, size_t));
+void text_lfree __P((TEXTH *));
+void text_free __P((TEXT *));
+int db_eget __P((SCR *, db_recno_t, CHAR_T **, size_t *, int *));
+int db_get __P((SCR *, db_recno_t, u_int32_t, CHAR_T **, size_t *));
+int db_delete __P((SCR *, db_recno_t));
+int db_append __P((SCR *, int, db_recno_t, const CHAR_T *, size_t));
+int db_insert __P((SCR *, db_recno_t, CHAR_T *, size_t));
+int db_set __P((SCR *, db_recno_t, CHAR_T *, size_t));
+int db_exist __P((SCR *, db_recno_t));
+int db_last __P((SCR *, db_recno_t *));
+void db_err __P((SCR *, db_recno_t));
+int scr_update __P((SCR *sp, db_recno_t lno, 
+                       lnop_t op, int current));
+void update_cache __P((SCR *sp, lnop_t op, db_recno_t lno));
+int line_insdel __P((SCR *sp, lnop_t op, db_recno_t lno));
+int del __P((SCR *, MARK *, MARK *, int));
+FREF *file_add __P((SCR *, const char *));
+int file_init __P((SCR *, FREF *, char *, int));
+int file_end __P((SCR *, EXF *, int));
+int file_write __P((SCR *, MARK *, MARK *, char *, int));
+int file_m1 __P((SCR *, int, int));
+int file_m2 __P((SCR *, int));
+int file_m3 __P((SCR *, int));
+int file_aw __P((SCR *, int));
+void set_alt_name __P((SCR *, const char *));
+lockr_t file_lock __P((SCR *, char *, int *, int, int));
+GS * gs_init __P((char*));
+WIN * gs_new_win __P((GS *gp));
+int win_end __P((WIN *wp));
+void gs_end __P((GS *));
+int v_key_init __P((SCR *));
+void v_key_ilookup __P((SCR *));
+size_t v_key_len __P((SCR *, ARG_CHAR_T));
+u_char *v_key_name __P((SCR *, ARG_CHAR_T));
+e_key_t v_key_val __P((SCR *, ARG_CHAR_T));
+int v_event_push __P((SCR *, EVENT *, const CHAR_T *, size_t, u_int));
+int v_event_get __P((SCR *, EVENT *, int, u_int32_t));
+void v_event_err __P((SCR *, EVENT *));
+int v_event_flush __P((SCR *, u_int));
+int log_init __P((SCR *, EXF *));
+int log_end __P((SCR *, EXF *));
+int log_cursor __P((SCR *));
+int log_line __P((SCR *, db_recno_t, u_int));
+int log_mark __P((SCR *, LMARK *));
+int log_backward __P((SCR *, MARK *));
+int log_setline __P((SCR *));
+int log_forward __P((SCR *, MARK *));
+int log_init __P((SCR *, EXF *));
+int log_end __P((SCR *, EXF *));
+int log_cursor __P((SCR *));
+int log_line __P((SCR *, db_recno_t, u_int));
+int log_mark __P((SCR *, LMARK *));
+int log_backward __P((SCR *, MARK *));
+int log_setline __P((SCR *));
+int log_forward __P((SCR *, MARK *));
+int editor __P((WIN *, int, char *[]));
+int mark_init __P((SCR *, EXF *));
+int mark_end __P((SCR *, EXF *));
+int mark_get __P((SCR *, ARG_CHAR_T, MARK *, mtype_t));
+int mark_set __P((SCR *, ARG_CHAR_T, MARK *, int));
+int mark_insdel __P((SCR *, lnop_t, db_recno_t));
+void msgq __P((SCR *, mtype_t, const char *, ...))
+    __attribute__((__format__(__printf__, 3, 4)));
+void msgq_wstr __P((SCR *, mtype_t, const CHAR_T *, const char *));
+void msgq_str __P((SCR *, mtype_t, const char *, const char *));
+void mod_rpt __P((SCR *));
+void msgq_status __P((SCR *, db_recno_t, u_int));
+int msg_open __P((SCR *, const char *));
+void msg_close __P((GS *));
+const char *msg_cmsg __P((SCR *, cmsg_t, size_t *));
+const char *msg_cat __P((SCR *, const char *, size_t *));
+char *msg_print __P((SCR *, const char *, int *));
+void thread_init __P((GS *gp));
+int opts_init __P((SCR *, int *));
+int opts_set __P((SCR *, ARGS *[], const char *));
+int o_set __P((SCR *, int, u_int, const char *, u_long));
+int opts_empty __P((SCR *, int, int));
+void opts_dump __P((SCR *, enum optdisp));
+int opts_save __P((SCR *, FILE *));
+OPTLIST const *opts_search __P((const CHAR_T *));
+void opts_nomatch __P((SCR *, const CHAR_T *));
+int opts_copy __P((SCR *, SCR *));
+void opts_free __P((SCR *));
+int f_altwerase __P((SCR *, OPTION *, const char *, u_long *));
+int f_columns __P((SCR *, OPTION *, const char *, u_long *));
+int f_lines __P((SCR *, OPTION *, const char *, u_long *));
+int f_lisp __P((SCR *, OPTION *, const char *, u_long *));
+int f_msgcat __P((SCR *, OPTION *, const char *, u_long *));
+int f_paragraph __P((SCR *, OPTION *, const char *, u_long *));
+int f_print __P((SCR *, OPTION *, const char *, u_long *));
+int f_readonly __P((SCR *, OPTION *, const char *, u_long *));
+int f_recompile __P((SCR *, OPTION *, const char *, u_long *));
+int f_reformat __P((SCR *, OPTION *, const char *, u_long *));
+int f_section __P((SCR *, OPTION *, const char *, u_long *));
+int f_ttywerase __P((SCR *, OPTION *, const char *, u_long *));
+int f_w300 __P((SCR *, OPTION *, const char *, u_long *));
+int f_w1200 __P((SCR *, OPTION *, const char *, u_long *));
+int f_w9600 __P((SCR *, OPTION *, const char *, u_long *));
+int f_window __P((SCR *, OPTION *, const char *, u_long *));
+int f_encoding __P((SCR *, OPTION *, const char *, u_long *));
+void thread_init __P((GS *gp));
+int put __P((SCR *, CB *, ARG_CHAR_T *, MARK *, MARK *, int));
+int rcv_tmp __P((SCR *, EXF *, char *));
+int rcv_init __P((SCR *));
+int rcv_sync __P((SCR *, u_int));
+int rcv_list __P((SCR *));
+int rcv_read __P((SCR *, FREF *));
+int screen_init __P((GS *, SCR *, SCR **));
+int screen_end __P((SCR *));
+SCR *screen_next __P((SCR *));
+int f_search __P((SCR *,
+   MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int));
+int b_search __P((SCR *,
+   MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int));
+void search_busy __P((SCR *, busy_t));
+int seq_set __P((SCR *, CHAR_T *,
+   size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int));
+int seq_delete __P((SCR *, CHAR_T *, size_t, seq_t));
+int seq_mdel __P((SEQ *));
+SEQ *seq_find
+   __P((SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *));
+void seq_close __P((GS *));
+int seq_dump __P((SCR *, seq_t, int));
+int seq_save __P((SCR *, FILE *, const char *, seq_t));
+int e_memcmp __P((CHAR_T *, EVENT *, size_t));
+void vtrace_end __P((void));
+void vtrace_init __P((char *));
+void vtrace __P((const char *, ...))
+    __attribute__((__format__(__printf__, 1, 2)));
+void *binc __P((SCR *, void *, size_t *, size_t));
+int nonblank __P((SCR *, db_recno_t, size_t *));
+const char *tail __P((const char *));
+char *v_strdup __P((SCR *, const char *, size_t));
+CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t));
+enum nresult nget_uslong __P((SCR *, u_long *, const CHAR_T *, CHAR_T **, int));
+enum nresult nget_slong __P((SCR *, long *, const CHAR_T *, CHAR_T **, int));
+#ifdef USE_DB4_LOGGING
+int __vi_marker_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+     u_int32_t));
+int __vi_marker_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_marker_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_marker_read __P((DB_ENV *, void *, __vi_marker_args **));
+int __vi_cursor_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+     u_int32_t, db_recno_t, size_t));
+int __vi_cursor_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_cursor_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_cursor_read __P((DB_ENV *, void *, __vi_cursor_args **));
+int __vi_mark_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+     LMARK *));
+int __vi_mark_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_mark_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_mark_read __P((DB_ENV *, void *, __vi_mark_args **));
+int __vi_change_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+     u_int32_t, db_recno_t));
+int __vi_change_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_change_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+     void *));
+int __vi_change_read __P((DB_ENV *, void *, __vi_change_args **));
+int __vi_init_print __P((DB_ENV *, int (***)(DB_ENV *, DBT *,
+     DB_LSN *, db_recops, void *), size_t *));
+int __vi_init_getpgnos __P((DB_ENV *, int (***)(DB_ENV *, DBT *,
+     DB_LSN *, db_recops, void *), size_t *));
+int __vi_init_recover __P((DB_ENV *));
+#endif
+#ifdef USE_DB4_LOGGING
+int __vi_marker_recover
+  __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+int __vi_cursor_recover
+  __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+int __vi_mark_recover
+  __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+int __vi_change_recover
+  __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+int __vi_log_truncate __P((EXF *ep));
+int __vi_log_dispatch __P((DB_ENV *dbenv, DBT *data, DB_LSN *lsn, db_recops ops));
+int __vi_log_traverse __P((SCR *sp, undo_t undo, MARK *));
+#endif
diff --git a/dist/nvi/common/gs.c b/dist/nvi/common/gs.c
new file mode 100644 (file)
index 0000000..3e3bb46
--- /dev/null
@@ -0,0 +1,218 @@
+/*     $NetBSD: gs.c,v 1.2 2011/09/16 16:13:41 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2000
+ *     Sven Verdoolaege.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../perl_api/extern.h"
+
+__dead static void        perr __P((char *, char *));
+
+/*
+ * gs_init --
+ *     Create and partially initialize the GS structure.
+ * PUBLIC: GS * gs_init __P((char*));
+ */
+GS *
+gs_init(char *name)
+{
+       GS *gp;
+       char *p;
+
+       /* Figure out what our name is. */
+       if ((p = strrchr(name, '/')) != NULL)
+               name = p + 1;
+
+       /* Allocate the global structure. */
+       CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS));
+       if (gp == NULL)
+               perr(name, NULL);
+
+       gp->progname = name;
+
+       /* Common global structure initialization. */
+       /* others will need to be copied from main.c */
+       CIRCLEQ_INIT(&gp->dq);
+
+       CIRCLEQ_INIT(&gp->hq);
+       gp->noprint = DEFAULT_NOPRINT;
+
+       /* Structures shared by screens so stored in the GS structure. */
+       CIRCLEQ_INIT(&gp->frefq);
+       CIRCLEQ_INIT(&gp->exfq);
+       LIST_INIT(&gp->seqq);
+
+       thread_init(gp);
+
+       return (gp);
+}
+
+/*
+ * gs_new_win
+ *     Create new window
+ * PUBLIC: WIN * gs_new_win __P((GS *gp));
+ */
+
+WIN *
+gs_new_win(GS *gp)
+{
+       WIN *wp;
+
+       CALLOC_NOMSG(NULL, wp, WIN *, 1, sizeof(*wp));
+       if (!wp)
+               return NULL;
+
+       /* Common global structure initialization. */
+       LIST_INIT(&wp->ecq);
+       LIST_INSERT_HEAD(&wp->ecq, &wp->excmd, q);
+
+       CIRCLEQ_INSERT_TAIL(&gp->dq, wp, q);
+       CIRCLEQ_INIT(&wp->scrq);
+
+       CIRCLEQ_INIT(&wp->dcb_store.textq);
+       LIST_INIT(&wp->cutq);
+
+       wp->gp = gp;
+
+       return wp;
+}
+
+/*
+ * win_end --
+ *     Remove window.
+ *
+ * PUBLIC: int win_end __P((WIN *wp));
+ */
+int
+win_end(WIN *wp)
+{
+       SCR *sp;
+
+       CIRCLEQ_REMOVE(&wp->gp->dq, wp, q);
+
+       if (wp->ccl_sp != NULL) {
+               (void)file_end(wp->ccl_sp, NULL, 1);
+               (void)screen_end(wp->ccl_sp);
+       }
+       while ((sp = wp->scrq.cqh_first) != (void *)&wp->scrq)
+               (void)screen_end(sp);
+
+       /* Free key input queue. */
+       if (wp->i_event != NULL)
+               free(wp->i_event);
+
+       /* Free cut buffers. */
+       cut_close(wp);
+
+       /* Free default buffer storage. */
+       (void)text_lfree(&wp->dcb_store.textq);
+
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+       /* Free any temporary space. */
+       if (wp->tmp_bp != NULL)
+               free(wp->tmp_bp);
+#endif
+
+       return 0;
+}
+
+/*
+ * gs_end --
+ *     End the program, discarding screens and most of the global area.
+ *
+ * PUBLIC: void gs_end __P((GS *));
+ */
+void
+gs_end(GS *gp)
+{
+       MSGS *mp;
+       SCR *sp;
+       WIN *wp;
+
+       /* If there are any remaining screens, kill them off. */
+       while ((wp = gp->dq.cqh_first) != (void *)&gp->dq)
+               (void)win_end(wp);
+       while ((sp = gp->hq.cqh_first) != (void *)&gp->hq)
+               (void)screen_end(sp);
+
+#ifdef HAVE_PERL_INTERP
+       perl_end(gp);
+#endif
+
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+       { FREF *frp;
+               /* Free FREF's. */
+               while ((frp = gp->frefq.cqh_first) != (FREF *)&gp->frefq) {
+                       CIRCLEQ_REMOVE(&gp->frefq, frp, q);
+                       if (frp->name != NULL)
+                               free(frp->name);
+                       if (frp->tname != NULL)
+                               free(frp->tname);
+                       free(frp);
+               }
+       }
+
+       /* Free map sequences. */
+       seq_close(gp);
+
+       /* Close message catalogs. */
+       msg_close(gp);
+#endif
+
+       /* Ring the bell if scheduled. */
+       if (F_ISSET(gp, G_BELLSCHED))
+               (void)fprintf(stderr, "\07");           /* \a */
+
+       /*
+        * Flush any remaining messages.  If a message is here, it's almost
+        * certainly the message about the event that killed us (although
+        * it's possible that the user is sourcing a file that exits from the
+        * editor).
+        */
+       while ((mp = gp->msgq.lh_first) != NULL) {
+               (void)fprintf(stderr, "%s%.*s",
+                   mp->mtype == M_ERR ? "ex/vi: " : "", (int)mp->len, mp->buf);
+               LIST_REMOVE(mp, q);
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+               free(mp->buf);
+               free(mp);
+#endif
+       }
+
+#if defined(TRACE)
+       /* Close tracing file descriptor. */
+       vtrace_end();
+#endif
+}
+
+
+/*
+ * perr --
+ *     Print system error.
+ */
+static void
+perr(char *name, char *msg)
+{
+       (void)fprintf(stderr, "%s:", name);
+       if (msg != NULL)
+               (void)fprintf(stderr, "%s:", msg);
+       (void)fprintf(stderr, "%s\n", strerror(errno));
+       exit(1);
+}
diff --git a/dist/nvi/common/gs.h b/dist/nvi/common/gs.h
new file mode 100644 (file)
index 0000000..3198eaf
--- /dev/null
@@ -0,0 +1,212 @@
+/*     $NetBSD: gs.h,v 1.5 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: gs.h,v 10.55 2001/11/01 10:28:25 skimo Exp (Berkeley) Date: 2001/11/01 10:28:25
+ */
+
+#define        TEMPORARY_FILE_STRING   "/tmp"  /* Default temporary file name. */
+
+/*
+ * File reference structure (FREF).  The structure contains the name of the
+ * file, along with the information that follows the name.
+ *
+ * !!!
+ * The read-only bit follows the file name, not the file itself.
+ */
+struct _fref {
+       CIRCLEQ_ENTRY(_fref) q;         /* Linked list of file references. */
+       char    *name;                  /* File name. */
+       char    *tname;                 /* Backing temporary file name. */
+
+       db_recno_t       lno;                   /* 1-N: file cursor line. */
+       size_t   cno;                   /* 0-N: file cursor column. */
+
+#define        FR_CURSORSET    0x0001          /* If lno/cno values valid. */
+#define        FR_DONTDELETE   0x0002          /* Don't delete the temporary file. */
+#define        FR_EXNAMED      0x0004          /* Read/write renamed the file. */
+#define        FR_NAMECHANGE   0x0008          /* If the name changed. */
+#define        FR_NEWFILE      0x0010          /* File doesn't really exist yet. */
+#define        FR_RECOVER      0x0020          /* File is being recovered. */
+#define        FR_TMPEXIT      0x0040          /* Modified temporary file, no exit. */
+#define        FR_TMPFILE      0x0080          /* If file has no name. */
+#define        FR_UNLOCKED     0x0100          /* File couldn't be locked. */
+       u_int16_t flags;
+};
+
+/* Action arguments to scr_exadjust(). */
+typedef enum { EX_TERM_CE, EX_TERM_SCROLL } exadj_t;
+
+/* Screen attribute arguments to scr_attr(). */
+typedef enum { SA_ALTERNATE, SA_INVERSE } scr_attr_t;
+
+/* Key type arguments to scr_keyval(). */
+typedef enum { KEY_VEOF, KEY_VERASE, KEY_VKILL, KEY_VWERASE } scr_keyval_t;
+
+/*
+ * GS:
+ *
+ * Structure that describes global state of the running program.
+ */
+struct _gs {
+       char    *progname;              /* Programe name. */
+
+       int      id;                    /* Last allocated screen id. */
+       CIRCLEQ_HEAD(_dqh, _win) dq;    /* Displayed windows. */
+       CIRCLEQ_HEAD(_hqh, _scr) hq;    /* Hidden screens. */
+
+       void    *perl_interp;           /* Perl interpreter. */
+       void    *tcl_interp;            /* Tcl_Interp *: Tcl interpreter. */
+
+       void    *cl_private;            /* Curses support private area. */
+       void    *tk_private;            /* Tk/Tcl support private area. */
+
+                                       /* File references. */
+       CIRCLEQ_HEAD(_frefh, _fref) frefq;
+                                       /* File structures. */
+       CIRCLEQ_HEAD(_exfh, _exf) exfq;
+
+#define        GO_COLUMNS      0               /* Global options: columns. */
+#define        GO_LINES        1               /* Global options: lines. */
+#define        GO_SECURE       2               /* Global options: secure. */
+#define        GO_TERM         3               /* Global options: terminal type. */
+       OPTION   opts[GO_TERM + 1];
+
+       DB      *msg;                   /* Message catalog DB. */
+       MSGH     msgq;                  /* User message list. */
+#define        DEFAULT_NOPRINT '\1'            /* Emergency non-printable character. */
+       int      noprint;               /* Cached, unprintable character. */
+
+       char    *c_option;              /* Ex initial, command-line command. */
+
+#ifdef DEBUG
+       FILE    *tracefp;               /* Trace file pointer. */
+#endif
+
+#define        MAX_BIT_SEQ     0x7f            /* Max + 1 fast check character. */
+       LIST_HEAD(_seqh, _seq) seqq;    /* Linked list of maps, abbrevs. */
+       bitstr_t bit_decl(seqb, MAX_BIT_SEQ + 1);
+
+#define        MAX_FAST_KEY    0xff            /* Max fast check character.*/
+#define        KEY_LEN(sp, ch)                                                 \
+       (((ch) & ~MAX_FAST_KEY) == 0 ?                                  \
+           sp->gp->cname[(unsigned char)ch].len : v_key_len(sp, ch))
+#define        KEY_NAME(sp, ch)                                                \
+       (((ch) & ~MAX_FAST_KEY) == 0 ?                                  \
+           sp->gp->cname[(unsigned char)ch].name : v_key_name(sp, ch))
+       struct {
+               u_char   name[MAX_CHARACTER_COLUMNS + 1];
+               u_int8_t len;
+       } cname[MAX_FAST_KEY + 1];      /* Fast lookup table. */
+
+#define        KEY_VAL(sp, ch)                                                 \
+       (((ch) & ~MAX_FAST_KEY) == 0 ?                                  \
+           sp->gp->special_key[(unsigned char)ch] : v_key_val(sp,ch))
+       e_key_t                         /* Fast lookup table. */
+           special_key[MAX_FAST_KEY + 1];
+
+/* Flags. */
+#define        G_ABBREV        0x0001          /* If have abbreviations. */
+#define        G_BELLSCHED     0x0002          /* Bell scheduled. */
+#define        G_INTERRUPTED   0x0004          /* Interrupted. */
+#define        G_RECOVER_SET   0x0008          /* Recover system initialized. */
+#define        G_SCRIPTED      0x0010          /* Ex script session. */
+#define        G_SCRWIN        0x0020          /* Scripting windows running. */
+#define        G_SNAPSHOT      0x0040          /* Always snapshot files. */
+#define        G_SRESTART      0x0080          /* Screen restarted. */
+       u_int32_t flags;
+
+       /* Screen interface functions. */
+                                       /* Add a string to the screen. */
+       int     (*scr_addstr) __P((SCR *, const char *, size_t));
+                                       /* Add a string to the screen. */
+       int     (*scr_waddstr) __P((SCR *, const CHAR_T *, size_t));
+                                       /* Toggle a screen attribute. */
+       int     (*scr_attr) __P((SCR *, scr_attr_t, int));
+                                       /* Terminal baud rate. */
+       int     (*scr_baud) __P((SCR *, u_long *));
+                                       /* Beep/bell/flash the terminal. */
+       int     (*scr_bell) __P((SCR *));
+                                       /* Display a busy message. */
+       void    (*scr_busy) __P((SCR *, const char *, busy_t));
+                                       /* Prepare child. */
+       int     (*scr_child) __P((SCR *));
+                                       /* Clear to the end of the line. */
+       int     (*scr_clrtoeol) __P((SCR *));
+                                       /* Return the cursor location. */
+       int     (*scr_cursor) __P((SCR *, size_t *, size_t *));
+                                       /* Delete a line. */
+       int     (*scr_deleteln) __P((SCR *));
+                                       /* Discard a screen. */
+       int     (*scr_discard) __P((SCR *, SCR **));
+                                       /* Get a keyboard event. */
+       int     (*scr_event) __P((SCR *, EVENT *, u_int32_t, int));
+                                       /* Ex: screen adjustment routine. */
+       int     (*scr_ex_adjust) __P((SCR *, exadj_t));
+       int     (*scr_fmap)             /* Set a function key. */
+           __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+                                       /* Get terminal key value. */
+       int     (*scr_keyval) __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+                                       /* Insert a line. */
+       int     (*scr_insertln) __P((SCR *));
+                                       /* Handle an option change. */
+       int     (*scr_optchange) __P((SCR *, int, const char *, u_long *));
+                                       /* Move the cursor. */
+       int     (*scr_move) __P((SCR *, size_t, size_t));
+                                       /* Refresh the screen. */
+       int     (*scr_refresh) __P((SCR *, int));
+                                       /* Rename the file. */
+       int     (*scr_rename) __P((SCR *, char *, int));
+                                       /* Reply to an event. */
+       int     (*scr_reply) __P((SCR *, int, char *));
+                                       /* Set the screen type. */
+       int     (*scr_screen) __P((SCR *, u_int32_t));
+                                       /* Split the screen. */
+       int     (*scr_split) __P((SCR *, SCR *));
+                                       /* Suspend the editor. */
+       int     (*scr_suspend) __P((SCR *, int *));
+                                       /* Print usage message. */
+       void    (*scr_usage) __P((void));
+
+       /* Threading stuff */
+       void    *th_private;
+
+       int     (*run) __P((WIN *, void *(*)(void*), void *));
+
+       int     (*lock_init) __P((WIN *, void **));
+#define LOCK_INIT(wp,s)                                                            \
+       wp->gp->lock_init(wp, &s->lock)
+       int     (*lock_try) __P((WIN *, void **));
+#define LOCK_TRY(wp,s)                                                     \
+       wp->gp->lock_try(wp, &s->lock)
+       int     (*lock_unlock) __P((WIN *, void **));
+#define LOCK_UNLOCK(wp,s)                                                  \
+       wp->gp->lock_unlock(wp, &s->lock)
+       int     (*lock_end) __P((WIN *, void **));
+#define LOCK_END(wp,s)                                                     \
+       wp->gp->lock_end(wp, &s->lock)
+};
+
+/*
+ * XXX
+ * Block signals if there are asynchronous events.  Used to keep DB system calls
+ * from being interrupted and not restarted, as that will result in consistency
+ * problems.  This should be handled by DB.
+ */
+#ifdef BLOCK_SIGNALS
+#include <signal.h>
+extern sigset_t        __sigblockset;
+#define        SIGBLOCK \
+       (void)sigprocmask(SIG_BLOCK, &__sigblockset, NULL)
+#define        SIGUNBLOCK \
+       (void)sigprocmask(SIG_UNBLOCK, &__sigblockset, NULL);
+#else
+#define        SIGBLOCK
+#define        SIGUNBLOCK
+#endif
diff --git a/dist/nvi/common/key.c b/dist/nvi/common/key.c
new file mode 100644 (file)
index 0000000..249ea11
--- /dev/null
@@ -0,0 +1,844 @@
+/*     $NetBSD: key.c,v 1.6 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: key.c,v 10.48 2001/06/25 15:19:10 skimo Exp (Berkeley) Date: 2001/06/25 15:19:10";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+
+static int     v_event_append __P((SCR *, EVENT *));
+static int     v_event_grow __P((SCR *, int));
+static int     v_key_cmp __P((const void *, const void *));
+static void    v_keyval __P((SCR *, int, scr_keyval_t));
+static void    v_sync __P((SCR *, int));
+
+/*
+ * !!!
+ * Historic vi always used:
+ *
+ *     ^D: autoindent deletion
+ *     ^H: last character deletion
+ *     ^W: last word deletion
+ *     ^Q: quote the next character (if not used in flow control).
+ *     ^V: quote the next character
+ *
+ * regardless of the user's choices for these characters.  The user's erase
+ * and kill characters worked in addition to these characters.  Nvi wires
+ * down the above characters, but in addition permits the VEOF, VERASE, VKILL
+ * and VWERASE characters described by the user's termios structure.
+ *
+ * Ex was not consistent with this scheme, as it historically ran in tty
+ * cooked mode.  This meant that the scroll command and autoindent erase
+ * characters were mapped to the user's EOF character, and the character
+ * and word deletion characters were the user's tty character and word
+ * deletion characters.  This implementation makes it all consistent, as
+ * described above for vi.
+ *
+ * !!!
+ * This means that all screens share a special key set.
+ */
+KEYLIST keylist[] = {
+       {K_BACKSLASH,     '\\'},        /*  \ */
+       {K_CARAT,          '^'},        /*  ^ */
+       {K_CNTRLD,      '\004'},        /* ^D */
+       {K_CNTRLR,      '\022'},        /* ^R */
+       {K_CNTRLT,      '\024'},        /* ^T */
+       {K_CNTRLZ,      '\032'},        /* ^Z */
+       {K_COLON,          ':'},        /*  : */
+       {K_CR,            '\r'},        /* \r */
+       {K_ESCAPE,      '\033'},        /* ^[ */
+       {K_FORMFEED,      '\f'},        /* \f */
+       {K_HEXCHAR,     '\030'},        /* ^X */
+       {K_NL,            '\n'},        /* \n */
+       {K_RIGHTBRACE,     '}'},        /*  } */
+       {K_RIGHTPAREN,     ')'},        /*  ) */
+       {K_TAB,           '\t'},        /* \t */
+       {K_VERASE,        '\b'},        /* \b */
+       {K_VKILL,       '\025'},        /* ^U */
+       {K_VLNEXT,      '\021'},        /* ^Q */
+       {K_VLNEXT,      '\026'},        /* ^V */
+       {K_VWERASE,     '\027'},        /* ^W */
+       {K_ZERO,           '0'},        /*  0 */
+
+#define        ADDITIONAL_CHARACTERS   4
+       {K_NOTUSED, 0},                 /* VEOF, VERASE, VKILL, VWERASE */
+       {K_NOTUSED, 0},
+       {K_NOTUSED, 0},
+       {K_NOTUSED, 0},
+};
+static int nkeylist =
+    (sizeof(keylist) / sizeof(keylist[0])) - ADDITIONAL_CHARACTERS;
+
+/*
+ * v_key_init --
+ *     Initialize the special key lookup table.
+ *
+ * PUBLIC: int v_key_init __P((SCR *));
+ */
+int
+v_key_init(SCR *sp)
+{
+       int ch;
+       GS *gp;
+       KEYLIST *kp;
+       int cnt;
+
+       gp = sp->gp;
+
+       /*
+        * XXX
+        * 8-bit only, for now.  Recompilation should get you any 8-bit
+        * character set, as long as nul isn't a character.
+        */
+       (void)setlocale(LC_ALL, "");
+#if __linux__
+       /*
+        * In libc 4.5.26, setlocale(LC_ALL, ""), doesn't setup the table
+        * for ctype(3c) correctly.  This bug is fixed in libc 4.6.x.
+        *
+        * This code works around this problem for libc 4.5.x users.
+        * Note that this code is harmless if you're using libc 4.6.x.
+        */
+       (void)setlocale(LC_CTYPE, "");
+#endif
+       v_key_ilookup(sp);
+
+       v_keyval(sp, K_CNTRLD, KEY_VEOF);
+       v_keyval(sp, K_VERASE, KEY_VERASE);
+       v_keyval(sp, K_VKILL, KEY_VKILL);
+       v_keyval(sp, K_VWERASE, KEY_VWERASE);
+
+       /* Sort the special key list. */
+       qsort(keylist, nkeylist, sizeof(keylist[0]), v_key_cmp);
+
+       /* Initialize the fast lookup table. */
+       for (kp = keylist, cnt = nkeylist; cnt--; ++kp)
+               gp->special_key[kp->ch] = kp->value;
+
+       /* Find a non-printable character to use as a message separator. */
+       for (ch = 1; ch <= UCHAR_MAX; ++ch)
+               if (!isprint(ch)) {
+                       gp->noprint = ch;
+                       break;
+               }
+       if (ch != gp->noprint) {
+               msgq(sp, M_ERR, "079|No non-printable character found");
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * v_keyval --
+ *     Set key values.
+ *
+ * We've left some open slots in the keylist table, and if these values exist,
+ * we put them into place.  Note, they may reset (or duplicate) values already
+ * in the table, so we check for that first.
+ */
+static void
+v_keyval(SCR *sp, int val, scr_keyval_t name)
+{
+       KEYLIST *kp;
+       CHAR_T ch;
+       int dne;
+
+       /* Get the key's value from the screen. */
+       if (sp->gp->scr_keyval(sp, name, &ch, &dne))
+               return;
+       if (dne)
+               return;
+
+       /* Check for duplication. */
+       for (kp = keylist; kp->value != K_NOTUSED; ++kp)
+               if (kp->ch == ch) {
+                       kp->value = val;
+                       return;
+               }
+
+       /* Add a new entry. */
+       if (kp->value == K_NOTUSED) {
+               keylist[nkeylist].ch = ch;
+               keylist[nkeylist].value = val;
+               ++nkeylist;
+       }
+}
+
+/*
+ * v_key_ilookup --
+ *     Build the fast-lookup key display array.
+ *
+ * PUBLIC: void v_key_ilookup __P((SCR *));
+ */
+void
+v_key_ilookup(SCR *sp)
+{
+       UCHAR_T ch;
+       unsigned char *p, *t;
+       GS *gp;
+       size_t len;
+
+       for (gp = sp->gp, ch = 0;; ++ch) {
+               for (p = gp->cname[ch].name, t = v_key_name(sp, ch),
+                   len = gp->cname[ch].len = sp->clen; len--;)
+                       *p++ = *t++;
+               if (ch == MAX_FAST_KEY)
+                       break;
+       }
+}
+
+/*
+ * v_key_len --
+ *     Return the length of the string that will display the key.
+ *     This routine is the backup for the KEY_LEN() macro.
+ *
+ * PUBLIC: size_t v_key_len __P((SCR *, ARG_CHAR_T));
+ */
+size_t
+v_key_len(SCR *sp, ARG_CHAR_T ch)
+{
+       (void)v_key_name(sp, ch);
+       return (sp->clen);
+}
+
+/*
+ * v_key_name --
+ *     Return the string that will display the key.  This routine
+ *     is the backup for the KEY_NAME() macro.
+ *
+ * PUBLIC: u_char *v_key_name __P((SCR *, ARG_CHAR_T));
+ */
+u_char *
+v_key_name(SCR *sp, ARG_CHAR_T ach)
+{
+       static const char hexdigit[] = "0123456789abcdef";
+       static const char octdigit[] = "01234567";
+       int ch;
+       size_t len, i;
+       const char *chp;
+
+       if (INTISWIDE(ach))
+               goto vis;
+       ch = (unsigned char)ach;
+
+       /* See if the character was explicitly declared printable or not. */
+       if ((chp = O_STR(sp, O_PRINT)) != NULL)
+               for (; *chp != '\0'; ++chp)
+                       if (*chp == ch)
+                               goto pr;
+       if ((chp = O_STR(sp, O_NOPRINT)) != NULL)
+               for (; *chp != '\0'; ++chp)
+                       if (*chp == ch)
+                               goto nopr;
+
+       /*
+        * Historical (ARPA standard) mappings.  Printable characters are left
+        * alone.  Control characters less than 0x20 are represented as '^'
+        * followed by the character offset from the '@' character in the ASCII
+        * character set.  Del (0x7f) is represented as '^' followed by '?'.
+        *
+        * XXX
+        * The following code depends on the current locale being identical to
+        * the ASCII map from 0x40 to 0x5f (since 0x1f + 0x40 == 0x5f).  I'm
+        * told that this is a reasonable assumption...
+        *
+        * XXX
+        * This code will only work with CHAR_T's that are multiples of 8-bit
+        * bytes.
+        *
+        * XXX
+        * NB: There's an assumption here that all printable characters take
+        * up a single column on the screen.  This is not always correct.
+        */
+       if (isprint(ch)) {
+pr:            sp->cname[0] = ch;
+               len = 1;
+               goto done;
+       }
+nopr:  if (iscntrl(ch) && (ch < 0x20 || ch == 0x7f)) {
+               sp->cname[0] = '^';
+               sp->cname[1] = ch == 0x7f ? '?' : '@' + ch;
+               len = 2;
+               goto done;
+       }
+vis:   for (i = 1; i <= sizeof(CHAR_T); ++i)
+               if ((ach >> i * CHAR_BIT) == 0) 
+                       break;
+       ch = (ach >> --i * CHAR_BIT) & UCHAR_MAX;
+       if (O_ISSET(sp, O_OCTAL)) {
+               sp->cname[0] = '\\';
+               sp->cname[1] = octdigit[(ch & 0300) >> 6];
+               sp->cname[2] = octdigit[(ch &  070) >> 3];
+               sp->cname[3] = octdigit[ ch &   07      ];
+       } else {
+               sp->cname[0] = '\\';
+               sp->cname[1] = 'x';
+               sp->cname[2] = hexdigit[(ch & 0xf0) >> 4];
+               sp->cname[3] = hexdigit[ ch & 0x0f      ];
+       }
+       len = 4;
+done:  sp->cname[sp->clen = len] = '\0';
+       return (sp->cname);
+}
+
+/*
+ * v_key_val --
+ *     Fill in the value for a key.  This routine is the backup
+ *     for the KEY_VAL() macro.
+ *
+ * PUBLIC: int v_key_val __P((SCR *, ARG_CHAR_T));
+ */
+e_key_t
+v_key_val(SCR *sp, ARG_CHAR_T ch)
+{
+       KEYLIST k, *kp;
+
+       k.ch = ch;
+       kp = bsearch(&k, keylist, nkeylist, sizeof(keylist[0]), v_key_cmp);
+       return (kp == NULL ? K_NOTUSED : kp->value);
+}
+
+/*
+ * v_event_push --
+ *     Push events/keys onto the front of the buffer.
+ *
+ * There is a single input buffer in ex/vi.  Characters are put onto the
+ * end of the buffer by the terminal input routines, and pushed onto the
+ * front of the buffer by various other functions in ex/vi.  Each key has
+ * an associated flag value, which indicates if it has already been quoted,
+ * and if it is the result of a mapping or an abbreviation.
+ *
+ * PUBLIC: int v_event_push __P((SCR *, EVENT *, const CHAR_T *, size_t, u_int));
+ */
+int
+v_event_push(SCR *sp, EVENT *p_evp, const CHAR_T *p_s, size_t nitems, u_int flags)
+               
+                                       /* Push event. */
+                                       /* Push characters. */
+                                       /* Number of items to push. */
+                                       /* CH_* flags. */
+{
+       EVENT *evp;
+       GS *gp;
+       WIN *wp;
+       size_t total;
+
+       /* If we have room, stuff the items into the buffer. */
+       gp = sp->gp;
+       wp = sp->wp;
+       if (nitems <= wp->i_next ||
+           (wp->i_event != NULL && wp->i_cnt == 0 && nitems <= wp->i_nelem)) {
+               if (wp->i_cnt != 0)
+                       wp->i_next -= nitems;
+               goto copy;
+       }
+
+       /*
+        * If there are currently items in the queue, shift them up,
+        * leaving some extra room.  Get enough space plus a little
+        * extra.
+        */
+#define        TERM_PUSH_SHIFT 30
+       total = wp->i_cnt + wp->i_next + nitems + TERM_PUSH_SHIFT;
+       if (total >= wp->i_nelem && v_event_grow(sp, MAX(total, 64)))
+               return (1);
+       if (wp->i_cnt)
+               MEMMOVE(wp->i_event + TERM_PUSH_SHIFT + nitems,
+                   wp->i_event + wp->i_next, wp->i_cnt);
+       wp->i_next = TERM_PUSH_SHIFT;
+
+       /* Put the new items into the queue. */
+copy:  wp->i_cnt += nitems;
+       for (evp = wp->i_event + wp->i_next; nitems--; ++evp) {
+               if (p_evp != NULL)
+                       *evp = *p_evp++;
+               else {
+                       evp->e_event = E_CHARACTER;
+                       evp->e_c = *p_s++;
+                       evp->e_value = KEY_VAL(sp, evp->e_c);
+                       FL_INIT(evp->e_flags, flags);
+               }
+       }
+       return (0);
+}
+
+/*
+ * v_event_append --
+ *     Append events onto the tail of the buffer.
+ */
+static int
+v_event_append(SCR *sp, EVENT *argp)
+{
+       CHAR_T *s;                      /* Characters. */
+       EVENT *evp;
+       WIN *wp;
+       size_t nevents;                 /* Number of events. */
+
+       /* Grow the buffer as necessary. */
+       nevents = argp->e_event == E_STRING ? argp->e_len : 1;
+       wp = sp->wp;
+       if (wp->i_event == NULL ||
+           nevents > wp->i_nelem - (wp->i_next + wp->i_cnt))
+               v_event_grow(sp, MAX(nevents, 64));
+       evp = wp->i_event + wp->i_next + wp->i_cnt;
+       wp->i_cnt += nevents;
+
+       /* Transform strings of characters into single events. */
+       if (argp->e_event == E_STRING)
+               for (s = argp->e_csp; nevents--; ++evp) {
+                       evp->e_event = E_CHARACTER;
+                       evp->e_c = *s++;
+                       evp->e_value = KEY_VAL(sp, evp->e_c);
+                       evp->e_flags = 0;
+               }
+       else
+               *evp = *argp;
+       return (0);
+}
+
+/* Remove events from the queue. */
+#define        QREM(len) {                                                     \
+       if ((wp->i_cnt -= len) == 0)                                    \
+               wp->i_next = 0;                                         \
+       else                                                            \
+               wp->i_next += len;                                      \
+}
+
+/*
+ * v_event_get --
+ *     Return the next event.
+ *
+ * !!!
+ * The flag EC_NODIGIT probably needs some explanation.  First, the idea of
+ * mapping keys is that one or more keystrokes act like a function key.
+ * What's going on is that vi is reading a number, and the character following
+ * the number may or may not be mapped (EC_MAPCOMMAND).  For example, if the
+ * user is entering the z command, a valid command is "z40+", and we don't want
+ * to map the '+', i.e. if '+' is mapped to "xxx", we don't want to change it
+ * into "z40xxx".  However, if the user enters "35x", we want to put all of the
+ * characters through the mapping code.
+ *
+ * Historical practice is a bit muddled here.  (Surprise!)  It always permitted
+ * mapping digits as long as they weren't the first character of the map, e.g.
+ * ":map ^A1 xxx" was okay.  It also permitted the mapping of the digits 1-9
+ * (the digit 0 was a special case as it doesn't indicate the start of a count)
+ * as the first character of the map, but then ignored those mappings.  While
+ * it's probably stupid to map digits, vi isn't your mother.
+ *
+ * The way this works is that the EC_MAPNODIGIT causes term_key to return the
+ * end-of-digit without "looking" at the next character, i.e. leaving it as the
+ * user entered it.  Presumably, the next term_key call will tell us how the
+ * user wants it handled.
+ *
+ * There is one more complication.  Users might map keys to digits, and, as
+ * it's described above, the commands:
+ *
+ *     :map g 1G
+ *     d2g
+ *
+ * would return the keys "d2<end-of-digits>1G", when the user probably wanted
+ * "d21<end-of-digits>G".  So, if a map starts off with a digit we continue as
+ * before, otherwise, we pretend we haven't mapped the character, and return
+ * <end-of-digits>.
+ *
+ * Now that that's out of the way, let's talk about Energizer Bunny macros.
+ * It's easy to create macros that expand to a loop, e.g. map x 3x.  It's
+ * fairly easy to detect this example, because it's all internal to term_key.
+ * If we're expanding a macro and it gets big enough, at some point we can
+ * assume it's looping and kill it.  The examples that are tough are the ones
+ * where the parser is involved, e.g. map x "ayyx"byy.  We do an expansion
+ * on 'x', and get "ayyx"byy.  We then return the first 4 characters, and then
+ * find the looping macro again.  There is no way that we can detect this
+ * without doing a full parse of the command, because the character that might
+ * cause the loop (in this case 'x') may be a literal character, e.g. the map
+ * map x "ayy"xyy"byy is perfectly legal and won't cause a loop.
+ *
+ * Historic vi tried to detect looping macros by disallowing obvious cases in
+ * the map command, maps that that ended with the same letter as they started
+ * (which wrongly disallowed "map x 'x"), and detecting macros that expanded
+ * too many times before keys were returned to the command parser.  It didn't
+ * get many (most?) of the tricky cases right, however, and it was certainly
+ * possible to create macros that ran forever.  And, even if it did figure out
+ * what was going on, the user was usually tossed into ex mode.  Finally, any
+ * changes made before vi realized that the macro was recursing were left in
+ * place.  We recover gracefully, but the only recourse the user has in an
+ * infinite macro loop is to interrupt.
+ *
+ * !!!
+ * It is historic practice that mapping characters to themselves as the first
+ * part of the mapped string was legal, and did not cause infinite loops, i.e.
+ * ":map! { {^M^T" and ":map n nz." were known to work.  The initial, matching
+ * characters were returned instead of being remapped.
+ *
+ * !!!
+ * It is also historic practice that the macro "map ] ]]^" caused a single ]
+ * keypress to behave as the command ]] (the ^ got the map past the vi check
+ * for "tail recursion").  Conversely, the mapping "map n nn^" went recursive.
+ * What happened was that, in the historic vi, maps were expanded as the keys
+ * were retrieved, but not all at once and not centrally.  So, the keypress ]
+ * pushed ]]^ on the stack, and then the first ] from the stack was passed to
+ * the ]] command code.  The ]] command then retrieved a key without entering
+ * the mapping code.  This could bite us anytime a user has a map that depends
+ * on secondary keys NOT being mapped.  I can't see any possible way to make
+ * this work in here without the complete abandonment of Rationality Itself.
+ *
+ * XXX
+ * The final issue is recovery.  It would be possible to undo all of the work
+ * that was done by the macro if we entered a record into the log so that we
+ * knew when the macro started, and, in fact, this might be worth doing at some
+ * point.  Given that this might make the log grow unacceptably (consider that
+ * cursor keys are done with maps), for now we leave any changes made in place.
+ *
+ * PUBLIC: int v_event_get __P((SCR *, EVENT *, int, u_int32_t));
+ */
+int
+v_event_get(SCR *sp, EVENT *argp, int timeout, u_int32_t flags)
+{
+       EVENT *evp, ev;
+       GS *gp;
+       SEQ *qp;
+       int init_nomap, ispartial, istimeout, remap_cnt;
+       WIN *wp;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       /* If simply checking for interrupts, argp may be NULL. */
+       if (argp == NULL)
+               argp = &ev;
+
+retry: istimeout = remap_cnt = 0;
+
+       /*
+        * If the queue isn't empty and we're timing out for characters,
+        * return immediately.
+        */
+       if (wp->i_cnt != 0 && LF_ISSET(EC_TIMEOUT))
+               return (0);
+
+       /*
+        * If the queue is empty, we're checking for interrupts, or we're
+        * timing out for characters, get more events.
+        */
+       if (wp->i_cnt == 0 || LF_ISSET(EC_INTERRUPT | EC_TIMEOUT)) {
+               /*
+                * If we're reading new characters, check any scripting
+                * windows for input.
+                */
+               if (F_ISSET(gp, G_SCRWIN) && sscr_input(sp))
+                       return (1);
+loop:          if (gp->scr_event(sp, argp,
+                   LF_ISSET(EC_INTERRUPT | EC_QUOTED | EC_RAW), timeout))
+                       return (1);
+               switch (argp->e_event) {
+               case E_ERR:
+               case E_SIGHUP:
+               case E_SIGTERM:
+                       /*
+                        * Fatal conditions cause the file to be synced to
+                        * disk immediately.
+                        */
+                       v_sync(sp, RCV_ENDSESSION | RCV_PRESERVE |
+                           (argp->e_event == E_SIGTERM ? 0: RCV_EMAIL));
+                       return (1);
+               case E_TIMEOUT:
+                       istimeout = 1;
+                       break;
+               case E_INTERRUPT:
+                       /* Set the global interrupt flag. */
+                       F_SET(sp->gp, G_INTERRUPTED);
+
+                       /*
+                        * If the caller was interested in interrupts, return
+                        * immediately.
+                        */
+                       if (LF_ISSET(EC_INTERRUPT))
+                               return (0);
+                       goto append;
+               default:
+append:                        if (v_event_append(sp, argp))
+                               return (1);
+                       break;
+               }
+       }
+
+       /*
+        * If the caller was only interested in interrupts or timeouts, return
+        * immediately.  (We may have gotten characters, and that's okay, they
+        * were queued up for later use.)
+        */
+       if (LF_ISSET(EC_INTERRUPT | EC_TIMEOUT))
+               return (0);
+        
+newmap:        evp = &wp->i_event[wp->i_next];
+
+       /* 
+        * If the next event in the queue isn't a character event, return
+        * it, we're done.
+        */
+       if (evp->e_event != E_CHARACTER) {
+               *argp = *evp;
+               QREM(1);
+               return (0);
+       }
+       
+       /*
+        * If the key isn't mappable because:
+        *
+        *      + ... the timeout has expired
+        *      + ... it's not a mappable key
+        *      + ... neither the command or input map flags are set
+        *      + ... there are no maps that can apply to it
+        *
+        * return it forthwith.
+        */
+       if (istimeout || FL_ISSET(evp->e_flags, CH_NOMAP) ||
+           !LF_ISSET(EC_MAPCOMMAND | EC_MAPINPUT) ||
+           ((evp->e_c & ~MAX_BIT_SEQ) == 0 &&
+           !bit_test(gp->seqb, evp->e_c)))
+               goto nomap;
+
+       /* Search the map. */
+       qp = seq_find(sp, NULL, evp, NULL, wp->i_cnt,
+           LF_ISSET(EC_MAPCOMMAND) ? SEQ_COMMAND : SEQ_INPUT, &ispartial);
+
+       /*
+        * If get a partial match, get more characters and retry the map.
+        * If time out without further characters, return the characters
+        * unmapped.
+        *
+        * !!!
+        * <escape> characters are a problem.  Cursor keys start with <escape>
+        * characters, so there's almost always a map in place that begins with
+        * an <escape> character.  If we timeout <escape> keys in the same way
+        * that we timeout other keys, the user will get a noticeable pause as
+        * they enter <escape> to terminate input mode.  If key timeout is set
+        * for a slow link, users will get an even longer pause.  Nvi used to
+        * simply timeout <escape> characters at 1/10th of a second, but this
+        * loses over PPP links where the latency is greater than 100Ms.
+        */
+       if (ispartial) {
+               if (O_ISSET(sp, O_TIMEOUT))
+                       timeout = (evp->e_value == K_ESCAPE ?
+                           O_VAL(sp, O_ESCAPETIME) :
+                           O_VAL(sp, O_KEYTIME)) * 100;
+               else
+                       timeout = 0;
+               goto loop;
+       }
+
+       /* If no map, return the character. */
+       if (qp == NULL) {
+nomap:         if (!ISDIGIT(evp->e_c) && LF_ISSET(EC_MAPNODIGIT))
+                       goto not_digit;
+               *argp = *evp;
+               QREM(1);
+               return (0);
+       }
+
+       /*
+        * If looking for the end of a digit string, and the first character
+        * of the map is it, pretend we haven't seen the character.
+        */
+       if (LF_ISSET(EC_MAPNODIGIT) &&
+           qp->output != NULL && !ISDIGIT(qp->output[0])) {
+not_digit:     argp->e_c = CH_NOT_DIGIT;
+               argp->e_value = K_NOTUSED;
+               argp->e_event = E_CHARACTER;
+               FL_INIT(argp->e_flags, 0);
+               return (0);
+       }
+
+       /* Find out if the initial segments are identical. */
+       init_nomap = !e_memcmp(qp->output, &wp->i_event[wp->i_next], qp->ilen);
+
+       /* Delete the mapped characters from the queue. */
+       QREM(qp->ilen);
+
+       /* If keys mapped to nothing, go get more. */
+       if (qp->output == NULL)
+               goto retry;
+
+       /* If remapping characters... */
+       if (O_ISSET(sp, O_REMAP)) {
+               /*
+                * Periodically check for interrupts.  Always check the first
+                * time through, because it's possible to set up a map that
+                * will return a character every time, but will expand to more,
+                * e.g. "map! a aaaa" will always return a 'a', but we'll never
+                * get anywhere useful.
+                */
+               if ((++remap_cnt == 1 || remap_cnt % 10 == 0) &&
+                   (gp->scr_event(sp, &ev,
+                   EC_INTERRUPT, 0) || ev.e_event == E_INTERRUPT)) {
+                       F_SET(sp->gp, G_INTERRUPTED);
+                       argp->e_event = E_INTERRUPT;
+                       return (0);
+               }
+
+               /*
+                * If an initial part of the characters mapped, they are not
+                * further remapped -- return the first one.  Push the rest
+                * of the characters, or all of the characters if no initial
+                * part mapped, back on the queue.
+                */
+               if (init_nomap) {
+                       if (v_event_push(sp, NULL, qp->output + qp->ilen,
+                           qp->olen - qp->ilen, CH_MAPPED))
+                               return (1);
+                       if (v_event_push(sp, NULL,
+                           qp->output, qp->ilen, CH_NOMAP | CH_MAPPED))
+                               return (1);
+                       evp = &wp->i_event[wp->i_next];
+                       goto nomap;
+               }
+               if (v_event_push(sp, NULL, qp->output, qp->olen, CH_MAPPED))
+                       return (1);
+               goto newmap;
+       }
+
+       /* Else, push the characters on the queue and return one. */
+       if (v_event_push(sp, NULL, qp->output, qp->olen, CH_MAPPED | CH_NOMAP))
+               return (1);
+
+       goto nomap;
+}
+
+/*
+ * v_sync --
+ *     Walk the screen lists, sync'ing files to their backup copies.
+ */
+static void
+v_sync(SCR *sp, int flags)
+{
+       GS *gp;
+       WIN *wp;
+
+       gp = sp->gp;
+       for (wp = gp->dq.cqh_first; wp != (void *)&gp->dq; 
+           wp = wp->q.cqe_next)
+               for (sp = wp->scrq.cqh_first; sp != (void *)&wp->scrq; 
+                   sp = sp->q.cqe_next)
+               rcv_sync(sp, flags);
+       for (sp = gp->hq.cqh_first; sp != (void *)&gp->hq; sp = sp->q.cqe_next)
+               rcv_sync(sp, flags);
+}
+
+/*
+ * v_event_err --
+ *     Unexpected event.
+ *
+ * PUBLIC: void v_event_err __P((SCR *, EVENT *));
+ */
+void
+v_event_err(SCR *sp, EVENT *evp)
+{
+       switch (evp->e_event) {
+       case E_CHARACTER:
+               msgq(sp, M_ERR, "276|Unexpected character event");
+               break;
+       case E_EOF:
+               msgq(sp, M_ERR, "277|Unexpected end-of-file event");
+               break;
+       case E_INTERRUPT:
+               msgq(sp, M_ERR, "279|Unexpected interrupt event");
+               break;
+       case E_IPCOMMAND:
+               msgq(sp, M_ERR, "318|Unexpected command or input");
+               break;
+       case E_REPAINT:
+               msgq(sp, M_ERR, "281|Unexpected repaint event");
+               break;
+       case E_STRING:
+               msgq(sp, M_ERR, "285|Unexpected string event");
+               break;
+       case E_TIMEOUT:
+               msgq(sp, M_ERR, "286|Unexpected timeout event");
+               break;
+       case E_WRESIZE:
+               msgq(sp, M_ERR, "316|Unexpected resize event");
+               break;
+
+       /*
+        * Theoretically, none of these can occur, as they're handled at the
+        * top editor level.
+        */
+       case E_ERR:
+       case E_SIGHUP:
+       case E_SIGTERM:
+       default:
+               abort();
+       }
+}
+
+/*
+ * v_event_flush --
+ *     Flush any flagged keys, returning if any keys were flushed.
+ *
+ * PUBLIC: int v_event_flush __P((SCR *, u_int));
+ */
+int
+v_event_flush(SCR *sp, u_int flags)
+{
+       WIN *wp;
+       int rval;
+
+       for (rval = 0, wp = sp->wp; wp->i_cnt != 0 &&
+           FL_ISSET(wp->i_event[wp->i_next].e_flags, flags); rval = 1)
+               QREM(1);
+       return (rval);
+}
+
+/*
+ * v_event_grow --
+ *     Grow the terminal queue.
+ */
+static int
+v_event_grow(SCR *sp, int add)
+{
+       WIN *wp;
+       size_t new_nelem, olen;
+
+       wp = sp->wp;
+       new_nelem = wp->i_nelem + add;
+       olen = wp->i_nelem * sizeof(wp->i_event[0]);
+       BINC_RET(sp, EVENT, wp->i_event, olen, new_nelem * sizeof(EVENT));
+       wp->i_nelem = olen / sizeof(wp->i_event[0]);
+       return (0);
+}
+
+/*
+ * v_key_cmp --
+ *     Compare two keys for sorting.
+ */
+static int
+v_key_cmp(const void *ap, const void *bp)
+{
+       return (((const KEYLIST *)ap)->ch - ((const KEYLIST *)bp)->ch);
+}
diff --git a/dist/nvi/common/key.h b/dist/nvi/common/key.h
new file mode 100644 (file)
index 0000000..8c30d61
--- /dev/null
@@ -0,0 +1,229 @@
+/*     $NetBSD: key.h,v 1.3 2011/11/14 13:29:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: key.h,v 10.50 2001/06/28 17:53:58 skimo Exp (Berkeley) Date: 2001/06/28 17:53:58
+ */
+
+#include "multibyte.h"
+
+#ifdef USE_WIDECHAR
+#define FILE2INT5(sp,buf,n,nlen,w,wlen)                                            \
+    sp->conv.file2int(sp, n, nlen, &buf, &wlen, &w)
+#define INT2FILE(sp,w,wlen,n,nlen)                                         \
+    sp->conv.int2file(sp, w, wlen, &sp->wp->cw, &nlen, &n)
+#define CHAR2INT5(sp,buf,n,nlen,w,wlen)                                            \
+    sp->conv.sys2int(sp, n, nlen, &buf, &wlen, &w)
+#define INT2CHAR(sp,w,wlen,n,nlen)                                         \
+    sp->conv.int2sys(sp, w, wlen, &sp->wp->cw, &nlen, &n)
+#define INT2SYS(sp,w,wlen,n,nlen)                                          \
+    sp->conv.int2sys(sp, w, wlen, &sp->wp->cw, &nlen, &n)
+#define INPUT2INT5(sp,cw,n,nlen,w,wlen)                                            \
+    sp->conv.input2int(sp, n, nlen, &(cw), &wlen, &w)
+#define CONST
+#define CHAR_WIDTH(sp, ch)  wcwidth(ch)
+#define INTISWIDE(c)   (wctob(c) == EOF)           /* XXX wrong name */
+#else
+#define FILE2INT5(sp,buf,n,nlen,w,wlen) \
+    (w = n, wlen = nlen, 0)
+#define INT2FILE(sp,w,wlen,n,nlen) \
+    (n = w, nlen = wlen, 0)
+#define CHAR2INT5(sp,buf,n,nlen,w,wlen) \
+    (w = n, wlen = nlen, 0)
+#define INT2CHAR(sp,w,wlen,n,nlen) \
+    (n = w, nlen = wlen, 0)
+#define INT2SYS(sp,w,wlen,n,nlen) \
+    (n = w, nlen = wlen, 0)
+#define INPUT2INT5(sp,buf,n,nlen,w,wlen) \
+    (w = n, wlen = nlen, 0)
+#define CONST const
+#define INTISWIDE(c)       0
+#define CHAR_WIDTH(sp, ch)  1
+#endif
+#define FILE2INT(sp,n,nlen,w,wlen)                                         \
+    FILE2INT5(sp,sp->wp->cw,n,nlen,w,wlen)
+#define CHAR2INT(sp,n,nlen,w,wlen)                                         \
+    CHAR2INT5(sp,sp->wp->cw,n,nlen,w,wlen)
+
+#define MEMCPYW(to, from, n) \
+    memcpy(to, from, (n) * sizeof(CHAR_T))
+#define MEMMOVEW(to, from, n) \
+    memmove(to, from, (n) * sizeof(CHAR_T))
+
+/* The maximum number of columns any character can take up on a screen. */
+#define        MAX_CHARACTER_COLUMNS   4
+
+/*
+ * Event types.
+ *
+ * The program structure depends on the event loop being able to return
+ * E_EOF/E_ERR multiple times -- eventually enough things will end due
+ * to the events that vi will reach the command level for the screen, at
+ * which point the exit flags will be set and vi will exit.
+ */
+typedef enum {
+       E_NOTUSED = 0,                  /* Not set. */
+       E_CHARACTER,                    /* Input character: e_c set. */
+       E_EOF,                          /* End of input (NOT ^D). */
+       E_ERR,                          /* Input error. */
+       E_INTERRUPT,                    /* Interrupt. */
+       E_IPCOMMAND,                    /* IP command: e_ipcom set. */
+       E_REPAINT,                      /* Repaint: e_flno, e_tlno set. */
+       E_SIGHUP,                       /* SIGHUP. */
+       E_SIGTERM,                      /* SIGTERM. */
+       E_STRING,                       /* Input string: e_csp, e_len set. */
+       E_TIMEOUT,                      /* Timeout. */
+       E_WRESIZE,                      /* Window resize. */
+       E_FLAGS                         /* Flags */
+} e_event_t;
+
+/*
+ * Character values.
+ */
+typedef enum {
+       K_NOTUSED = 0,                  /* Not set. */
+       K_BACKSLASH,                    /*  \ */
+       K_CARAT,                        /*  ^ */
+       K_CNTRLD,                       /* ^D */
+       K_CNTRLR,                       /* ^R */
+       K_CNTRLT,                       /* ^T */
+       K_CNTRLZ,                       /* ^Z */
+       K_COLON,                        /*  : */
+       K_CR,                           /* \r */
+       K_ESCAPE,                       /* ^[ */
+       K_FORMFEED,                     /* \f */
+       K_HEXCHAR,                      /* ^X */
+       K_NL,                           /* \n */
+       K_RIGHTBRACE,                   /*  } */
+       K_RIGHTPAREN,                   /*  ) */
+       K_TAB,                          /* \t */
+       K_VERASE,                       /* set from tty: default ^H */
+       K_VKILL,                        /* set from tty: default ^U */
+       K_VLNEXT,                       /* set from tty: default ^V */
+       K_VWERASE,                      /* set from tty: default ^W */
+       K_ZERO                          /*  0 */
+} e_key_t;
+
+struct _event {
+       TAILQ_ENTRY(_event) q;          /* Linked list of events. */
+       e_event_t e_event;              /* Event type. */
+       int       e_ipcom;              /* IP command. */
+
+#define        CH_ABBREVIATED  0x01            /* Character is from an abbreviation. */
+#define        CH_MAPPED       0x02            /* Character is from a map. */
+#define        CH_NOMAP        0x04            /* Do not map the character. */
+#define        CH_QUOTED       0x08            /* Character is already quoted. */
+       ARG_CHAR_T e_c;                 /* Character. */
+       e_key_t   e_value;              /* Key type. */
+
+#define        e_flags e_val1                  /* Flags. */
+#define        e_lno   e_val1                  /* Single location. */
+#define        e_cno   e_val2
+#define        e_flno  e_val1                  /* Text region. */
+#define        e_fcno  e_val2
+#define        e_tlno  e_val3
+#define        e_tcno  e_val4
+       size_t    e_val1;               /* Value #1. */
+       size_t    e_val2;               /* Value #2. */
+       size_t    e_val3;               /* Value #3. */
+       size_t    e_val4;               /* Value #4. */
+
+#define        e_csp   e_str1
+#define        e_len   e_len1
+       CHAR_T   *e_str1;               /* String #1. */
+       size_t    e_len1;               /* String #1 length. */
+       CHAR_T   *e_str2;               /* String #2. */
+       size_t    e_len2;               /* String #2 length. */
+};
+
+typedef struct _keylist {
+       e_key_t value;                  /* Special value. */
+       int     ch;                     /* Key. */
+} KEYLIST;
+extern KEYLIST keylist[];
+
+                                       /* Return if more keys in queue. */
+#define        KEYS_WAITING(sp)        ((sp)->wp->i_cnt != 0)
+#define        MAPPED_KEYS_WAITING(sp)                                         \
+       (KEYS_WAITING(sp) &&                                            \
+           FL_ISSET((sp)->wp->i_event[(sp)->wp->i_next].e_flags, CH_MAPPED))
+
+/* The "standard" tab width, for displaying things to users. */
+#define        STANDARD_TAB    6
+
+/* Various special characters, messages. */
+#define        CH_BSEARCH      '?'             /* Backward search prompt. */
+#define        CH_CURSOR       ' '             /* Cursor character. */
+#define        CH_ENDMARK      '$'             /* End of a range. */
+#define        CH_EXPROMPT     ':'             /* Ex prompt. */
+#define        CH_FSEARCH      '/'             /* Forward search prompt. */
+#define        CH_HEX          '\030'          /* Leading hex character. */
+#define        CH_LITERAL      '\026'          /* ASCII ^V. */
+#define        CH_NO           'n'             /* No. */
+#define        CH_NOT_DIGIT    'a'             /* A non-isdigit() character. */
+#define        CH_QUIT         'q'             /* Quit. */
+#define        CH_YES          'y'             /* Yes. */
+
+/*
+ * Checking for interrupts means that we look at the bit that gets set if the
+ * screen code supports asynchronous events, and call back into the event code
+ * so that non-asynchronous screens get a chance to post the interrupt.
+ *
+ * INTERRUPT_CHECK is the number of lines "operated" on before checking for
+ * interrupts.
+ */
+#define        INTERRUPT_CHECK 100
+#define        INTERRUPTED(sp)                                                 \
+       (F_ISSET((sp)->gp, G_INTERRUPTED) ||                            \
+       (!v_event_get(sp, NULL, 0, EC_INTERRUPT) &&                     \
+       F_ISSET((sp)->gp, G_INTERRUPTED)))
+#define        CLR_INTERRUPT(sp)                                               \
+       F_CLR((sp)->gp, G_INTERRUPTED)
+
+/* Flags describing types of characters being requested. */
+#define        EC_INTERRUPT    0x001           /* Checking for interrupts. */
+#define        EC_MAPCOMMAND   0x002           /* Apply the command map. */
+#define        EC_MAPINPUT     0x004           /* Apply the input map. */
+#define        EC_MAPNODIGIT   0x008           /* Return to a digit. */
+#define        EC_QUOTED       0x010           /* Try to quote next character */
+#define        EC_RAW          0x020           /* Any next character. XXX: not used. */
+#define        EC_TIMEOUT      0x040           /* Timeout to next character. */
+
+/* Flags describing text input special cases. */
+#define        TXT_ADDNEWLINE  0x00000001      /* Replay starts on a new line. */
+#define        TXT_AICHARS     0x00000002      /* Leading autoindent chars. */
+#define        TXT_ALTWERASE   0x00000004      /* Option: altwerase. */
+#define        TXT_APPENDEOL   0x00000008      /* Appending after EOL. */
+#define        TXT_AUTOINDENT  0x00000010      /* Autoindent set this line. */
+#define        TXT_BACKSLASH   0x00000020      /* Backslashes escape characters. */
+#define        TXT_BEAUTIFY    0x00000040      /* Only printable characters. */
+#define        TXT_BS          0x00000080      /* Backspace returns the buffer. */
+#define        TXT_CEDIT       0x00000100      /* Can return TERM_CEDIT. */
+#define        TXT_CNTRLD      0x00000200      /* Control-D is a command. */
+#define        TXT_CNTRLT      0x00000400      /* Control-T is an indent special. */
+#define        TXT_CR          0x00000800      /* CR returns the buffer. */
+#define        TXT_DOTTERM     0x00001000      /* Leading '.' terminates the input. */
+#define        TXT_EMARK       0x00002000      /* End of replacement mark. */
+#define        TXT_EOFCHAR     0x00004000      /* ICANON set, return EOF character. */
+#define        TXT_ESCAPE      0x00008000      /* Escape returns the buffer. */
+#define        TXT_FILEC       0x00010000      /* Option: filec. */
+#define        TXT_INFOLINE    0x00020000      /* Editing the info line. */
+#define        TXT_MAPINPUT    0x00040000      /* Apply the input map. */
+#define        TXT_NLECHO      0x00080000      /* Echo the newline. */
+#define        TXT_NUMBER      0x00100000      /* Number the line. */
+#define        TXT_OVERWRITE   0x00200000      /* Overwrite characters. */
+#define        TXT_PROMPT      0x00400000      /* Display a prompt. */
+#define        TXT_RECORD      0x00800000      /* Record for replay. */
+#define        TXT_REPLACE     0x01000000      /* Replace; don't delete overwrite. */
+#define        TXT_REPLAY      0x02000000      /* Replay the last input. */
+#define        TXT_RESOLVE     0x04000000      /* Resolve the text into the file. */
+#define        TXT_SEARCHINCR  0x08000000      /* Incremental search. */
+#define        TXT_SHOWMATCH   0x10000000      /* Option: showmatch. */
+#define        TXT_TTYWERASE   0x20000000      /* Option: ttywerase. */
+#define        TXT_WRAPMARGIN  0x40000000      /* Option: wrapmargin. */
diff --git a/dist/nvi/common/log.c b/dist/nvi/common/log.c
new file mode 100644 (file)
index 0000000..d61e8d2
--- /dev/null
@@ -0,0 +1,806 @@
+/*     $NetBSD: log.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: log.c,v 10.26 2002/03/02 23:12:13 skimo Exp (Berkeley) Date: 2002/03/02 23:12:13";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "dbinternal.h"
+
+/*
+ * The log consists of records, each containing a type byte and a variable
+ * length byte string, as follows:
+ *
+ *     LOG_CURSOR_INIT         MARK
+ *     LOG_CURSOR_END          MARK
+ *     LOG_LINE_APPEND_F       db_recno_t              char *
+ *     LOG_LINE_APPEND_B       db_recno_t              char *
+ *     LOG_LINE_DELETE_F       db_recno_t              char *
+ *     LOG_LINE_DELETE_B       db_recno_t              char *
+ *     LOG_LINE_RESET_F        db_recno_t              char *
+ *     LOG_LINE_RESET_B        db_recno_t              char *
+ *     LOG_MARK                LMARK
+ *
+ * We do before image physical logging.  This means that the editor layer
+ * MAY NOT modify records in place, even if simply deleting or overwriting
+ * characters.  Since the smallest unit of logging is a line, we're using
+ * up lots of space.  This may eventually have to be reduced, probably by
+ * doing logical logging, which is a much cooler database phrase.
+ *
+ * The implementation of the historic vi 'u' command, using roll-forward and
+ * roll-back, is simple.  Each set of changes has a LOG_CURSOR_INIT record,
+ * followed by a number of other records, followed by a LOG_CURSOR_END record.
+ * LOG_LINE_RESET records come in pairs.  The first is a LOG_LINE_RESET_B
+ * record, and is the line before the change.  The second is LOG_LINE_RESET_F,
+ * and is the line after the change.  Roll-back is done by backing up to the
+ * first LOG_CURSOR_INIT record before a change.  Roll-forward is done in a
+ * similar fashion.
+ *
+ * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END
+ * record for a line different from the current one.  It should be noted that
+ * this means that a subsequent 'u' command will make a change based on the
+ * new position of the log's cursor.  This is okay, and, in fact, historic vi
+ * behaved that way.
+ */
+
+static int     vi_log_get __P((SCR *sp, db_recno_t *lnop, size_t *size));
+static int     log_cursor1 __P((SCR *, int));
+static void    log_err __P((SCR *, const char *, int));
+#if defined(DEBUG) && 0
+static void    log_trace __P((SCR *, const char *, db_recno_t, u_char *));
+#endif
+
+/* Try and restart the log on failure, i.e. if we run out of memory. */
+#define        LOG_ERR {                                                       \
+       log_err(sp, __FILE__, __LINE__);                                \
+       return (1);                                                     \
+}
+
+/* offset of CHAR_T string in log needs to be aligned on some systems
+ * because it is passed to db_set as a string
+ */
+typedef struct {
+    char    data[sizeof(u_char) /* type */ + sizeof(db_recno_t)];
+    CHAR_T  str[1];
+} log_t;
+#define CHAR_T_OFFSET ((char *)(((log_t*)0)->str) - (char *)0)
+
+/*
+ * log_init --
+ *     Initialize the logging subsystem.
+ *
+ * PUBLIC: int log_init __P((SCR *, EXF *));
+ */
+int
+log_init(SCR *sp, EXF *ep)
+{
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        *
+        * Initialize the buffer.  The logging subsystem has its own
+        * buffers because the global ones are almost by definition
+        * going to be in use when the log runs.
+        */
+       sp->wp->l_lp = NULL;
+       sp->wp->l_len = 0;
+       ep->l_cursor.lno = 1;           /* XXX Any valid recno. */
+       ep->l_cursor.cno = 0;
+       ep->l_high = ep->l_cur = 1;
+
+       if (db_create(&ep->log, 0, 0) != 0 ||
+           db_open(ep->log, NULL, DB_RECNO,
+                         DB_CREATE | VI_DB_THREAD, S_IRUSR | S_IWUSR) != 0) {
+               msgq(sp, M_SYSERR, "009|Log file");
+               F_SET(ep, F_NOLOG);
+               return (1);
+       }
+
+       ep->l_win = NULL;
+       /*LOCK_INIT(sp->wp, ep);*/
+
+       return (0);
+}
+
+/*
+ * log_end --
+ *     Close the logging subsystem.
+ *
+ * PUBLIC: int log_end __P((SCR *, EXF *));
+ */
+int
+log_end(SCR *sp, EXF *ep)
+{
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        */
+       /*LOCK_END(sp->wp, ep);*/
+       if (ep->log != NULL) {
+               (void)(ep->log->close)(ep->log,DB_NOSYNC);
+               ep->log = NULL;
+       }
+       if (sp->wp->l_lp != NULL) {
+               free(sp->wp->l_lp);
+               sp->wp->l_lp = NULL;
+       }
+       sp->wp->l_len = 0;
+       ep->l_cursor.lno = 1;           /* XXX Any valid recno. */
+       ep->l_cursor.cno = 0;
+       ep->l_high = ep->l_cur = 1;
+       return (0);
+}
+
+/*
+ * log_cursor --
+ *     Log the current cursor position, starting an event.
+ *
+ * PUBLIC: int log_cursor __P((SCR *));
+ */
+int
+log_cursor(SCR *sp)
+{
+       EXF *ep;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /*
+        * If any changes were made since the last cursor init,
+        * put out the ending cursor record.
+        */
+       if (ep->l_cursor.lno == OOBLNO) {
+               if (ep->l_win && ep->l_win != sp->wp)
+                       return 0;
+               ep->l_cursor.lno = sp->lno;
+               ep->l_cursor.cno = sp->cno;
+               ep->l_win = NULL;
+               return (log_cursor1(sp, LOG_CURSOR_END));
+       }
+       ep->l_cursor.lno = sp->lno;
+       ep->l_cursor.cno = sp->cno;
+       return (0);
+}
+
+/*
+ * log_cursor1 --
+ *     Actually push a cursor record out.
+ */
+static int
+log_cursor1(SCR *sp, int type)
+{
+       DBT data, key;
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /*
+       if (type == LOG_CURSOR_INIT &&
+           LOCK_TRY(sp->wp, ep))
+               return 1;
+       */
+
+       BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, sizeof(u_char) + sizeof(MARK));
+       sp->wp->l_lp[0] = type;
+       memmove(sp->wp->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
+
+       memset(&key, 0, sizeof(key));
+       key.data = &ep->l_cur;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.size = sizeof(u_char) + sizeof(MARK);
+       if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
+               LOG_ERR;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
+           type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
+           sp->lno, sp->cno);
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+
+       /*
+       if (type == LOG_CURSOR_END)
+               LOCK_UNLOCK(sp->wp, ep);
+       */
+       return (0);
+}
+
+/*
+ * log_line --
+ *     Log a line change.
+ *
+ * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
+ */
+int
+log_line(SCR *sp, db_recno_t lno, u_int action)
+{
+       DBT data, key;
+       EXF *ep;
+       size_t len;
+       CHAR_T *lp;
+       db_recno_t lcur;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /*
+        * XXX
+        *
+        * Kluge for vi.  Clear the EXF undo flag so that the
+        * next 'u' command does a roll-back, regardless.
+        */
+       F_CLR(ep, F_UNDO);
+
+       /* Put out one initial cursor record per set of changes. */
+       if (ep->l_cursor.lno != OOBLNO) {
+               if (log_cursor1(sp, LOG_CURSOR_INIT))
+                       return (1);
+               ep->l_cursor.lno = OOBLNO;
+               ep->l_win = sp->wp;
+       } /*else if (ep->l_win != sp->wp) {
+               printf("log_line own: %p, this: %p\n", ep->l_win, sp->wp);
+               return 1;
+       }*/
+
+       switch (action) {
+       /* newly added for DB4 logging */
+       case LOG_LINE_APPEND_B:
+       case LOG_LINE_DELETE_F:
+               return 0;
+       }
+
+       /*
+        * Put out the changes.  If it's a LOG_LINE_RESET_B call, it's a
+        * special case, avoid the caches.  Also, if it fails and it's
+        * line 1, it just means that the user started with an empty file,
+        * so fake an empty length line.
+        */
+       if (action == LOG_LINE_RESET_B) {
+               if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) {
+                       static CHAR_T nul = 0;
+                       if (lno != 1) {
+                               db_err(sp, lno);
+                               return (1);
+                       }
+                       len = 0;
+                       lp = &nul;
+               }
+       } else
+               if (db_get(sp, lno, DBG_FATAL, &lp, &len))
+                       return (1);
+       BINC_RETC(sp,
+           sp->wp->l_lp, sp->wp->l_len, 
+           len * sizeof(CHAR_T) + CHAR_T_OFFSET);
+       sp->wp->l_lp[0] = action;
+       memmove(sp->wp->l_lp + sizeof(u_char), &lno, sizeof(db_recno_t));
+       MEMMOVEW(sp->wp->l_lp + CHAR_T_OFFSET, lp, len);
+
+       lcur = ep->l_cur;
+       memset(&key, 0, sizeof(key));
+       key.data = &lcur;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.size = len * sizeof(CHAR_T) + CHAR_T_OFFSET;
+       if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
+               LOG_ERR;
+
+#if defined(DEBUG) && 0
+       switch (action) {
+       case LOG_LINE_APPEND_F:
+               vtrace(sp, "%u: log_line: append_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_APPEND_B:
+               vtrace(sp, "%u: log_line: append_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_DELETE_F:
+               vtrace(sp, "%lu: log_line: delete_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_DELETE_B:
+               vtrace(sp, "%lu: log_line: delete_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_RESET_F:
+               vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_RESET_B:
+               vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       }
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+
+       return (0);
+}
+
+/*
+ * log_mark --
+ *     Log a mark position.  For the log to work, we assume that there
+ *     aren't any operations that just put out a log record -- this
+ *     would mean that undo operations would only reset marks, and not
+ *     cause any other change.
+ *
+ * PUBLIC: int log_mark __P((SCR *, LMARK *));
+ */
+int
+log_mark(SCR *sp, LMARK *lmp)
+{
+       DBT data, key;
+       EXF *ep;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /* Put out one initial cursor record per set of changes. */
+       if (ep->l_cursor.lno != OOBLNO) {
+               if (log_cursor1(sp, LOG_CURSOR_INIT))
+                       return (1);
+               ep->l_cursor.lno = OOBLNO;
+               ep->l_win = sp->wp;
+       }
+
+       BINC_RETC(sp, sp->wp->l_lp,
+           sp->wp->l_len, sizeof(u_char) + sizeof(LMARK));
+       sp->wp->l_lp[0] = LOG_MARK;
+       memmove(sp->wp->l_lp + sizeof(u_char), lmp, sizeof(LMARK));
+
+       memset(&key, 0, sizeof(key));
+       key.data = &ep->l_cur;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.size = sizeof(u_char) + sizeof(LMARK);
+       if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
+               LOG_ERR;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "%lu: mark %c: %lu/%u\n",
+           ep->l_cur, lmp->name, lmp->lno, lmp->cno);
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+       return (0);
+}
+
+/*
+ * vi_log_get --
+ *     Get a line from the log in log buffer.
+ */
+static int
+vi_log_get(SCR *sp, db_recno_t *lnop, size_t *size)
+{
+       DBT key, data;
+       size_t nlen;
+       EXF *ep;
+
+       ep = sp->ep;
+
+       nlen = 1024;
+retry:
+       BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
+
+       memset(&key, 0, sizeof(key));
+       key.data = lnop;                /* Initialize db request. */
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.ulen = sp->wp->l_len;
+       data.flags = DB_DBT_USERMEM;
+       switch (ep->log->get(ep->log, NULL, &key, &data, 0)) {
+       case ENOMEM:
+               nlen = data.size;
+               goto retry;
+       case 0:
+               *size = data.size;
+               return 0;
+       default:
+               return 1;
+       }
+}
+
+/*
+ * Log_backward --
+ *     Roll the log backward one operation.
+ *
+ * PUBLIC: int log_backward __P((SCR *, MARK *));
+ */
+int
+log_backward(SCR *sp, MARK *rp)
+{
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       int didop;
+       u_char *p;
+       size_t size;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+                   "010|Logging not being performed, undo not possible");
+               return (1);
+       }
+
+       if (ep->l_cur == 1) {
+               msgq(sp, M_BERR, "011|No changes to undo");
+               return (1);
+       }
+
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+       ep->l_win = sp->wp;
+               
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       for (didop = 0;;) {
+               --ep->l_cur;
+               if (vi_log_get(sp, &ep->l_cur, &size))
+                       LOG_ERR;
+#if defined(DEBUG) && 0
+               log_trace(sp, "log_backward", ep->l_cur, data.data);
+#endif
+               switch (*(p = (u_char *)sp->wp->l_lp)) {
+               case LOG_CURSOR_INIT:
+                       if (didop) {
+                               memmove(rp, p + sizeof(u_char), sizeof(MARK));
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_CURSOR_END:
+                       break;
+               case LOG_LINE_APPEND_F:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_delete(sp, lno))
+                               goto err;
+                       ++sp->rptlines[L_DELETED];
+                       break;
+               case LOG_LINE_DELETE_B:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_insert(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       ++sp->rptlines[L_ADDED];
+                       break;
+               case LOG_LINE_RESET_F:
+                       break;
+               case LOG_LINE_RESET_B:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_set(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       if (sp->rptlchange != lno) {
+                               sp->rptlchange = lno;
+                               ++sp->rptlines[L_CHANGED];
+                       }
+                       break;
+               case LOG_MARK:
+                       didop = 1;
+                       memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+                       m.lno = lm.lno;
+                       m.cno = lm.cno;
+                       if (mark_set(sp, lm.name, &m, 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+err:   F_CLR(ep, F_NOLOG);
+       ep->l_win = NULL;
+       return (1);
+}
+
+/*
+ * Log_setline --
+ *     Reset the line to its original appearance.
+ *
+ * XXX
+ * There's a bug in this code due to our not logging cursor movements
+ * unless a change was made.  If you do a change, move off the line,
+ * then move back on and do a 'U', the line will be restored to the way
+ * it was before the original change.
+ *
+ * PUBLIC: int log_setline __P((SCR *));
+ */
+int
+log_setline(SCR *sp)
+{
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       u_char *p;
+       size_t size;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+                   "012|Logging not being performed, undo not possible");
+               return (1);
+       }
+
+       if (ep->l_cur == 1)
+               return (1);
+
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+       ep->l_win = sp->wp;
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       for (;;) {
+               --ep->l_cur;
+               if (vi_log_get(sp, &ep->l_cur, &size))
+                       LOG_ERR;
+#if defined(DEBUG) && 0
+               log_trace(sp, "log_setline", ep->l_cur, data.data);
+#endif
+               switch (*(p = (u_char *)sp->wp->l_lp)) {
+               case LOG_CURSOR_INIT:
+                       memmove(&m, p + sizeof(u_char), sizeof(MARK));
+                       if (m.lno != sp->lno || ep->l_cur == 1) {
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_CURSOR_END:
+                       memmove(&m, p + sizeof(u_char), sizeof(MARK));
+                       if (m.lno != sp->lno) {
+                               ++ep->l_cur;
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_LINE_APPEND_F:
+               case LOG_LINE_DELETE_B:
+               case LOG_LINE_RESET_F:
+                       break;
+               case LOG_LINE_RESET_B:
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (lno == sp->lno &&
+                           db_set(sp, lno, (CHAR_T *)(p + CHAR_T_OFFSET),
+                               (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       if (sp->rptlchange != lno) {
+                               sp->rptlchange = lno;
+                               ++sp->rptlines[L_CHANGED];
+                       }
+               case LOG_MARK:
+                       memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+                       m.lno = lm.lno;
+                       m.cno = lm.cno;
+                       if (mark_set(sp, lm.name, &m, 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+err:   F_CLR(ep, F_NOLOG);
+       ep->l_win = NULL;
+       return (1);
+}
+
+/*
+ * Log_forward --
+ *     Roll the log forward one operation.
+ *
+ * PUBLIC: int log_forward __P((SCR *, MARK *));
+ */
+int
+log_forward(SCR *sp, MARK *rp)
+{
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       int didop;
+       u_char *p;
+       size_t size;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+           "013|Logging not being performed, roll-forward not possible");
+               return (1);
+       }
+
+       if (ep->l_cur == ep->l_high) {
+               msgq(sp, M_BERR, "014|No changes to re-do");
+               return (1);
+       }
+
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+       ep->l_win = sp->wp;
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       for (didop = 0;;) {
+               ++ep->l_cur;
+               if (vi_log_get(sp, &ep->l_cur, &size))
+                       LOG_ERR;
+#if defined(DEBUG) && 0
+               log_trace(sp, "log_forward", ep->l_cur, data.data);
+#endif
+               switch (*(p = (u_char *)sp->wp->l_lp)) {
+               case LOG_CURSOR_END:
+                       if (didop) {
+                               ++ep->l_cur;
+                               memmove(rp, p + sizeof(u_char), sizeof(MARK));
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_CURSOR_INIT:
+                       break;
+               case LOG_LINE_APPEND_F:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_insert(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       ++sp->rptlines[L_ADDED];
+                       break;
+               case LOG_LINE_DELETE_B:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_delete(sp, lno))
+                               goto err;
+                       ++sp->rptlines[L_DELETED];
+                       break;
+               case LOG_LINE_RESET_B:
+                       break;
+               case LOG_LINE_RESET_F:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_set(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       if (sp->rptlchange != lno) {
+                               sp->rptlchange = lno;
+                               ++sp->rptlines[L_CHANGED];
+                       }
+                       break;
+               case LOG_MARK:
+                       didop = 1;
+                       memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+                       m.lno = lm.lno;
+                       m.cno = lm.cno;
+                       if (mark_set(sp, lm.name, &m, 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+err:   F_CLR(ep, F_NOLOG);
+       ep->l_win = NULL;
+       return (1);
+}
+
+/*
+ * log_err --
+ *     Try and restart the log on failure, i.e. if we run out of memory.
+ */
+static void
+log_err(SCR *sp, const char *file, int line)
+{
+       EXF *ep;
+
+       msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
+       ep = sp->ep;
+       (void)ep->log->close(ep->log, DB_NOSYNC);
+       if (!log_init(sp, ep))
+               msgq(sp, M_ERR, "267|Log restarted");
+}
+
+#if defined(DEBUG) && 0
+static void
+log_trace(SCR *sp, const char *msg, db_recno_t rno, u_char *p)
+{
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+
+       switch (*p) {
+       case LOG_CURSOR_INIT:
+               memmove(&m, p + sizeof(u_char), sizeof(MARK));
+               vtrace(sp, "%lu: %s:  C_INIT: %u/%u\n", rno, msg, m.lno, m.cno);
+               break;
+       case LOG_CURSOR_END:
+               memmove(&m, p + sizeof(u_char), sizeof(MARK));
+               vtrace(sp, "%lu: %s:   C_END: %u/%u\n", rno, msg, m.lno, m.cno);
+               break;
+       case LOG_LINE_APPEND_F:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  APPEND_F: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_APPEND_B:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  APPEND_B: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_DELETE_F:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  DELETE_F: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_DELETE_B:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  DELETE_B: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_RESET_F:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_RESET_B:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno);
+               break;
+       case LOG_MARK:
+               memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+               vtrace(sp,
+                   "%lu: %s:    MARK: %u/%u\n", rno, msg, lm.lno, lm.cno);
+               break;
+       default:
+               abort();
+       }
+}
+#endif
diff --git a/dist/nvi/common/log.h b/dist/nvi/common/log.h
new file mode 100644 (file)
index 0000000..06e0e12
--- /dev/null
@@ -0,0 +1,31 @@
+/*     $NetBSD: log.h,v 1.1.1.2 2008/05/18 14:29:46 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: log.h,v 10.4 2002/06/08 21:00:33 skimo Exp (Berkeley) Date: 2002/06/08 21:00:33
+ */
+
+#define        LOG_NOTYPE              0
+#define        LOG_CURSOR_INIT         2
+#define        LOG_CURSOR_END          3
+#define        LOG_LINE_APPEND_B       4
+#define        LOG_LINE_APPEND_F       5
+#define        LOG_LINE_DELETE_B       6
+#define        LOG_LINE_DELETE_F       7
+#define        LOG_LINE_RESET_B        8
+#define        LOG_LINE_RESET_F        9
+#define        LOG_MARK                10      
+
+typedef enum { UNDO_FORWARD, UNDO_BACKWARD, UNDO_SETLINE } undo_t;
+
+struct _log_state {
+       int     didop;
+       MARK    pos;
+       undo_t  undo;
+};
diff --git a/dist/nvi/common/log4.c b/dist/nvi/common/log4.c
new file mode 100644 (file)
index 0000000..615a18a
--- /dev/null
@@ -0,0 +1,458 @@
+/*     $NetBSD: log4.c,v 1.1.1.2 2008/05/18 14:29:47 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: log4.c,v 10.3 2002/06/08 21:00:33 skimo Exp";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+/*
+ * The log consists of records, each containing a type byte and a variable
+ * length byte string, as follows:
+ *
+ *     LOG_CURSOR_INIT         MARK
+ *     LOG_CURSOR_END          MARK
+ *     LOG_LINE_APPEND_F       db_recno_t              char *
+ *     LOG_LINE_APPEND_B       db_recno_t              char *
+ *     LOG_LINE_DELETE_F       db_recno_t              char *
+ *     LOG_LINE_DELETE_B       db_recno_t              char *
+ *     LOG_LINE_RESET_F        db_recno_t              char *
+ *     LOG_LINE_RESET_B        db_recno_t              char *
+ *     LOG_MARK                LMARK
+ *
+ * We do before image physical logging.  This means that the editor layer
+ * MAY NOT modify records in place, even if simply deleting or overwriting
+ * characters.  Since the smallest unit of logging is a line, we're using
+ * up lots of space.  This may eventually have to be reduced, probably by
+ * doing logical logging, which is a much cooler database phrase.
+ *
+ * The implementation of the historic vi 'u' command, using roll-forward and
+ * roll-back, is simple.  Each set of changes has a LOG_CURSOR_INIT record,
+ * followed by a number of other records, followed by a LOG_CURSOR_END record.
+ * LOG_LINE_RESET records come in pairs.  The first is a LOG_LINE_RESET_B
+ * record, and is the line before the change.  The second is LOG_LINE_RESET_F,
+ * and is the line after the change.  Roll-back is done by backing up to the
+ * first LOG_CURSOR_INIT record before a change.  Roll-forward is done in a
+ * similar fashion.
+ *
+ * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END
+ * record for a line different from the current one.  It should be noted that
+ * this means that a subsequent 'u' command will make a change based on the
+ * new position of the log's cursor.  This is okay, and, in fact, historic vi
+ * behaved that way.
+ */
+
+static int     log_cursor1 __P((SCR *, int));
+
+/*
+ * log_init --
+ *     Initialize the logging subsystem.
+ *
+ * PUBLIC: int log_init __P((SCR *, EXF *));
+ */
+int
+log_init(SCR *sp, EXF *ep)
+{
+       DB_LOGC *logc;
+       DBT data;
+       size_t nlen;
+
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        *
+        * Initialize the buffer.  The logging subsystem has its own
+        * buffers because the global ones are almost by definition
+        * going to be in use when the log runs.
+        */
+       sp->wp->l_lp = NULL;
+       sp->wp->l_len = 0;
+       ep->l_cursor.lno = 1;           /* XXX Any valid recno. */
+       ep->l_cursor.cno = 0;
+       ep->l_high = ep->l_cur = 1;
+
+       if ((sp->db_error = ep->env->log_cursor(ep->env, &logc, 0)) 
+                   != 0) {
+               msgq(sp, M_DBERR, "env->log_cursor");
+               F_SET(ep, F_NOLOG);
+               return (1);
+       }
+       nlen = 1024;
+retry:
+       BINC_GOTO(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.ulen = sp->wp->l_len;
+       data.flags = DB_DBT_USERMEM;
+       switch ((sp->db_error = 
+           logc->get(logc, &ep->lsn_first, &data, DB_LAST))) {
+       case ENOMEM:
+               nlen = data.size;
+               goto retry;
+       default:
+alloc_err:
+               msgq(sp, M_DBERR, "logc->get");
+               F_SET(ep, F_NOLOG);
+               return (1);
+       case 0:
+               ;
+       }
+       MEMCPY(&ep->lsn_cur, &ep->lsn_first, 1);
+       MEMCPY(&ep->lsn_high, &ep->lsn_first, 1);
+       logc->close(logc, 0);
+
+       ep->l_win = NULL;
+       /*LOCK_INIT(sp->wp, ep);*/
+
+       return (0);
+}
+
+/*
+ * log_end --
+ *     Close the logging subsystem.
+ *
+ * PUBLIC: int log_end __P((SCR *, EXF *));
+ */
+int
+log_end(SCR *sp, EXF *ep)
+{
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        */
+       /*LOCK_END(sp->wp, ep);*/
+       if (sp->wp->l_lp != NULL) {
+               free(sp->wp->l_lp);
+               sp->wp->l_lp = NULL;
+       }
+       sp->wp->l_len = 0;
+       ep->l_cursor.lno = 1;           /* XXX Any valid recno. */
+       ep->l_cursor.cno = 0;
+       ep->l_high = ep->l_cur = 1;
+       return (0);
+}
+
+/*
+ * log_cursor --
+ *     Log the current cursor position, starting an event.
+ *
+ * PUBLIC: int log_cursor __P((SCR *));
+ */
+int
+log_cursor(SCR *sp)
+{
+       EXF *ep;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /*
+        * If any changes were made since the last cursor init,
+        * put out the ending cursor record.
+        */
+       if (ep->l_cursor.lno == OOBLNO) {
+               if (ep->l_win && ep->l_win != sp->wp)
+                       return 0;
+               ep->l_cursor.lno = sp->lno;
+               ep->l_cursor.cno = sp->cno;
+               ep->l_win = NULL;
+               return (log_cursor1(sp, LOG_CURSOR_END));
+       }
+       ep->l_cursor.lno = sp->lno;
+       ep->l_cursor.cno = sp->cno;
+       return (0);
+}
+
+/*
+ * log_cursor1 --
+ *     Actually push a cursor record out.
+ */
+static int
+log_cursor1(SCR *sp, int type)
+{
+       DBT data, key;
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /*
+       if (type == LOG_CURSOR_INIT &&
+           LOCK_TRY(sp->wp, ep))
+               return 1;
+       */
+
+       if (type == LOG_CURSOR_INIT && 
+           (sp->db_error = __vi_log_truncate(ep)) != 0) {
+               msgq(sp, M_DBERR, "truncate");
+               return 1;
+       }
+       if ((sp->db_error = 
+               __vi_cursor_log(ep->env, NULL, &ep->lsn_cur, 0, type, 
+                           ep->l_cursor.lno, ep->l_cursor.cno)) != 0) {
+               msgq(sp, M_DBERR, "cursor_log");
+               return 1;
+       }
+       if (type == LOG_CURSOR_END) {
+               MEMCPY(&ep->lsn_high, &ep->lsn_cur, 1);
+               /* XXXX should not be needed */
+               ep->env->log_flush(ep->env, NULL);
+       }
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
+           type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
+           sp->lno, sp->cno);
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+
+       /*
+       if (type == LOG_CURSOR_END)
+               LOCK_UNLOCK(sp->wp, ep);
+       */
+       return (0);
+}
+
+/*
+ * log_line --
+ *     Log a line change.
+ *
+ * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
+ */
+int
+log_line(SCR *sp, db_recno_t lno, u_int action)
+{
+       DBT data, key;
+       EXF *ep;
+       size_t len;
+       CHAR_T *lp;
+       db_recno_t lcur;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /*
+        * XXX
+        *
+        * Kluge for vi.  Clear the EXF undo flag so that the
+        * next 'u' command does a roll-back, regardless.
+        */
+       F_CLR(ep, F_UNDO);
+
+       /* Put out one initial cursor record per set of changes. */
+       if (ep->l_cursor.lno != OOBLNO) {
+               if (log_cursor1(sp, LOG_CURSOR_INIT))
+                       return (1);
+               ep->l_cursor.lno = OOBLNO;
+               ep->l_win = sp->wp;
+       } /*else if (ep->l_win != sp->wp) {
+               printf("log_line own: %p, this: %p\n", ep->l_win, sp->wp);
+               return 1;
+       }*/
+
+       if ((sp->db_error = 
+               __vi_change_log(ep->env, NULL, &ep->lsn_cur, 0, action, 
+                           lno)) != 0) {
+               msgq(sp, M_DBERR, "change_log");
+               return 1;
+       }
+
+#if defined(DEBUG) && 0
+       switch (action) {
+       case LOG_LINE_APPEND_F:
+               vtrace(sp, "%u: log_line: append_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_APPEND_B:
+               vtrace(sp, "%u: log_line: append_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_DELETE_F:
+               vtrace(sp, "%lu: log_line: delete_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_DELETE_B:
+               vtrace(sp, "%lu: log_line: delete_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_RESET_F:
+               vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_RESET_B:
+               vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       }
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+
+       return (0);
+}
+
+/*
+ * log_mark --
+ *     Log a mark position.  For the log to work, we assume that there
+ *     aren't any operations that just put out a log record -- this
+ *     would mean that undo operations would only reset marks, and not
+ *     cause any other change.
+ *
+ * PUBLIC: int log_mark __P((SCR *, LMARK *));
+ */
+int
+log_mark(SCR *sp, LMARK *lmp)
+{
+       DBT data, key;
+       EXF *ep;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /* Put out one initial cursor record per set of changes. */
+       if (ep->l_cursor.lno != OOBLNO) {
+               if (log_cursor1(sp, LOG_CURSOR_INIT))
+                       return (1);
+               ep->l_cursor.lno = OOBLNO;
+               ep->l_win = sp->wp;
+       }
+
+       if ((sp->db_error = 
+               __vi_mark_log(ep->env, NULL, &ep->lsn_cur, 0, 
+                           lmp)) != 0) {
+               msgq(sp, M_DBERR, "cursor_log");
+               return 1;
+       }
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "%lu: mark %c: %lu/%u\n",
+           ep->l_cur, lmp->name, lmp->lno, lmp->cno);
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+       return (0);
+}
+
+/*
+ * Log_backward --
+ *     Roll the log backward one operation.
+ *
+ * PUBLIC: int log_backward __P((SCR *, MARK *));
+ */
+int
+log_backward(SCR *sp, MARK *rp)
+{
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       int didop;
+       u_char *p;
+       size_t size;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+                   "010|Logging not being performed, undo not possible");
+               return (1);
+       }
+
+       if (log_compare(&ep->lsn_cur, &ep->lsn_first) <= 0) {
+               msgq(sp, M_BERR, "011|No changes to undo");
+               return (1);
+       }
+       return __vi_log_traverse(sp, UNDO_BACKWARD, rp);
+}
+
+/*
+ * Log_setline --
+ *     Reset the line to its original appearance.
+ *
+ * XXX
+ * There's a bug in this code due to our not logging cursor movements
+ * unless a change was made.  If you do a change, move off the line,
+ * then move back on and do a 'U', the line will be restored to the way
+ * it was before the original change.
+ *
+ * PUBLIC: int log_setline __P((SCR *));
+ */
+int
+log_setline(SCR *sp)
+{
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       u_char *p;
+       size_t size;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+                   "012|Logging not being performed, undo not possible");
+               return (1);
+       }
+
+       if (log_compare(&ep->lsn_cur, &ep->lsn_first) <= 0) {
+               msgq(sp, M_BERR, "011|No changes to undo");
+               return (1);
+       }
+       return __vi_log_traverse(sp, UNDO_SETLINE, &m);
+}
+
+/*
+ * Log_forward --
+ *     Roll the log forward one operation.
+ *
+ * PUBLIC: int log_forward __P((SCR *, MARK *));
+ */
+int
+log_forward(SCR *sp, MARK *rp)
+{
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       int didop;
+       u_char *p;
+       size_t size;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+           "013|Logging not being performed, roll-forward not possible");
+               return (1);
+       }
+
+       if (log_compare(&ep->lsn_cur, &ep->lsn_high) >= 0) {
+               msgq(sp, M_BERR, "014|No changes to re-do");
+               return (1);
+       }
+       return __vi_log_traverse(sp, UNDO_FORWARD, rp);
+}
diff --git a/dist/nvi/common/main.c b/dist/nvi/common/main.c
new file mode 100644 (file)
index 0000000..60218a2
--- /dev/null
@@ -0,0 +1,529 @@
+/*     $NetBSD: main.c,v 1.3 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"%Z% Copyright (c) 1992, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n\
+%Z% Copyright (c) 1992, 1993, 1994, 1995, 1996\n\
+       Keith Bostic.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static const char sccsid[] = "Id: main.c,v 10.63 2001/11/01 15:24:43 skimo Exp (Berkeley) Date: 2001/11/01 15:24:43";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+#include "pathnames.h"
+
+static void     v_estr __P((const char *, int, const char *));
+static int      v_obsolete __P((char *, char *[]));
+
+/*
+ * editor --
+ *     Main editor routine.
+ *
+ * PUBLIC: int editor __P((WIN *, int, char *[]));
+ */
+int
+editor(WIN *wp, int argc, char **argv)
+{
+       extern int optind;
+       extern char *optarg;
+       const char *p;
+       EVENT ev;
+       FREF *frp;
+       SCR *sp;
+       GS *gp;
+       size_t len;
+       u_int flags;
+       int ch, flagchk, lflag, secure, startup, readonly, rval, silent;
+#ifdef GTAGS
+       int gtags = 0;
+#endif
+       char *tag_f, *wsizearg, path[256];
+       const CHAR_T *w;
+       size_t wlen;
+
+       gp = wp->gp;
+
+       /* Initialize the busy routine, if not defined by the screen. */
+       if (gp->scr_busy == NULL)
+               gp->scr_busy = vs_busy;
+       /* Initialize the message routine, if not defined by the screen. */
+       if (wp->scr_msg == NULL)
+               wp->scr_msg = vs_msg;
+
+       /* Set initial screen type and mode based on the program name. */
+       readonly = 0;
+       if (!strcmp(gp->progname, "ex") || !strcmp(gp->progname, "nex"))
+               LF_INIT(SC_EX);
+       else {
+               /* Nview, view are readonly. */
+               if (!strcmp(gp->progname, "nview") ||
+                   !strcmp(gp->progname, "view"))
+                       readonly = 1;
+               
+               /* Vi is the default. */
+               LF_INIT(SC_VI);
+       }
+
+       /* Convert old-style arguments into new-style ones. */
+       if (v_obsolete(gp->progname, argv))
+               return (1);
+
+       /* Parse the arguments. */
+       flagchk = '\0';
+       tag_f = wsizearg = NULL;
+       lflag = secure = silent = 0;
+       startup = 1;
+
+       /* Set the file snapshot flag. */
+       F_SET(gp, G_SNAPSHOT);
+
+       while ((ch = getopt(argc, argv, "c:"
+#ifdef DEBUG
+           "D:"
+#endif
+           "eF"
+#ifdef GTAGS
+           "G"
+#endif
+           "lRrSsT:t:vw:")) != EOF)
+               switch (ch) {
+               case 'c':               /* Run the command. */
+                       /*
+                        * XXX
+                        * We should support multiple -c options.
+                        */
+                       if (gp->c_option != NULL) {
+                               v_estr(gp->progname, 0,
+                                   "only one -c command may be specified.");
+                               return (1);
+                       }
+                       gp->c_option = optarg;
+                       break;
+#ifdef DEBUG
+               case 'D':
+                       switch (optarg[0]) {
+                       case 's':
+                               startup = 0;
+                               break;
+                       case 'w':
+                               attach(gp);
+                               break;
+                       default:
+                               v_estr(gp->progname, 0,
+                                   "usage: -D requires s or w argument.");
+                               return (1);
+                       }
+                       break;
+#endif
+               case 'e':               /* Ex mode. */
+                       LF_CLR(SC_VI);
+                       LF_SET(SC_EX);
+                       break;
+               case 'F':               /* No snapshot. */
+                       v_estr(gp->progname, 0, 
+                           "-F option no longer supported.");
+                       break;
+               case 'l':               /* Set lisp, showmatch options. */
+                       lflag = 1;
+                       break;
+#ifdef GTAGS
+               case 'G':               /* gtags mode. */
+                       gtags = 1;
+                       break;
+#endif
+               case 'R':               /* Readonly. */
+                       readonly = 1;
+                       break;
+               case 'r':               /* Recover. */
+                       if (flagchk == 't') {
+                               v_estr(gp->progname, 0,
+                                   "only one of -r and -t may be specified.");
+                               return (1);
+                       }
+                       flagchk = 'r';
+                       break;
+               case 'S':
+                       secure = 1;
+                       break;
+               case 's':
+                       silent = 1;
+                       break;
+#ifdef TRACE
+               case 'T':               /* Trace. */
+                       (void)vtrace_init(optarg);
+                       break;
+#endif
+               case 't':               /* Tag. */
+                       if (flagchk == 'r') {
+                               v_estr(gp->progname, 0,
+                                   "only one of -r and -t may be specified.");
+                               return (1);
+                       }
+                       if (flagchk == 't') {
+                               v_estr(gp->progname, 0,
+                                   "only one tag file may be specified.");
+                               return (1);
+                       }
+                       flagchk = 't';
+                       tag_f = optarg;
+                       break;
+               case 'v':               /* Vi mode. */
+                       LF_CLR(SC_EX);
+                       LF_SET(SC_VI);
+                       break;
+               case 'w':
+                       wsizearg = optarg;
+                       break;
+               case '?':
+               default:
+                       (void)gp->scr_usage();
+                       return (1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       /*
+        * -s option is only meaningful to ex.
+        *
+        * If not reading from a terminal, it's like -s was specified.
+        */
+       if (silent && !LF_ISSET(SC_EX)) {
+               v_estr(gp->progname, 0, "-s option is only applicable to ex.");
+               goto err;
+       }
+       if (LF_ISSET(SC_EX) && F_ISSET(gp, G_SCRIPTED))
+               silent = 1;
+
+       /*
+        * Build and initialize the first/current screen.  This is a bit
+        * tricky.  If an error is returned, we may or may not have a
+        * screen structure.  If we have a screen structure, put it on a
+        * display queue so that the error messages get displayed.
+        *
+        * !!!
+        * Everything we do until we go interactive is done in ex mode.
+        */
+       if (screen_init(gp, NULL, &sp)) {
+               if (sp != NULL) {
+                       CIRCLEQ_INSERT_HEAD(&wp->scrq, sp, q);
+                       sp->wp = wp;
+               }
+               goto err;
+       }
+       F_SET(sp, SC_EX);
+       CIRCLEQ_INSERT_HEAD(&wp->scrq, sp, q);
+       sp->wp = wp;
+
+       if (v_key_init(sp))             /* Special key initialization. */
+               goto err;
+
+       { int oargs[5], *oargp = oargs;
+       if (lflag) {                    /* Command-line options. */
+               *oargp++ = O_LISP;
+               *oargp++ = O_SHOWMATCH;
+       }
+       if (readonly)
+               *oargp++ = O_READONLY;
+#ifdef GTAGS
+       if (gtags)
+               *oargp++ = O_GTAGSMODE;
+#endif
+       if (secure)
+               *oargp++ = O_SECURE;
+       *oargp = -1;                    /* Options initialization. */
+       if (opts_init(sp, oargs))
+               goto err;
+       }
+       if (wsizearg != NULL) {
+               ARGS *av[2], a, b;
+               (void)snprintf(path, sizeof(path), "window=%s", wsizearg);
+               a.bp = (CHAR_T *)path;
+               a.len = strlen(path);
+               b.bp = NULL;
+               b.len = 0;
+               av[0] = &a;
+               av[1] = &b;
+               (void)opts_set(sp, av, NULL);
+       }
+       if (silent) {                   /* Ex batch mode option values. */
+               O_CLR(sp, O_AUTOPRINT);
+               O_CLR(sp, O_PROMPT);
+               O_CLR(sp, O_VERBOSE);
+               O_CLR(sp, O_WARN);
+               F_SET(sp, SC_EX_SILENT);
+       }
+
+       sp->rows = O_VAL(sp, O_LINES);  /* Make ex formatting work. */
+       sp->cols = O_VAL(sp, O_COLUMNS);
+
+       if (!silent && startup) {       /* Read EXINIT, exrc files. */
+               if (ex_exrc(sp))
+                       goto err;
+               if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+                       if (screen_end(sp))
+                               goto err;
+                       goto done;
+               }
+       }
+
+       /*
+        * List recovery files if -r specified without file arguments.
+        * Note, options must be initialized and startup information
+        * read before doing this.
+        */
+       if (flagchk == 'r' && argv[0] == NULL) {
+               if (rcv_list(sp))
+                       goto err;
+               if (screen_end(sp))
+                       goto err;
+               goto done;
+       }
+
+       /*
+        * !!!
+        * Initialize the default ^D, ^U scrolling value here, after the
+        * user has had every opportunity to set the window option.
+        *
+        * It's historic practice that changing the value of the window
+        * option did not alter the default scrolling value, only giving
+        * a count to ^D/^U did that.
+        */
+       sp->defscroll = (O_VAL(sp, O_WINDOW) + 1) / 2;
+
+       /*
+        * If we don't have a command-line option, switch into the right
+        * editor now, so that we position default files correctly, and
+        * so that any tags file file-already-locked messages are in the
+        * vi screen, not the ex screen.
+        *
+        * XXX
+        * If we have a command-line option, the error message can end
+        * up in the wrong place, but I think that the combination is
+        * unlikely.
+        */
+       if (gp->c_option == NULL) {
+               F_CLR(sp, SC_EX | SC_VI);
+               F_SET(sp, LF_ISSET(SC_EX | SC_VI));
+       }
+
+       /* Open a tag file if specified. */
+       if (tag_f != NULL) {
+               CHAR2INT(sp, tag_f, strlen(tag_f) + 1, w, wlen);
+               if (ex_tag_first(sp, w))
+                       goto err;
+       }
+
+       /*
+        * Append any remaining arguments as file names.  Files are recovery
+        * files if -r specified.  If the tag option or ex startup commands
+        * loaded a file, then any file arguments are going to come after it.
+        */
+       if (*argv != NULL) {
+               if (sp->frp != NULL) {
+                       /* Cheat -- we know we have an extra argv slot. */
+                       MALLOC_NOMSG(sp,
+                           *--argv, char *, strlen(sp->frp->name) + 1);
+                       if (*argv == NULL) {
+                               v_estr(gp->progname, errno, NULL);
+                               goto err;
+                       }
+                       (void)strcpy(*argv, sp->frp->name);
+               }
+               sp->argv = sp->cargv = argv;
+               F_SET(sp, SC_ARGNOFREE);
+               if (flagchk == 'r')
+                       F_SET(sp, SC_ARGRECOVER);
+       }
+
+       /*
+        * If the ex startup commands and or/the tag option haven't already
+        * created a file, create one.  If no command-line files were given,
+        * use a temporary file.
+        */
+       if (sp->frp == NULL) {
+               if (sp->argv == NULL) {
+                       if ((frp = file_add(sp, NULL)) == NULL)
+                               goto err;
+               } else  {
+                       if ((frp = file_add(sp, sp->argv[0])) == NULL)
+                               goto err;
+                       if (F_ISSET(sp, SC_ARGRECOVER))
+                               F_SET(frp, FR_RECOVER);
+               }
+
+               if (file_init(sp, frp, NULL, 0))
+                       goto err;
+               if (EXCMD_RUNNING(wp)) {
+                       (void)ex_cmd(sp);
+                       if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+                               if (screen_end(sp))
+                                       goto err;
+                               goto done;
+                       }
+               }
+       }
+
+       /*
+        * Check to see if we need to wait for ex.  If SC_SCR_EX is set, ex
+        * was forced to initialize the screen during startup.  We'd like to
+        * wait for a single character from the user, but we can't because
+        * we're not in raw mode.  We can't switch to raw mode because the
+        * vi initialization will switch to xterm's alternate screen, causing
+        * us to lose the messages we're pausing to make sure the user read.
+        * So, wait for a complete line.  
+        */
+       if (F_ISSET(sp, SC_SCR_EX)) {
+               p = msg_cmsg(sp, CMSG_CONT_R, &len);
+               (void)write(STDOUT_FILENO, p, len);
+               for (;;) {
+                       if (v_event_get(sp, &ev, 0, 0))
+                               goto err;
+                       if (ev.e_event == E_INTERRUPT ||
+                           (ev.e_event == E_CHARACTER &&
+                            (ev.e_value == K_CR || ev.e_value == K_NL)))
+                               break;
+                       (void)gp->scr_bell(sp);
+               }
+       }
+
+       /* Switch into the right editor, regardless. */
+       F_CLR(sp, SC_EX | SC_VI);
+       F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT);
+
+       /*
+        * Main edit loop.  Vi handles split screens itself, we only return
+        * here when switching editor modes or restarting the screen.
+        */
+       while (sp != NULL)
+               if (F_ISSET(sp, SC_EX) ? ex(&sp) : vi(&sp))
+                       goto err;
+
+done:  rval = 0;
+       if (0)
+err:           rval = 1;
+
+       return (rval);
+}
+
+/*
+ * v_obsolete --
+ *     Convert historic arguments into something getopt(3) will like.
+ */
+static int
+v_obsolete(char *name, char **argv)
+{
+       size_t len;
+       char *p;
+
+       /*
+        * Translate old style arguments into something getopt will like.
+        * Make sure it's not text space memory, because ex modifies the
+        * strings.
+        *      Change "+" into "-c$".
+        *      Change "+<anything else>" into "-c<anything else>".
+        *      Change "-" into "-s"
+        *      The c, T, t and w options take arguments so they can't be
+        *          special arguments.
+        *
+        * Stop if we find "--" as an argument, the user may want to edit
+        * a file named "+foo".
+        */
+       while (*++argv && strcmp(argv[0], "--"))
+               if (argv[0][0] == '+') {
+                       if (argv[0][1] == '\0') {
+                               MALLOC_NOMSG(NULL, argv[0], char *, 4);
+                               if (argv[0] == NULL)
+                                       goto nomem;
+                               (void)strcpy(argv[0], "-c$");
+                       } else  {
+                               p = argv[0];
+                               len = strlen(argv[0]);
+                               MALLOC_NOMSG(NULL, argv[0], char *, len + 2);
+                               if (argv[0] == NULL)
+                                       goto nomem;
+                               argv[0][0] = '-';
+                               argv[0][1] = 'c';
+                               (void)strcpy(argv[0] + 2, p + 1);
+                       }
+               } else if (argv[0][0] == '-') {
+                       if (argv[0][1] == '\0') {
+                               MALLOC_NOMSG(NULL, argv[0], char *, 3);
+                               if (argv[0] == NULL) {
+nomem:                                 v_estr(name, errno, NULL);
+                                       return (1);
+                               }
+                               (void)strcpy(argv[0], "-s");
+                       } else
+                               if ((argv[0][1] == 'c' || argv[0][1] == 'T' ||
+                                   argv[0][1] == 't' || argv[0][1] == 'w') &&
+                                   argv[0][2] == '\0')
+                                       ++argv;
+               }
+       return (0);
+}
+
+#ifdef DEBUG
+static void
+attach(GS *gp)
+{
+       int fd;
+       char ch;
+
+       if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
+               v_estr(gp->progname, errno, _PATH_TTY);
+               return;
+       }
+
+       (void)printf("process %lu waiting, enter <CR> to continue: ",
+           (u_long)getpid());
+       (void)fflush(stdout);
+
+       do {
+               if (read(fd, &ch, 1) != 1) {
+                       (void)close(fd);
+                       return;
+               }
+       } while (ch != '\n' && ch != '\r');
+       (void)close(fd);
+}
+#endif
+
+static void
+v_estr(const char *name, int eno, const char *msg)
+{
+       (void)fprintf(stderr, "%s", name);
+       if (msg != NULL)
+               (void)fprintf(stderr, ": %s", msg);
+       if (eno)
+               (void)fprintf(stderr, ": %s", strerror(errno));
+       (void)fprintf(stderr, "\n");
+}
diff --git a/dist/nvi/common/mark.c b/dist/nvi/common/mark.c
new file mode 100644 (file)
index 0000000..30653bc
--- /dev/null
@@ -0,0 +1,263 @@
+/*     $NetBSD: mark.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: mark.c,v 10.15 2001/06/25 15:19:11 skimo Exp (Berkeley) Date: 2001/06/25 15:19:11";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+static LMARK *mark_find __P((SCR *, ARG_CHAR_T));
+
+/*
+ * Marks are maintained in a key sorted doubly linked list.  We can't
+ * use arrays because we have no idea how big an index key could be.
+ * The underlying assumption is that users don't have more than, say,
+ * 10 marks at any one time, so this will be is fast enough.
+ *
+ * Marks are fixed, and modifications to the line don't update the mark's
+ * position in the line.  This can be hard.  If you add text to the line,
+ * place a mark in that text, undo the addition and use ` to move to the
+ * mark, the location will have disappeared.  It's tempting to try to adjust
+ * the mark with the changes in the line, but this is hard to do, especially
+ * if we've given the line to v_ntext.c:v_ntext() for editing.  Historic vi
+ * would move to the first non-blank on the line when the mark location was
+ * past the end of the line.  This can be complicated by deleting to a mark
+ * that has disappeared using the ` command.  Historic vi treated this as
+ * a line-mode motion and deleted the line.  This implementation complains to
+ * the user.
+ *
+ * In historic vi, marks returned if the operation was undone, unless the
+ * mark had been subsequently reset.  Tricky.  This is hard to start with,
+ * but in the presence of repeated undo it gets nasty.  When a line is
+ * deleted, we delete (and log) any marks on that line.  An undo will create
+ * the mark.  Any mark creations are noted as to whether the user created
+ * it or if it was created by an undo.  The former cannot be reset by another
+ * undo, but the latter may.
+ *
+ * All of these routines translate ABSMARK2 to ABSMARK1.  Setting either of
+ * the absolute mark locations sets both, so that "m'" and "m`" work like
+ * they, ah, for lack of a better word, "should".
+ */
+
+/*
+ * mark_init --
+ *     Set up the marks.
+ *
+ * PUBLIC: int mark_init __P((SCR *, EXF *));
+ */
+int
+mark_init(SCR *sp, EXF *ep)
+{
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        *
+        * Set up the marks.
+        */
+       LIST_INIT(&ep->marks);
+       return (0);
+}
+
+/*
+ * mark_end --
+ *     Free up the marks.
+ *
+ * PUBLIC: int mark_end __P((SCR *, EXF *));
+ */
+int
+mark_end(SCR *sp, EXF *ep)
+{
+       LMARK *lmp;
+
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        */
+       while ((lmp = ep->marks.lh_first) != NULL) {
+               LIST_REMOVE(lmp, q);
+               free(lmp);
+       }
+       return (0);
+}
+
+/*
+ * mark_get --
+ *     Get the location referenced by a mark.
+ *
+ * PUBLIC: int mark_get __P((SCR *, ARG_CHAR_T, MARK *, mtype_t));
+ */
+int
+mark_get(SCR *sp, ARG_CHAR_T key, MARK *mp, mtype_t mtype)
+{
+       LMARK *lmp;
+
+       if (key == ABSMARK2)
+               key = ABSMARK1;
+
+       lmp = mark_find(sp, key);
+       if (lmp == NULL || (ARG_CHAR_T)lmp->name != key) {
+               msgq(sp, mtype, "017|Mark %s: not set", KEY_NAME(sp, key));
+                return (1);
+       }
+       if (F_ISSET(lmp, MARK_DELETED)) {
+               msgq(sp, mtype,
+                   "018|Mark %s: the line was deleted", KEY_NAME(sp, key));
+                return (1);
+       }
+
+       /*
+        * !!!
+        * The absolute mark is initialized to lno 1/cno 0, and historically
+        * you could use it in an empty file.  Make such a mark always work.
+        */
+       if ((lmp->lno != 1 || lmp->cno != 0) && !db_exist(sp, lmp->lno)) {
+               msgq(sp, mtype,
+                   "019|Mark %s: cursor position no longer exists",
+                   KEY_NAME(sp, key));
+               return (1);
+       }
+       mp->lno = lmp->lno;
+       mp->cno = lmp->cno;
+       return (0);
+}
+
+/*
+ * mark_set --
+ *     Set the location referenced by a mark.
+ *
+ * PUBLIC: int mark_set __P((SCR *, ARG_CHAR_T, MARK *, int));
+ */
+int
+mark_set(SCR *sp, ARG_CHAR_T key, MARK *value, int userset)
+{
+       LMARK *lmp, *lmt;
+
+       if (key == ABSMARK2)
+               key = ABSMARK1;
+
+       /*
+        * The rules are simple.  If the user is setting a mark (if it's a
+        * new mark this is always true), it always happens.  If not, it's
+        * an undo, and we set it if it's not already set or if it was set
+        * by a previous undo.
+        */
+       lmp = mark_find(sp, key);
+       if (lmp == NULL || (ARG_CHAR_T)lmp->name != key) {
+               MALLOC_RET(sp, lmt, LMARK *, sizeof(LMARK));
+               if (lmp == NULL) {
+                       LIST_INSERT_HEAD(&sp->ep->marks, lmt, q);
+               } else
+                       LIST_INSERT_AFTER(lmp, lmt, q);
+               lmp = lmt;
+       } else if (!userset &&
+           !F_ISSET(lmp, MARK_DELETED) && F_ISSET(lmp, MARK_USERSET))
+               return (0);
+
+       lmp->lno = value->lno;
+       lmp->cno = value->cno;
+       lmp->name = key;
+       lmp->flags = userset ? MARK_USERSET : 0;
+       return (0);
+}
+
+/*
+ * mark_find --
+ *     Find the requested mark, or, the slot immediately before
+ *     where it would go.
+ */
+static LMARK *
+mark_find(SCR *sp, ARG_CHAR_T key)
+{
+       LMARK *lmp, *lastlmp;
+
+       /*
+        * Return the requested mark or the slot immediately before
+        * where it should go.
+        */
+       for (lastlmp = NULL, lmp = sp->ep->marks.lh_first;
+           lmp != NULL; lastlmp = lmp, lmp = lmp->q.le_next)
+               if ((ARG_CHAR_T)lmp->name >= key)
+                       return ((ARG_CHAR_T)lmp->name == key ? lmp : lastlmp);
+       return (lastlmp);
+}
+
+/*
+ * mark_insdel --
+ *     Update the marks based on an insertion or deletion.
+ *
+ * PUBLIC: int mark_insdel __P((SCR *, lnop_t, db_recno_t));
+ */
+int
+mark_insdel(SCR *sp, lnop_t op, db_recno_t lno)
+{
+       LMARK *lmp;
+       db_recno_t lline;
+
+       switch (op) {
+       case LINE_APPEND:
+               /* All insert/append operations are done as inserts. */
+               abort();
+       case LINE_DELETE:
+               for (lmp = sp->ep->marks.lh_first;
+                   lmp != NULL; lmp = lmp->q.le_next)
+                       if (lmp->lno >= lno) {
+                               if (lmp->lno == lno) {
+                                       F_SET(lmp, MARK_DELETED);
+                                       (void)log_mark(sp, lmp);
+                               } else
+                                       --lmp->lno;
+                       }
+               break;
+       case LINE_INSERT:
+               /*
+                * XXX
+                * Very nasty special case.  If the file was empty, then we're
+                * adding the first line, which is a replacement.  So, we don't
+                * modify the marks.  This is a hack to make:
+                *
+                *      mz:r!echo foo<carriage-return>'z
+                *
+                * work, i.e. historically you could mark the "line" in an empty
+                * file and replace it, and continue to use the mark.  Insane,
+                * well, yes, I know, but someone complained.
+                *
+                * Check for line #2 before going to the end of the file.
+                */
+               if (!db_exist(sp, 2)) {
+                       if (db_last(sp, &lline))
+                               return (1);
+                       if (lline == 1)
+                               return (0);
+               }
+
+               for (lmp = sp->ep->marks.lh_first;
+                   lmp != NULL; lmp = lmp->q.le_next)
+                       if (lmp->lno >= lno)
+                               ++lmp->lno;
+               break;
+       case LINE_RESET:
+               break;
+       }
+       return (0);
+}
diff --git a/dist/nvi/common/mark.h b/dist/nvi/common/mark.h
new file mode 100644 (file)
index 0000000..32a30ec
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: mark.h,v 1.1.1.2 2008/05/18 14:29:47 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: mark.h,v 10.5 2000/07/14 14:29:16 skimo Exp (Berkeley) Date: 2000/07/14 14:29:16
+ */
+
+/*
+ * The MARK and LMARK structures define positions in the file.  There are
+ * two structures because the mark subroutines are the only places where
+ * anything cares about something other than line and column.
+ *
+ * Because of the different interfaces used by the db(3) package, curses,
+ * and users, the line number is 1 based and the column number is 0 based.
+ * Additionally, it is known that the out-of-band line number is less than
+ * any legal line number.  The line number is of type db_recno_t, as that's
+ * the underlying type of the database.  The column number is of type size_t,
+ * guaranteeing that we can malloc a line.
+ */
+struct _mark {
+#define        OOBLNO          0               /* Out-of-band line number. */
+       db_recno_t       lno;                   /* Line number. */
+       size_t   cno;                   /* Column number. */
+};
+
+struct _lmark {
+       LIST_ENTRY(_lmark) q;           /* Linked list of marks. */
+       db_recno_t       lno;                   /* Line number. */
+       size_t   cno;                   /* Column number. */
+       /* XXXX Needed ? Can non ascii-chars be mark names ? */
+       CHAR_T   name;                  /* Mark name. */
+
+#define        MARK_DELETED    0x01            /* Mark was deleted. */
+#define        MARK_USERSET    0x02            /* User set this mark. */
+       u_int8_t flags;
+};
+
+#define        ABSMARK1        '\''            /* Absolute mark name. */
+#define        ABSMARK2        '`'             /* Absolute mark name. */
diff --git a/dist/nvi/common/mem.h b/dist/nvi/common/mem.h
new file mode 100644 (file)
index 0000000..c87b2c7
--- /dev/null
@@ -0,0 +1,207 @@
+/*     $NetBSD: mem.h,v 1.3 2009/01/18 03:43:45 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: mem.h,v 10.13 2002/01/05 23:13:37 skimo Exp (Berkeley) Date: 2002/01/05 23:13:37
+ */
+
+#if defined(HAVE_GCC) && !defined(__NetBSD__)
+#define CHECK_TYPE(type, var)                                          \
+       do { type L__lp __attribute__((__unused__)) = var; } while (/*CONSTCOND*/0);
+#else
+#define CHECK_TYPE(type, var)
+#endif
+
+/* Increase the size of a malloc'd buffer.  Two versions, one that
+ * returns, one that jumps to an error label.
+ */
+#define        BINC_GOTO(sp, type, lp, llen, nlen) {                           \
+       CHECK_TYPE(type *, lp)                                          \
+       void *L__bincp;                                                 \
+       if ((nlen) > llen) {                                            \
+               if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL)   \
+                       goto alloc_err;                                 \
+               /*                                                      \
+                * !!!                                                  \
+                * Possible pointer conversion.                         \
+                */                                                     \
+               lp = L__bincp;                                          \
+       }                                                               \
+}
+#define        BINC_GOTOC(sp, lp, llen, nlen)                                  \
+       BINC_GOTO(sp, char, lp, llen, nlen)
+#define        BINC_GOTOW(sp, lp, llen, nlen)                                  \
+       BINC_GOTO(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T))
+#define        BINC_RET(sp, type, lp, llen, nlen) {                            \
+       CHECK_TYPE(type *, lp)                                          \
+       void *L__bincp;                                                 \
+       if ((size_t)(nlen) > llen) {                                    \
+               if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL)   \
+                       return (1);                                     \
+               /*                                                      \
+                * !!!                                                  \
+                * Possible pointer conversion.                         \
+                */                                                     \
+               lp = L__bincp;                                          \
+       }                                                               \
+}
+#define        BINC_RETC(sp, lp, llen, nlen)                                   \
+       BINC_RET(sp, char, lp, llen, nlen)
+#define        BINC_RETW(sp, lp, llen, nlen)                                   \
+       BINC_RET(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T))
+
+/*
+ * Get some temporary space, preferably from the global temporary buffer,
+ * from a malloc'd buffer otherwise.  Two versions, one that returns, one
+ * that jumps to an error label.
+ */
+#define        GET_SPACE_GOTO(sp, type, bp, blen, nlen) {                      \
+       CHECK_TYPE(type *, bp)                                          \
+       WIN *L__wp = (sp) == NULL ? NULL : (sp)->wp;                    \
+       if (L__wp == NULL || F_ISSET(L__wp, W_TMP_INUSE)) {             \
+               bp = NULL;                                              \
+               blen = 0;                                               \
+               BINC_GOTO(sp, type, bp, blen, nlen);                    \
+       } else {                                                        \
+               BINC_GOTOC(sp, L__wp->tmp_bp, L__wp->tmp_blen, nlen);   \
+               bp = (type *) L__wp->tmp_bp;                            \
+               blen = L__wp->tmp_blen;                                 \
+               F_SET(L__wp, W_TMP_INUSE);                              \
+       }                                                               \
+}
+#define        GET_SPACE_GOTOC(sp, bp, blen, nlen)                             \
+       GET_SPACE_GOTO(sp, char, bp, blen, nlen)
+#define        GET_SPACE_GOTOW(sp, bp, blen, nlen)                             \
+       GET_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
+#define        GET_SPACE_RET(sp, type, bp, blen, nlen) {                       \
+       CHECK_TYPE(type *, bp)                                          \
+       WIN *L__wp = (sp) == NULL ? NULL : (sp)->wp;                    \
+       if (L__wp == NULL || F_ISSET(L__wp, W_TMP_INUSE)) {             \
+               bp = NULL;                                              \
+               blen = 0;                                               \
+               BINC_RET(sp, type, bp, blen, nlen);                     \
+       } else {                                                        \
+               BINC_RETC(sp, L__wp->tmp_bp, L__wp->tmp_blen, nlen);    \
+               bp = (type *) L__wp->tmp_bp;                            \
+               blen = L__wp->tmp_blen;                                 \
+               F_SET(L__wp, W_TMP_INUSE);                              \
+       }                                                               \
+}
+#define        GET_SPACE_RETC(sp, bp, blen, nlen)                              \
+       GET_SPACE_RET(sp, char, bp, blen, nlen)
+#define        GET_SPACE_RETW(sp, bp, blen, nlen)                              \
+       GET_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
+
+/*
+ * Add space to a GET_SPACE returned buffer.  Two versions, one that
+ * returns, one that jumps to an error label.
+ */
+#define        ADD_SPACE_GOTO(sp, type, bp, blen, nlen) {                      \
+       WIN *L__wp = (sp) == NULL ? NULL : (sp)->wp;                    \
+       CHECK_TYPE(type *, bp)                                          \
+       if (L__wp == NULL || bp == (type *)L__wp->tmp_bp) {             \
+               F_CLR(L__wp, W_TMP_INUSE);                              \
+               BINC_GOTOC(sp, L__wp->tmp_bp, L__wp->tmp_blen, nlen);   \
+               bp = (type *) L__wp->tmp_bp;                            \
+               blen = L__wp->tmp_blen;                                 \
+               F_SET(L__wp, W_TMP_INUSE);                              \
+       } else                                                          \
+               BINC_GOTO(sp, type, bp, blen, nlen);                    \
+}
+#define        ADD_SPACE_GOTOW(sp, bp, blen, nlen)                             \
+       ADD_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
+#define        ADD_SPACE_RET(sp, type, bp, blen, nlen) {                       \
+       CHECK_TYPE(type *, bp)                                          \
+       WIN *L__wp = (sp) == NULL ? NULL : (sp)->wp;                    \
+       if (L__wp == NULL || bp == (type *)L__wp->tmp_bp) {             \
+               F_CLR(L__wp, W_TMP_INUSE);                              \
+               BINC_RETC(sp, L__wp->tmp_bp, L__wp->tmp_blen, nlen);    \
+               bp = (type *) L__wp->tmp_bp;                            \
+               blen = L__wp->tmp_blen;                                 \
+               F_SET(L__wp, W_TMP_INUSE);                              \
+       } else                                                          \
+               BINC_RET(sp, type, bp, blen, nlen);                     \
+}
+#define        ADD_SPACE_RETW(sp, bp, blen, nlen)                              \
+       ADD_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
+
+/* Free a GET_SPACE returned buffer. */
+#define        FREE_SPACE(sp, bp, blen) {                                      \
+       WIN *L__wp = (sp) == NULL ? NULL : (sp)->wp;                    \
+       if (L__wp != NULL && bp == L__wp->tmp_bp)                       \
+               F_CLR(L__wp, W_TMP_INUSE);                              \
+       else                                                            \
+               free(bp);                                               \
+}
+#define        FREE_SPACEW(sp, bp, blen) {                                     \
+       CHECK_TYPE(CHAR_T *, bp)                                        \
+       FREE_SPACE(sp, (char *)bp, blen);                               \
+}
+
+/*
+ * Malloc a buffer, casting the return pointer.  Various versions.
+ *
+ * !!!
+ * The cast should be unnecessary, malloc(3) and friends return void *'s,
+ * which is all we need.  However, some systems that nvi needs to run on
+ * don't do it right yet, resulting in the compiler printing out roughly
+ * a million warnings.  After awhile, it seemed easier to put the casts
+ * in instead of explaining it all the time.
+ */
+#define        CALLOC(sp, p, cast, nmemb, size) {                              \
+       if ((p = (cast)calloc(nmemb, size)) == NULL)                    \
+               msgq(sp, M_SYSERR, NULL);                               \
+}
+#define        CALLOC_GOTO(sp, p, cast, nmemb, size) {                         \
+       if ((p = (cast)calloc(nmemb, size)) == NULL)                    \
+               goto alloc_err;                                         \
+}
+#define        CALLOC_NOMSG(sp, p, cast, nmemb, size) {                        \
+       p = (cast)calloc(nmemb, size);                                  \
+}
+#define        CALLOC_RET(sp, p, cast, nmemb, size) {                          \
+       if ((p = (cast)calloc(nmemb, size)) == NULL) {                  \
+               msgq(sp, M_SYSERR, NULL);                               \
+               return (1);                                             \
+       }                                                               \
+}
+
+#define        MALLOC(sp, p, cast, size) {                                     \
+       if ((p = (cast)malloc(size)) == NULL)                           \
+               msgq(sp, M_SYSERR, NULL);                               \
+}
+#define        MALLOC_GOTO(sp, p, cast, size) {                                \
+       if ((p = (cast)malloc(size)) == NULL)                           \
+               goto alloc_err;                                         \
+}
+#define        MALLOC_NOMSG(sp, p, cast, size) {                               \
+       p = (cast)malloc(size);                                         \
+}
+#define        MALLOC_RET(sp, p, cast, size) {                                 \
+       if ((p = (cast)malloc(size)) == NULL) {                         \
+               msgq(sp, M_SYSERR, NULL);                               \
+               return (1);                                             \
+       }                                                               \
+}
+/*
+ * XXX
+ * Don't depend on realloc(NULL, size) working.
+ */
+#define        REALLOC(sp, p, cast, size) {                                    \
+       if ((p = (cast)(p == NULL ?                                     \
+           malloc(size) : realloc(p, size))) == NULL)                  \
+               msgq(sp, M_SYSERR, NULL);                               \
+}
+
+/*
+ * Versions of memmove(3) and memset(3) that use the size of the
+ * initial pointer to figure out how much memory to manipulate.
+ */
+#define        MEMMOVE(p, t, len)      memmove(p, t, (len) * sizeof(*(p)))
+#define        MEMSET(p, value, len)   memset(p, value, (len) * sizeof(*(p)))
diff --git a/dist/nvi/common/msg.c b/dist/nvi/common/msg.c
new file mode 100644 (file)
index 0000000..31a8222
--- /dev/null
@@ -0,0 +1,929 @@
+/*     $NetBSD: msg.c,v 1.5 2011/08/17 12:56:55 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: msg.c,v 10.61 2003/07/18 23:17:30 skimo Exp (Berkeley) Date: 2003/07/18 23:17:30";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>         /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "common.h"
+#include "dbinternal.h"
+#include "../vi/vi.h"
+
+/*
+ * msgq --
+ *     Display a message.
+ *
+ * PUBLIC: void msgq __P((SCR *, mtype_t, const char *, ...));
+ */
+void
+#ifdef __STDC__
+msgq(SCR *sp, mtype_t mt, const char *fmt, ...)
+#else
+msgq(sp, mt, fmt, va_alist)
+       SCR *sp;
+       mtype_t mt;
+        const char *fmt;
+        va_dcl
+#endif
+{
+#ifndef NL_ARGMAX
+#define        __NL_ARGMAX     20              /* Set to 9 by System V. */
+       struct {
+               const char *str;        /* String pointer. */
+               size_t   arg;           /* Argument number. */
+               size_t   prefix;        /* Prefix string length. */
+               size_t   skip;          /* Skipped string length. */
+               size_t   suffix;        /* Suffix string length. */
+       } str[__NL_ARGMAX];
+#endif
+       static int reenter;             /* STATIC: Re-entrancy check. */
+       GS *gp;
+       WIN *wp = NULL;
+       size_t blen, len, mlen, nlen;
+       const char *p;
+       char *bp, *mp;
+        va_list ap;
+#ifndef NL_ARGMAX
+       int ch;
+       char *rbp, *s_rbp;
+       const char *t, *u;
+       size_t cnt1, cnt2, soff;
+#endif
+
+       /*
+        * !!!
+        * It's possible to enter msg when there's no screen to hold the
+        * message.  If sp is NULL, ignore the special cases and put the
+        * message out to stderr.
+        */
+       if (sp == NULL) {
+               gp = NULL;
+               if (mt == M_BERR)
+                       mt = M_ERR;
+               else if (mt == M_VINFO)
+                       mt = M_INFO;
+       } else {
+               gp = sp->gp;
+               wp = sp->wp;
+               switch (mt) {
+               case M_BERR:
+                       if (F_ISSET(sp, SC_VI) && !O_ISSET(sp, O_VERBOSE)) {
+                               F_SET(gp, G_BELLSCHED);
+                               return;
+                       }
+                       mt = M_ERR;
+                       break;
+               case M_VINFO:
+                       if (!O_ISSET(sp, O_VERBOSE))
+                               return;
+                       mt = M_INFO;
+                       /* FALLTHROUGH */
+               case M_INFO:
+                       if (F_ISSET(sp, SC_EX_SILENT))
+                               return;
+                       break;
+               case M_ERR:
+               case M_SYSERR:
+               case M_DBERR:
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * It's possible to reenter msg when it allocates space.  We're
+        * probably dead anyway, but there's no reason to drop core.
+        *
+        * XXX
+        * Yes, there's a race, but it should only be two instructions.
+        */
+       if (reenter++)
+               return;
+
+       /* Get space for the message. */
+       nlen = 1024;
+       if (0) {
+retry:         FREE_SPACE(sp, bp, blen);
+               nlen *= 2;
+       }
+       bp = NULL;
+       blen = 0;
+       GET_SPACE_GOTOC(sp, bp, blen, nlen);
+
+       /*
+        * Error prefix.
+        *
+        * mp:   pointer to the current next character to be written
+        * mlen: length of the already written characters
+        * blen: total length of the buffer
+        */
+#define        REM     (blen - mlen)
+       mp = bp;
+       mlen = 0;
+       if (mt == M_SYSERR || mt == M_DBERR) {
+               p = msg_cat(sp, "020|Error: ", &len);
+               if (REM < len)
+                       goto retry;
+               memcpy(mp, p, len);
+               mp += len;
+               mlen += len;
+       }
+
+       /*
+        * If we're running an ex command that the user didn't enter, display
+        * the file name and line number prefix.
+        */
+       if ((mt == M_ERR || mt == M_SYSERR) &&
+           sp != NULL && wp != NULL && wp->if_name != NULL) {
+               for (p = wp->if_name; *p != '\0'; ++p) {
+                       len = snprintf(mp, REM, "%s", KEY_NAME(sp, *p));
+                       mp += len;
+                       if ((mlen += len) > blen)
+                               goto retry;
+               }
+               len = snprintf(mp, REM, ", %d: ", wp->if_lno);
+               mp += len;
+               if ((mlen += len) > blen)
+                       goto retry;
+       }
+
+       /* If nothing to format, we're done. */
+       if (fmt == NULL)
+               goto nofmt;
+       fmt = msg_cat(sp, fmt, NULL);
+
+#ifndef NL_ARGMAX
+       /*
+        * Nvi should run on machines that don't support the numbered argument
+        * specifications (%[digit]*$).  We do this by reformatting the string
+        * so that we can hand it to vsprintf(3) and it will use the arguments
+        * in the right order.  When vsprintf returns, we put the string back
+        * into the right order.  It's undefined, according to SVID III, to mix
+        * numbered argument specifications with the standard style arguments,
+        * so this should be safe.
+        *
+        * In addition, we also need a character that is known to not occur in
+        * any vi message, for separating the parts of the string.  As callers
+        * of msgq are responsible for making sure that all the non-printable
+        * characters are formatted for printing before calling msgq, we use a
+        * random non-printable character selected at terminal initialization
+        * time.  This code isn't fast by any means, but as messages should be
+        * relatively short and normally have only a few arguments, it won't be
+        * too bad.  Regardless, nobody has come up with any other solution.
+        *
+        * The result of this loop is an array of pointers into the message
+        * string, with associated lengths and argument numbers.  The array
+        * is in the "correct" order, and the arg field contains the argument
+        * order.
+        */
+       for (p = fmt, soff = 0; soff < __NL_ARGMAX;) {
+               for (t = p; *p != '\0' && *p != '%'; ++p);
+               if (*p == '\0')
+                       break;
+               ++p;
+               if (!isdigit((unsigned char)*p)) {
+                       if (*p == '%')
+                               ++p;
+                       continue;
+               }
+               for (u = p; *++p != '\0' && isdigit((unsigned char)*p););
+               if (*p != '$')
+                       continue;
+
+               /* Up to, and including the % character. */
+               str[soff].str = t;
+               str[soff].prefix = u - t;
+
+               /* Up to, and including the $ character. */
+               str[soff].arg = atoi(u);
+               str[soff].skip = (p - u) + 1;
+               if (str[soff].arg >= __NL_ARGMAX)
+                       goto ret;
+
+               /* Up to, and including the conversion character. */
+               for (u = p; (ch = (unsigned char)*++p) != '\0';)
+                       if (isalpha(ch) &&
+                           strchr("diouxXfeEgGcspn", ch) != NULL)
+                               break;
+               str[soff].suffix = p - u;
+               if (ch != '\0')
+                       ++p;
+               ++soff;
+       }
+
+       /* If no magic strings, we're done. */
+       if (soff == 0)
+               goto format;
+
+        /* Get space for the reordered strings. */
+       if ((rbp = malloc(nlen)) == NULL)
+               goto ret;
+       s_rbp = rbp;
+
+       /*
+        * Reorder the strings into the message string based on argument
+        * order.
+        *
+        * !!!
+        * We ignore arguments that are out of order, i.e. if we don't find
+        * an argument, we continue.  Assume (almost certainly incorrectly)
+        * that whoever created the string knew what they were doing.
+        *
+        * !!!
+        * Brute force "sort", but since we don't expect more than one or two
+        * arguments in a string, the setup cost of a fast sort will be more
+        * expensive than the loop.
+        */
+       for (cnt1 = 1; cnt1 <= soff; ++cnt1)
+               for (cnt2 = 0; cnt2 < soff; ++cnt2)
+                       if (cnt1 == str[cnt2].arg) {
+                               memmove(s_rbp, str[cnt2].str, str[cnt2].prefix);
+                               memmove(s_rbp + str[cnt2].prefix,
+                                   str[cnt2].str + str[cnt2].prefix +
+                                   str[cnt2].skip, str[cnt2].suffix);
+                               s_rbp += str[cnt2].prefix + str[cnt2].suffix;
+                               *s_rbp++ =
+                                   gp == NULL ? DEFAULT_NOPRINT : gp->noprint;
+                               break;
+                       }
+       *s_rbp = '\0';
+       fmt = rbp;
+#endif
+
+#ifndef NL_ARGMAX
+format:        /* Format the arguments into the string. */
+#endif
+#ifdef __STDC__
+        va_start(ap, fmt);
+#else
+        va_start(ap);
+#endif
+       len = vsnprintf(mp, REM, fmt, ap);
+       va_end(ap);
+       if (len >= nlen)
+               goto retry;
+
+#ifndef NL_ARGMAX
+       if (soff == 0)
+               goto nofmt;
+
+       /*
+        * Go through the resulting string, and, for each separator character
+        * separated string, enter its new starting position and length in the
+        * array.
+        */
+       for (p = t = mp, cnt1 = 1,
+           ch = gp == NULL ? DEFAULT_NOPRINT : gp->noprint; *p != '\0'; ++p)
+               if (*p == ch) {
+                       for (cnt2 = 0; cnt2 < soff; ++cnt2)
+                               if (str[cnt2].arg == cnt1)
+                                       break;
+                       str[cnt2].str = t;
+                       str[cnt2].prefix = p - t;
+                       t = p + 1;
+                       ++cnt1;
+               }
+
+       /*
+        * Reorder the strings once again, putting them back into the
+        * message buffer.
+        *
+        * !!!
+        * Note, the length of the message gets decremented once for
+        * each substring, when we discard the separator character.
+        */
+       for (s_rbp = rbp, cnt1 = 0; cnt1 < soff; ++cnt1) {
+               memmove(rbp, str[cnt1].str, str[cnt1].prefix);
+               rbp += str[cnt1].prefix;
+               --len;
+       }
+       memmove(mp, s_rbp, rbp - s_rbp);
+
+       /* Free the reordered string memory. */
+       free(s_rbp);
+#endif
+
+nofmt: mp += len;
+       if ((mlen += len) > blen)
+               goto retry;
+       if (mt == M_SYSERR) {
+               len = snprintf(mp, REM, ": %s", strerror(errno));
+               mp += len;
+               if ((mlen += len) > blen)
+                       goto retry;
+               mt = M_ERR;
+       }
+       if (mt == M_DBERR) {
+               len = snprintf(mp, REM, ": %s", db_strerror(sp->db_error));
+               mp += len;
+               if ((mlen += len) > blen)
+                       goto retry;
+               mt = M_ERR;
+       }
+
+       /* Add trailing newline. */
+       if ((mlen += 1) > blen)
+               goto retry;
+       *mp = '\n';
+
+       if (sp != NULL && sp->ep != NULL)
+               (void)ex_fflush(sp);
+       if (wp != NULL)
+               wp->scr_msg(sp, mt, bp, mlen);
+       else
+               (void)fprintf(stderr, "%.*s", (int)mlen, bp);
+
+       /* Cleanup. */
+#ifndef NL_ARGMAX
+ret:
+#endif
+       FREE_SPACE(sp, bp, blen);
+alloc_err:
+       reenter = 0;
+}
+
+/*
+ * msgq_str --
+ *     Display a message with an embedded string.
+ *
+ * PUBLIC: void msgq_wstr __P((SCR *, mtype_t, const CHAR_T *, const char *));
+ */
+void
+msgq_wstr(SCR *sp, mtype_t mtype, const CHAR_T *str, const char *fmt)
+{
+       size_t nlen;
+       const char *nstr;
+
+       if (str == NULL) {
+               msgq(sp, mtype, "%s", fmt);
+               return;
+       }
+       INT2CHAR(sp, str, STRLEN(str) + 1, nstr, nlen);
+       msgq_str(sp, mtype, nstr, fmt);
+}
+
+/*
+ * msgq_str --
+ *     Display a message with an embedded string.
+ *
+ * PUBLIC: void msgq_str __P((SCR *, mtype_t, char *, char *));
+ */
+void
+msgq_str(SCR *sp, mtype_t mtype, const char *str, const char *fmt)
+{
+       int nf, sv_errno;
+       char *p;
+
+       if (str == NULL) {
+               msgq(sp, mtype, "%s", fmt);
+               return;
+       }
+
+       sv_errno = errno;
+       p = msg_print(sp, str, &nf);
+       errno = sv_errno;
+       msgq(sp, mtype, fmt, p);
+       if (nf)
+               FREE_SPACE(sp, p, 0);
+}
+
+/*
+ * mod_rpt --
+ *     Report on the lines that changed.
+ *
+ * !!!
+ * Historic vi documentation (USD:15-8) claimed that "The editor will also
+ * always tell you when a change you make affects text which you cannot see."
+ * This wasn't true -- edit a large file and do "100d|1".  We don't implement
+ * this semantic since it requires tracking each line that changes during a
+ * command instead of just keeping count.
+ *
+ * Line counts weren't right in historic vi, either.  For example, given the
+ * file:
+ *     abc
+ *     def
+ * the command 2d}, from the 'b' would report that two lines were deleted,
+ * not one.
+ *
+ * PUBLIC: void mod_rpt __P((SCR *));
+ */
+void
+mod_rpt(SCR *sp)
+{
+       static const char * const action[] = {
+               "293|added",
+               "294|changed",
+               "295|deleted",
+               "296|joined",
+               "297|moved",
+               "298|shifted",
+               "299|yanked",
+       };
+       static const char * const lines[] = {
+               "300|line",
+               "301|lines",
+       };
+       db_recno_t total;
+       u_long rptval;
+       int first;
+       size_t cnt, blen, len, tlen;
+       const char *t;
+       const char * const *ap;
+       char *bp, *p;
+
+       /* Change reports are turned off in batch mode. */
+       if (F_ISSET(sp, SC_EX_SILENT))
+               return;
+
+       /* Reset changing line number. */
+       sp->rptlchange = OOBLNO;
+
+       /*
+        * Don't build a message if not enough changed.
+        *
+        * !!!
+        * And now, a vi clone test.  Historically, vi reported if the number
+        * of changed lines was > than the value, not >=, unless it was a yank
+        * command, which used >=.  No lie.  Furthermore, an action was never
+        * reported for a single line action.  This is consistent for actions
+        * other than yank, but yank didn't report single line actions even if
+        * the report edit option was set to 1.  In addition, setting report to
+        * 0 in the 4BSD historic vi was equivalent to setting it to 1, for an
+        * unknown reason (this bug was fixed in System III/V at some point).
+        * I got complaints, so nvi conforms to System III/V historic practice
+        * except that we report a yank of 1 line if report is set to 1.
+        */
+#define        ARSIZE(a)       sizeof(a) / sizeof (*a)
+#define        MAXNUM          25
+       rptval = O_VAL(sp, O_REPORT);
+       for (cnt = 0, total = 0; cnt < ARSIZE(action); ++cnt)
+               total += sp->rptlines[cnt];
+       if (total == 0)
+               return;
+       if (total <= rptval && sp->rptlines[L_YANKED] < rptval) {
+               for (cnt = 0; cnt < ARSIZE(action); ++cnt)
+                       sp->rptlines[cnt] = 0;
+               return;
+       }
+
+       /* Build and display the message. */
+       GET_SPACE_GOTOC(sp, bp, blen, sizeof(action) * MAXNUM + 1);
+       for (p = bp, first = 1, tlen = 0,
+           ap = action, cnt = 0; cnt < ARSIZE(action); ++ap, ++cnt)
+               if (sp->rptlines[cnt] != 0) {
+                       if (first)
+                               first = 0;
+                       else {
+                               *p++ = ';';
+                               *p++ = ' ';
+                               tlen += 2;
+                       }
+                       len = snprintf(p, MAXNUM, "%lu ", 
+                               (unsigned long) sp->rptlines[cnt]);
+                       p += len;
+                       tlen += len;
+                       t = msg_cat(sp,
+                           lines[sp->rptlines[cnt] == 1 ? 0 : 1], &len);
+                       memcpy(p, t, len);
+                       p += len;
+                       tlen += len;
+                       *p++ = ' ';
+                       ++tlen;
+                       t = msg_cat(sp, *ap, &len);
+                       memcpy(p, t, len);
+                       p += len;
+                       tlen += len;
+                       sp->rptlines[cnt] = 0;
+               }
+
+       /* Add trailing newline. */
+       *p = '\n';
+       ++tlen;
+
+       (void)ex_fflush(sp);
+       sp->wp->scr_msg(sp, M_INFO, bp, tlen);
+
+       FREE_SPACE(sp, bp, blen);
+alloc_err:
+       return;
+
+#undef ARSIZE
+#undef MAXNUM
+}
+
+/*
+ * msgq_status --
+ *     Report on the file's status.
+ *
+ * PUBLIC: void msgq_status __P((SCR *, db_recno_t, u_int));
+ */
+void
+msgq_status(SCR *sp, db_recno_t lno, u_int flags)
+{
+       db_recno_t last;
+       size_t blen, len;
+       int cnt, needsep;
+       const char *t;
+       char **ap, *bp, *np, *p, *s;
+
+       /* Get sufficient memory. */
+       len = strlen(sp->frp->name);
+       GET_SPACE_GOTOC(sp, bp, blen, len * MAX_CHARACTER_COLUMNS + 128);
+       p = bp;
+
+       /* Copy in the filename. */
+       for (p = bp, t = sp->frp->name; *t != '\0'; ++t) {
+               len = KEY_LEN(sp, *t);
+               memcpy(p, KEY_NAME(sp, *t), len);
+               p += len;
+       }
+       np = p;
+       *p++ = ':';
+       *p++ = ' ';
+
+       /* Copy in the argument count. */
+       if (F_ISSET(sp, SC_STATUS_CNT) && sp->argv != NULL) {
+               for (cnt = 0, ap = sp->argv; *ap != NULL; ++ap, ++cnt);
+               if (cnt > 1) {
+                       (void)sprintf(p,
+                           msg_cat(sp, "317|%d files to edit", NULL), cnt);
+                       p += strlen(p);
+                       *p++ = ':';
+                       *p++ = ' ';
+               }
+               F_CLR(sp, SC_STATUS_CNT);
+       }
+
+       /*
+        * See nvi/exf.c:file_init() for a description of how and when the
+        * read-only bit is set.
+        *
+        * !!!
+        * The historic display for "name changed" was "[Not edited]".
+        */
+       needsep = 0;
+       if (F_ISSET(sp->frp, FR_NEWFILE)) {
+               F_CLR(sp->frp, FR_NEWFILE);
+               t = msg_cat(sp, "021|new file", &len);
+               memcpy(p, t, len);
+               p += len;
+               needsep = 1;
+       } else {
+               if (F_ISSET(sp->frp, FR_NAMECHANGE)) {
+                       t = msg_cat(sp, "022|name changed", &len);
+                       memcpy(p, t, len);
+                       p += len;
+                       needsep = 1;
+               }
+               if (needsep) {
+                       *p++ = ',';
+                       *p++ = ' ';
+               }
+               if (F_ISSET(sp->ep, F_MODIFIED))
+                       t = msg_cat(sp, "023|modified", &len);
+               else
+                       t = msg_cat(sp, "024|unmodified", &len);
+               memcpy(p, t, len);
+               p += len;
+               needsep = 1;
+       }
+       if (F_ISSET(sp->frp, FR_UNLOCKED)) {
+               if (needsep) {
+                       *p++ = ',';
+                       *p++ = ' ';
+               }
+               t = msg_cat(sp, "025|UNLOCKED", &len);
+               memcpy(p, t, len);
+               p += len;
+               needsep = 1;
+       }
+       if (O_ISSET(sp, O_READONLY)) {
+               if (needsep) {
+                       *p++ = ',';
+                       *p++ = ' ';
+               }
+               t = msg_cat(sp, "026|readonly", &len);
+               memcpy(p, t, len);
+               p += len;
+               needsep = 1;
+       }
+       if (needsep) {
+               *p++ = ':';
+               *p++ = ' ';
+       }
+       if (LF_ISSET(MSTAT_SHOWLAST)) {
+               if (db_last(sp, &last))
+                       return;
+               if (last == 0) {
+                       t = msg_cat(sp, "028|empty file", &len);
+                       memcpy(p, t, len);
+                       p += len;
+               } else {
+                       t = msg_cat(sp, "027|line %lu of %lu [%ld%%]", &len);
+                       (void)sprintf(p, t, lno, last, (lno * 100) / last);
+                       p += strlen(p);
+               }
+       } else {
+               t = msg_cat(sp, "029|line %lu", &len);
+               (void)sprintf(p, t, lno);
+               p += strlen(p);
+       }
+#ifdef DEBUG
+       (void)sprintf(p, " (pid %lu)", (u_long)getpid());
+       p += strlen(p);
+#endif
+       *p++ = '\n';
+       len = p - bp;
+
+       /*
+        * There's a nasty problem with long path names.  Cscope and tags files
+        * can result in long paths and vi will request a continuation key from
+        * the user as soon as it starts the screen.  Unfortunately, the user
+        * has already typed ahead, and chaos results.  If we assume that the
+        * characters in the filenames and informational messages only take a
+        * single screen column each, we can trim the filename.
+        *
+        * XXX
+        * Status lines get put up at fairly awkward times.  For example, when
+        * you do a filter read (e.g., :read ! echo foo) in the top screen of a
+        * split screen, we have to repaint the status lines for all the screens
+        * below the top screen.  We don't want users having to enter continue
+        * characters for those screens.  Make it really hard to screw this up.
+        */
+       s = bp;
+       if (LF_ISSET(MSTAT_TRUNCATE) && len > sp->cols) {
+               for (; s < np && (*s != '/' || (size_t)(p - s) > sp->cols - 3); ++s);
+               if (s == np) {
+                       s = p - (sp->cols - 5);
+                       *--s = ' ';
+               }
+               *--s = '.';
+               *--s = '.';
+               *--s = '.';
+               len = p - s;
+       }
+
+       /* Flush any waiting ex messages. */
+       (void)ex_fflush(sp);
+
+       sp->wp->scr_msg(sp, M_INFO, s, len);
+
+       FREE_SPACE(sp, bp, blen);
+alloc_err:
+       return;
+}
+
+/*
+ * msg_open --
+ *     Open the message catalogs.
+ *
+ * PUBLIC: int msg_open __P((SCR *, const char *));
+ */
+int
+msg_open(SCR *sp, const char *file)
+{
+       /*
+        * !!!
+        * Assume that the first file opened is the system default, and that
+        * all subsequent ones user defined.  Only display error messages
+        * if we can't open the user defined ones -- it's useful to know if
+        * the system one wasn't there, but if nvi is being shipped with an
+        * installed system, the file will be there, if it's not, then the
+        * message will be repeated every time nvi is started up.
+        */
+       static int first = 1;
+       DB *db;
+       DBT data, key;
+       db_recno_t msgno;
+       char buf[MAXPATHLEN];
+       const char *p, *t;
+
+       if ((p = strrchr(file, '/')) != NULL && p[1] == '\0' &&
+           (((t = getenv("LC_MESSAGES")) != NULL && t[0] != '\0') ||
+           ((t = getenv("LANG")) != NULL && t[0] != '\0'))) {
+               (void)snprintf(buf, sizeof(buf), "%s%s", file, t);
+               p = buf;
+       } else
+               p = file;
+       if ((sp->db_error = db_create(&db, 0, 0)) != 0 ||
+           (sp->db_error = db->set_re_source(db, p)) != 0 ||
+           (sp->db_error = db_open(db, NULL, DB_RECNO, 0, 0)) != 0) {
+               if (first) {
+                       first = 0;
+                       return (1);
+               }
+               msgq_str(sp, M_DBERR, p, "%s");
+               return (1);
+       }
+
+       /*
+        * Test record 1 for the magic string.  The msgq call is here so
+        * the message catalog build finds it.
+        */
+#define        VMC     "VI_MESSAGE_CATALOG"
+       memset(&key, 0, sizeof(key));
+       key.data = &msgno;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       msgno = 1;
+       if ((sp->db_error = db->get(db, NULL, &key, &data, 0)) != 0 ||
+           data.size != sizeof(VMC) - 1 ||
+           memcmp(data.data, VMC, sizeof(VMC) - 1)) {
+               (void)db->close(db, DB_NOSYNC);
+               if (first) {
+                       first = 0;
+                       return (1);
+               }
+               msgq_str(sp, M_DBERR, p,
+                   "030|The file %s is not a message catalog");
+               return (1);
+       }
+       first = 0;
+
+       if (sp->gp->msg != NULL)
+               (void)sp->gp->msg->close(sp->gp->msg, DB_NOSYNC);
+       sp->gp->msg = db;
+       return (0);
+}
+
+/*
+ * msg_close --
+ *     Close the message catalogs.
+ *
+ * PUBLIC: void msg_close __P((GS *));
+ */
+void
+msg_close(GS *gp)
+{
+       if (gp->msg != NULL) {
+               (void)gp->msg->close(gp->msg, 0);
+               gp->msg = NULL;
+       }
+}
+
+/*
+ * msg_cont --
+ *     Return common continuation messages.
+ *
+ * PUBLIC: const char *msg_cmsg __P((SCR *, cmsg_t, size_t *));
+ */
+const char *
+msg_cmsg(SCR *sp, cmsg_t which, size_t *lenp)
+{
+       switch (which) {
+       case CMSG_CONF:
+               return (msg_cat(sp, "268|confirm? [ynq]", lenp));
+       case CMSG_CONT:
+               return (msg_cat(sp, "269|Press any key to continue: ", lenp));
+       case CMSG_CONT_EX:
+               return (msg_cat(sp,
+           "270|Press any key to continue [: to enter more ex commands]: ",
+                   lenp));
+       case CMSG_CONT_R:
+               return (msg_cat(sp, "161|Press Enter to continue: ", lenp));
+       case CMSG_CONT_S:
+               return (msg_cat(sp, "275| cont?", lenp));
+       case CMSG_CONT_Q:
+               return (msg_cat(sp,
+                   "271|Press any key to continue [q to quit]: ", lenp));
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
+
+/*
+ * msg_cat --
+ *     Return a single message from the catalog, plus its length.
+ *
+ * !!!
+ * Only a single catalog message can be accessed at a time, if multiple
+ * ones are needed, they must be copied into local memory.
+ *
+ * PUBLIC: const char *msg_cat __P((SCR *, const char *, size_t *));
+ */
+const char *
+msg_cat(SCR *sp, const char *str, size_t *lenp)
+{
+       GS *gp;
+       DBT data, key;
+       db_recno_t msgno;
+
+       /*
+        * If it's not a catalog message, i.e. has doesn't have a leading
+        * number and '|' symbol, we're done.
+        */
+       if (isdigit((unsigned char)str[0]) &&
+           isdigit((unsigned char)str[1]) && isdigit((unsigned char)str[2]) &&
+           str[3] == '|') {
+               memset(&key, 0, sizeof(key));
+               key.data = &msgno;
+               key.size = sizeof(db_recno_t);
+               memset(&data, 0, sizeof(data));
+               msgno = atoi(str);
+
+               /*
+                * XXX
+                * Really sleazy hack -- we put an extra character on the
+                * end of the format string, and then we change it to be
+                * the nul termination of the string.  There ought to be
+                * a better way.  Once we can allocate multiple temporary
+                * memory buffers, maybe we can use one of them instead.
+                */
+               gp = sp == NULL ? NULL : sp->gp;
+               if (gp != NULL && gp->msg != NULL &&
+                   gp->msg->get(gp->msg, NULL, &key, &data, 0) == 0 &&
+                   data.size != 0) {
+                       if (lenp != NULL)
+                               *lenp = data.size - 1;
+                       ((char *)data.data)[data.size - 1] = '\0';
+                       return (data.data);
+               }
+               str = &str[4];
+       }
+       if (lenp != NULL)
+               *lenp = strlen(str);
+       return (str);
+}
+
+/*
+ * msg_print --
+ *     Return a printable version of a string, in allocated memory.
+ *
+ * PUBLIC: char *msg_print __P((SCR *, const char *, int *));
+ */
+char *
+msg_print(SCR *sp, const char *s, int *needfree)
+{
+       size_t blen, nlen;
+       const char *cp;
+       char *bp, *ep, *p;
+       unsigned char *t;
+
+       *needfree = 0;
+
+       for (cp = s; *cp != '\0'; ++cp)
+               if (!isprint((unsigned char)*cp))
+                       break;
+       if (*cp == '\0')
+               return ((char *)__UNCONST(s));  /* SAFE: needfree set to 0. */
+
+       nlen = 0;
+       if (0) {
+retry:         if (sp == NULL)
+                       free(bp);
+               else
+                       FREE_SPACE(sp, bp, blen);
+               *needfree = 0;
+       }
+       nlen += 256;
+       if (sp == NULL) {
+               if ((bp = malloc(nlen)) == NULL)
+                       goto alloc_err;
+       } else
+               GET_SPACE_GOTOC(sp, bp, blen, nlen);
+       if (0) {
+alloc_err:     return __UNCONST("");
+       }
+       *needfree = 1;
+
+       for (p = bp, ep = (bp + blen) - 1, cp = s; *cp != '\0' && p < ep; ++cp)
+               for (t = KEY_NAME(sp, *cp); *t != '\0' && p < ep; *p++ = *t++);
+       if (p == ep)
+               goto retry;
+       *p = '\0';
+       return (bp);
+}
diff --git a/dist/nvi/common/msg.h b/dist/nvi/common/msg.h
new file mode 100644 (file)
index 0000000..ad1c677
--- /dev/null
@@ -0,0 +1,67 @@
+/*     $NetBSD: msg.h,v 1.1.1.2 2008/05/18 14:29:48 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: msg.h,v 10.11 2000/04/21 21:26:19 skimo Exp (Berkeley) Date: 2000/04/21 21:26:19
+ */
+
+/*
+ * Common messages (continuation or confirmation).
+ */
+typedef enum {
+       CMSG_CONF, CMSG_CONT, CMSG_CONT_EX,
+       CMSG_CONT_R, CMSG_CONT_S, CMSG_CONT_Q } cmsg_t;
+
+/*
+ * Message types.
+ *
+ * !!!
+ * In historical vi, O_VERBOSE didn't exist, and O_TERSE made the error
+ * messages shorter.  In this implementation, O_TERSE has no effect and
+ * O_VERBOSE results in informational displays about common errors, for
+ * naive users.
+ *
+ * M_NONE      Display to the user, no reformatting, no nothing.
+ *
+ * M_BERR      Error: M_ERR if O_VERBOSE, else bell.
+ * M_ERR       Error: Display in inverse video.
+ * M_INFO       Info: Display in normal video.
+ * M_SYSERR    Error: M_ERR, using strerror(3) message.
+ * M_VINFO      Info: M_INFO if O_VERBOSE, else ignore.
+ *
+ * The underlying message display routines only need to know about M_NONE,
+ * M_ERR and M_INFO -- all the other message types are converted into one
+ * of them by the message routines.
+ */
+typedef enum {
+       M_NONE = 1, M_BERR, M_ERR, M_INFO, M_SYSERR, M_VINFO, M_DBERR } mtype_t;
+
+/*
+ * There are major problems with error messages being generated by routines
+ * preparing the screen to display error messages.  It's possible for the
+ * editor to generate messages before we have a screen in which to display
+ * them, or during the transition between ex (and vi startup) and a true vi.
+ * There's a queue in the global area to hold them.
+ *
+ * If SC_EX/SC_VI is set, that's the mode that the editor is in.  If the flag
+ * S_SCREEN_READY is set, that means that the screen is prepared to display
+ * messages.
+ */
+typedef struct _msgh MSGH;     /* MSGS list head structure. */
+LIST_HEAD(_msgh, _msg);
+struct _msg {
+       LIST_ENTRY(_msg) q;     /* Linked list of messages. */
+       mtype_t  mtype;         /* Message type: M_NONE, M_ERR, M_INFO. */
+       char    *buf;           /* Message buffer. */
+       size_t   len;           /* Message length. */
+};
+
+/* Flags to msgq_status(). */
+#define        MSTAT_SHOWLAST  0x01    /* Show the line number of the last line. */
+#define        MSTAT_TRUNCATE  0x02    /* Truncate the file name if it's too long. */
diff --git a/dist/nvi/common/multibyte.h b/dist/nvi/common/multibyte.h
new file mode 100644 (file)
index 0000000..7a94d76
--- /dev/null
@@ -0,0 +1,108 @@
+/*     $NetBSD: multibyte.h,v 1.7 2011/11/23 15:43:39 tnozaki Exp $ */
+
+#ifndef MULTIBYTE_H
+#define MULTIBYTE_H
+
+/*
+ * Ex/vi commands are generally separated by whitespace characters.  We
+ * can't use the standard isspace(3) macro because it returns true for
+ * characters like ^K in the ASCII character set.  The 4.4BSD isblank(3)
+ * macro does exactly what we want, but it's not portable yet.
+ *
+ * XXX
+ * Note side effect, ch is evaluated multiple times.
+ */
+#define ISBLANK(c)     ((c) == ' ' || (c) == '\t')
+
+#define ISDIGIT(c)     ((c) >= '0' && (c) <= '9')
+#define ISXDIGIT(c)    (ISDIGIT(c) || \
+                        ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
+#define ISALPHA(c)     (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#define ISALNUM(c)     (ISALPHA(c) || ISDIGIT(c))
+
+/*
+ * Fundamental character types.
+ *
+ * CHAR_T       An integral type that can hold any character.
+ * ARG_CHAR_T   The type of a CHAR_T when passed as an argument using
+ *              traditional promotion rules.  It should also be able
+ *              to be compared against any CHAR_T for equality without
+ *              problems.
+ *
+ * If no integral type can hold a character, don't even try the port.
+ */
+
+#ifdef USE_WIDECHAR
+#include <wchar.h>
+#include <wctype.h>
+
+typedef wchar_t                RCHAR_T;
+#define REOF           WEOF
+typedef wchar_t                CHAR_T;
+typedef        wint_t          ARG_CHAR_T;
+typedef wint_t         UCHAR_T;
+
+#define STRLEN         wcslen
+#define STRTOL         wcstol
+#define STRTOUL                wcstoul
+#define SPRINTF                swprintf
+#define STRCMP         wcscmp
+#define STRPBRK                wcspbrk
+#define ISBLANK2       iswblank
+#define ISCNTRL                iswcntrl
+#define ISGRAPH                iswgraph
+#define ISLOWER                iswlower
+#define ISPUNCT                iswpunct
+#define ISSPACE                iswspace
+#define ISUPPER                iswupper
+#define TOLOWER                towlower
+#define TOUPPER                towupper
+#define STRSET         wmemset
+#define STRCHR         wcschr
+
+#define L(ch)          L ## ch
+#define WS             "%ls"
+#define WVS            "%*ls"
+#define WC             "%lc"
+
+#else
+#include <stdio.h>
+
+typedef        char            RCHAR_T;
+#define REOF           EOF
+typedef        char            CHAR_T;
+typedef        int             ARG_CHAR_T;
+typedef        unsigned char   UCHAR_T;
+
+#define STRLEN         strlen
+#define STRTOL         strtol
+#define STRTOUL                strtoul
+#define SPRINTF                snprintf
+#define STRCMP         strcmp
+#define STRPBRK                strpbrk
+#define ISBLANK2       isblank
+#define ISCNTRL                iscntrl
+#define ISGRAPH                isgraph
+#define ISLOWER                islower
+#define ISPUNCT                ispunct
+#define ISSPACE                isspace
+#define ISUPPER                isupper
+#define TOLOWER                tolower
+#define TOUPPER                toupper
+#define STRSET         memset
+#define STRCHR         strchr
+
+#define L(ch)          ch
+#define WS             "%s"
+#define WVS            "%*s"
+#define WC             "%c"
+
+#endif
+
+#define MEMCMP(to, from, n)                                                \
+       memcmp(to, from, (n) * sizeof(*(to)))
+#define        MEMMOVE(p, t, len)      memmove(p, t, (len) * sizeof(*(p)))
+#define        MEMCPY(p, t, len)       memcpy(p, t, (len) * sizeof(*(p)))
+#define SIZE(w)                (sizeof(w)/sizeof(*w))
+
+#endif
diff --git a/dist/nvi/common/nothread.c b/dist/nvi/common/nothread.c
new file mode 100644 (file)
index 0000000..446c3b0
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: nothread.c,v 1.1.1.2 2008/05/18 14:29:48 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 2000
+ *     Sven Verdoolaege.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: nothread.c,v 1.4 2000/07/22 14:52:37 skimo Exp (Berkeley) Date: 2000/07/22 14:52:37";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+static int vi_nothread_run __P((WIN *wp, void *(*fun)(void*), void *data));
+static int vi_nothread_lock __P((WIN *, void **));
+
+/*
+ * thread_init
+ *
+ * PUBLIC: void thread_init __P((GS *gp));
+ */
+void 
+thread_init(GS *gp)
+{
+       gp->run = vi_nothread_run;
+       gp->lock_init = vi_nothread_lock;
+       gp->lock_end = vi_nothread_lock;
+       gp->lock_try = vi_nothread_lock;
+       gp->lock_unlock = vi_nothread_lock;
+}
+
+static int
+vi_nothread_run(WIN *wp, void *(*fun)(void*), void *data)
+{
+       fun(data);
+       return 0;
+}
+
+static int 
+vi_nothread_lock (WIN * wp, void **lp)
+{
+       return 0;
+}
diff --git a/dist/nvi/common/options.awk b/dist/nvi/common/options.awk
new file mode 100644 (file)
index 0000000..0b81bb5
--- /dev/null
@@ -0,0 +1,21 @@
+#      Id: options.awk,v 10.1 1995/06/08 19:00:01 bostic Exp (Berkeley) Date: 1995/06/08 19:00:01
+/^\/\* O_[0-9A-Z_]*/ {
+       opt = $2
+       printf("#define %s %d\n", opt, cnt++)
+       ofs = FS
+       FS="\""
+       do getline
+       while ($1 != "  {L(")
+       FS=ofs
+       opt_name = $2
+       if (opt_name < prev_name) {
+               printf "missorted %s: \"%s\" < \"%s\"\n", opt, opt_name, prev_name >"/dev/stderr"
+               exit 1
+       }
+       prev_name = opt_name
+       next
+}
+END {
+       printf("#define O_OPTIONCOUNT %d\n", cnt);
+}
diff --git a/dist/nvi/common/options.c b/dist/nvi/common/options.c
new file mode 100644 (file)
index 0000000..90d252b
--- /dev/null
@@ -0,0 +1,1190 @@
+/*     $NetBSD: options.c,v 1.10 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: options.c,v 10.65 2002/01/18 22:34:43 skimo Exp (Berkeley) Date: 2002/01/18 22:34:43";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+#include "pathnames.h"
+
+static int              opts_abbcmp __P((const void *, const void *));
+static int              opts_cmp __P((const void *, const void *));
+static int              opts_print __P((SCR *, OPTLIST const *));
+
+#ifdef USE_WIDECHAR
+#define OPT_WC     0
+#else
+#define OPT_WC     (OPT_NOSAVE | OPT_NDISP)
+#endif
+
+/*
+ * O'Reilly noted options and abbreviations are from "Learning the VI Editor",
+ * Fifth Edition, May 1992.  There's no way of knowing what systems they are
+ * actually from.
+ *
+ * HPUX noted options and abbreviations are from "The Ultimate Guide to the
+ * VI and EX Text Editors", 1990.
+ *
+ * This list must be sorted...
+ */
+OPTLIST const optlist[] = {
+/* O_ALTWERASE   4.4BSD */
+       {L("altwerase"),        f_altwerase,    OPT_0BOOL,      0},
+/* O_AUTOINDENT            4BSD */
+       {L("autoindent"),       NULL,           OPT_0BOOL,      0},
+/* O_AUTOPRINT     4BSD */
+       {L("autoprint"),        NULL,           OPT_1BOOL,      0},
+/* O_AUTOWRITE     4BSD */
+       {L("autowrite"),        NULL,           OPT_0BOOL,      0},
+/* O_BACKUP      4.4BSD */
+       {L("backup"),   NULL,           OPT_STR,        0},
+/* O_BEAUTIFY      4BSD */
+       {L("beautify"), NULL,           OPT_0BOOL,      0},
+/* O_CDPATH      4.4BSD */
+       {L("cdpath"),   NULL,           OPT_STR,        0},
+/* O_CEDIT       4.4BSD */
+       {L("cedit"),    NULL,           OPT_STR,        0},
+/* O_COLUMNS     4.4BSD */
+       {L("columns"),  f_columns,      OPT_NUM,        OPT_NOSAVE},
+/* O_COMBINED */
+       {L("combined"), NULL,           OPT_0BOOL,      OPT_NOSET|OPT_WC},
+/* O_COMMENT     4.4BSD */
+       {L("comment"),  NULL,           OPT_0BOOL,      0},
+/* O_TMP_DIRECTORY         4BSD */
+       {L("directory"),        NULL,           OPT_STR,        0},
+/* O_EDCOMPATIBLE   4BSD */
+       {L("edcompatible"),NULL,                OPT_0BOOL,      0},
+/* O_ERRORBELLS            4BSD */
+       {L("errorbells"),       NULL,           OPT_0BOOL,      0},
+/* O_ESCAPETIME          4.4BSD */
+       {L("escapetime"),       NULL,           OPT_NUM,        0},
+/* O_EXPANDTAB   NetBSD 5.0 */
+       {L("expandtab"),        NULL,           OPT_0BOOL,      0},
+/* O_EXRC      System V (undocumented) */
+       {L("exrc"),     NULL,           OPT_0BOOL,      0},
+/* O_EXTENDED    4.4BSD */
+       {L("extended"), f_recompile,    OPT_0BOOL,      0},
+/* O_FILEC       4.4BSD */
+       {L("filec"),    NULL,           OPT_STR,        0},
+/* O_FILEENCODING */
+       {L("fileencoding"),f_encoding,  OPT_STR,        OPT_WC},
+/* O_FLASH         HPUX */
+       {L("flash"),    NULL,           OPT_1BOOL,      0},
+#ifdef GTAGS
+/* O_GTAGSMODE     FreeBSD/NetBSD */
+       {L("gtagsmode"),NULL,           OPT_0BOOL,      0},
+#endif
+/* O_HARDTABS      4BSD */
+       {L("hardtabs"), NULL,           OPT_NUM,        0},
+/* O_ICLOWER     4.4BSD */
+       {L("iclower"),  f_recompile,    OPT_0BOOL,      0},
+/* O_IGNORECASE            4BSD */
+       {L("ignorecase"),       f_recompile,    OPT_0BOOL,      0},
+/* O_INPUTENCODING */
+       {L("inputencoding"),f_encoding, OPT_STR,        OPT_WC},
+/* O_KEYTIME     4.4BSD */
+       {L("keytime"),  NULL,           OPT_NUM,        0},
+/* O_LEFTRIGHT   4.4BSD */
+       {L("leftright"),        f_reformat,     OPT_0BOOL,      0},
+/* O_LINES       4.4BSD */
+       {L("lines"),    f_lines,        OPT_NUM,        OPT_NOSAVE},
+/* O_LISP          4BSD
+ *     XXX
+ *     When the lisp option is implemented, delete the OPT_NOSAVE flag,
+ *     so that :mkexrc dumps it.
+ */
+       {L("lisp"),     f_lisp,         OPT_0BOOL,      OPT_NOSAVE},
+/* O_LIST          4BSD */
+       {L("list"),     f_reformat,     OPT_0BOOL,      0},
+/* O_LOCKFILES   4.4BSD
+ *     XXX
+ *     Locking isn't reliable enough over NFS to require it, in addition,
+ *     it's a serious startup performance problem over some remote links.
+ */
+       {L("lock"),     NULL,           OPT_1BOOL,      0},
+/* O_MAGIC         4BSD */
+       {L("magic"),    NULL,           OPT_1BOOL,      0},
+/* O_MATCHCHARS          netbsd 2.0 */
+       {L("matchchars"),       NULL,           OPT_STR,        OPT_PAIRS},
+/* O_MATCHTIME   4.4BSD */
+       {L("matchtime"),        NULL,           OPT_NUM,        0},
+/* O_MESG          4BSD */
+       {L("mesg"),     NULL,           OPT_1BOOL,      0},
+/* O_MODELINE      4BSD
+ *     !!!
+ *     This has been documented in historical systems as both "modeline"
+ *     and as "modelines".  Regardless of the name, this option represents
+ *     a security problem of mammoth proportions, not to mention a stunning
+ *     example of what your intro CS professor referred to as the perils of
+ *     mixing code and data.  Don't add it, or I will kill you.
+ */
+       {L("modeline"), NULL,           OPT_0BOOL,      OPT_NOSET},
+/* O_MSGCAT      4.4BSD */
+       {L("msgcat"),   f_msgcat,       OPT_STR,        0},
+/* O_NOPRINT     4.4BSD */
+       {L("noprint"),  f_print,        OPT_STR,        0},
+/* O_NUMBER        4BSD */
+       {L("number"),   f_reformat,     OPT_0BOOL,      0},
+/* O_OCTAL       4.4BSD */
+       {L("octal"),    f_print,        OPT_0BOOL,      0},
+/* O_OPEN          4BSD */
+       {L("open"),     NULL,           OPT_1BOOL,      0},
+/* O_OPTIMIZE      4BSD */
+       {L("optimize"), NULL,           OPT_1BOOL,      0},
+/* O_PARAGRAPHS            4BSD */
+       {L("paragraphs"), NULL,         OPT_STR,        OPT_PAIRS},
+/* O_PATH        4.4BSD */
+       {L("path"),     NULL,           OPT_STR,        0},
+/* O_PRINT       4.4BSD */
+       {L("print"),    f_print,        OPT_STR,        0},
+/* O_PROMPT        4BSD */
+       {L("prompt"),   NULL,           OPT_1BOOL,      0},
+/* O_READONLY      4BSD (undocumented) */
+       {L("readonly"), f_readonly,     OPT_0BOOL,      OPT_ALWAYS},
+/* O_RECDIR      4.4BSD */
+       {L("recdir"),   NULL,           OPT_STR,        0},
+/* O_REDRAW        4BSD */
+       {L("redraw"),   NULL,           OPT_0BOOL,      0},
+/* O_REMAP         4BSD */
+       {L("remap"),    NULL,           OPT_1BOOL,      0},
+/* O_REPORT        4BSD */
+       {L("report"),   NULL,           OPT_NUM,        0},
+/* O_RULER       4.4BSD */
+       {L("ruler"),    NULL,           OPT_0BOOL,      0},
+/* O_SCROLL        4BSD */
+       {L("scroll"),   NULL,           OPT_NUM,        0},
+/* O_SEARCHINCR          4.4BSD */
+       {L("searchincr"),       NULL,           OPT_0BOOL,      0},
+/* O_SECTIONS      4BSD */
+       {L("sections"), NULL,           OPT_STR,        OPT_PAIRS},
+/* O_SECURE      4.4BSD */
+       {L("secure"),   NULL,           OPT_0BOOL,      OPT_NOUNSET},
+/* O_SHELL         4BSD */
+       {L("shell"),    NULL,           OPT_STR,        0},
+/* O_SHELLMETA   4.4BSD */
+       {L("shellmeta"),        NULL,           OPT_STR,        0},
+/* O_SHIFTWIDTH            4BSD */
+       {L("shiftwidth"),       NULL,           OPT_NUM,        OPT_NOZERO},
+/* O_SHOWMATCH     4BSD */
+       {L("showmatch"),        NULL,           OPT_0BOOL,      0},
+/* O_SHOWMODE    4.4BSD */
+       {L("showmode"), NULL,           OPT_0BOOL,      0},
+/* O_SIDESCROLL          4.4BSD */
+       {L("sidescroll"),       NULL,           OPT_NUM,        OPT_NOZERO},
+/* O_SLOWOPEN      4BSD  */
+       {L("slowopen"), NULL,           OPT_0BOOL,      0},
+/* O_SOURCEANY     4BSD (undocumented)
+ *     !!!
+ *     Historic vi, on startup, source'd $HOME/.exrc and ./.exrc, if they
+ *     were owned by the user.  The sourceany option was an undocumented
+ *     feature of historic vi which permitted the startup source'ing of
+ *     .exrc files the user didn't own.  This is an obvious security problem,
+ *     and we ignore the option.
+ */
+       {L("sourceany"),        NULL,           OPT_0BOOL,      OPT_NOSET},
+/* O_TABSTOP       4BSD */
+       {L("tabstop"),  f_reformat,     OPT_NUM,        OPT_NOZERO},
+/* O_TAGLENGTH     4BSD */
+       {L("taglength"),        NULL,           OPT_NUM,        0},
+/* O_TAGS          4BSD */
+       {L("tags"),     NULL,           OPT_STR,        0},
+/* O_TERM          4BSD
+ *     !!!
+ *     By default, the historic vi always displayed information about two
+ *     options, redraw and term.  Term seems sufficient.
+ */
+       {L("term"),     NULL,           OPT_STR,        OPT_ADISP|OPT_NOSAVE},
+/* O_TERSE         4BSD */
+       {L("terse"),    NULL,           OPT_0BOOL,      0},
+/* O_TILDEOP      4.4BSD */
+       {L("tildeop"),  NULL,           OPT_0BOOL,      0},
+/* O_TIMEOUT       4BSD (undocumented) */
+       {L("timeout"),  NULL,           OPT_1BOOL,      0},
+/* O_TTYWERASE   4.4BSD */
+       {L("ttywerase"),        f_ttywerase,    OPT_0BOOL,      0},
+/* O_VERBOSE     4.4BSD */
+       {L("verbose"),  NULL,           OPT_0BOOL,      0},
+/* O_W1200         4BSD */
+       {L("w1200"),    f_w1200,        OPT_NUM,        OPT_NDISP|OPT_NOSAVE},
+/* O_W300          4BSD */
+       {L("w300"),     f_w300,         OPT_NUM,        OPT_NDISP|OPT_NOSAVE},
+/* O_W9600         4BSD */
+       {L("w9600"),    f_w9600,        OPT_NUM,        OPT_NDISP|OPT_NOSAVE},
+/* O_WARN          4BSD */
+       {L("warn"),     NULL,           OPT_1BOOL,      0},
+/* O_WINDOW        4BSD */
+       {L("window"),   f_window,       OPT_NUM,        0},
+/* O_WINDOWNAME            4BSD */
+       {L("windowname"),       NULL,           OPT_0BOOL,      0},
+/* O_WRAPLEN     4.4BSD */
+       {L("wraplen"),  NULL,           OPT_NUM,        0},
+/* O_WRAPMARGIN            4BSD */
+       {L("wrapmargin"),       NULL,           OPT_NUM,        0},
+/* O_WRAPSCAN      4BSD */
+       {L("wrapscan"), NULL,           OPT_1BOOL,      0},
+/* O_WRITEANY      4BSD */
+       {L("writeany"), NULL,           OPT_0BOOL,      0},
+       {NULL,          NULL,           OPT_NUM,        0},
+};
+
+typedef struct abbrev {
+        const CHAR_T *name;
+        int offset;
+} OABBREV;
+
+static OABBREV const abbrev[] = {
+       {L("ai"),       O_AUTOINDENT},          /*     4BSD */
+       {L("ap"),       O_AUTOPRINT},           /*     4BSD */
+       {L("aw"),       O_AUTOWRITE},           /*     4BSD */
+       {L("bf"),       O_BEAUTIFY},            /*     4BSD */
+       {L("co"),       O_COLUMNS},             /*   4.4BSD */
+       {L("dir"),      O_TMP_DIRECTORY},       /*     4BSD */
+       {L("eb"),       O_ERRORBELLS},          /*     4BSD */
+       {L("ed"),       O_EDCOMPATIBLE},        /*     4BSD */
+       {L("et"),       O_EXPANDTAB},           /* NetBSD 5.0 */
+       {L("ex"),       O_EXRC},                /* System V (undocumented) */
+#ifdef GTAGS
+       {L("gt"),       O_GTAGSMODE},           /* FreeBSD, NetBSD */
+#endif
+       {L("fe"),       O_FILEENCODING},
+       {L("ht"),       O_HARDTABS},            /*     4BSD */
+       {L("ic"),       O_IGNORECASE},          /*     4BSD */
+       {L("ie"),       O_INPUTENCODING},
+       {L("li"),       O_LINES},               /*   4.4BSD */
+       {L("modelines"),        O_MODELINE},            /*     HPUX */
+       {L("nu"),       O_NUMBER},              /*     4BSD */
+       {L("opt"),      O_OPTIMIZE},            /*     4BSD */
+       {L("para"),     O_PARAGRAPHS},          /*     4BSD */
+       {L("re"),       O_REDRAW},              /* O'Reilly */
+       {L("ro"),       O_READONLY},            /*     4BSD (undocumented) */
+       {L("scr"),      O_SCROLL},              /*     4BSD (undocumented) */
+       {L("sect"),     O_SECTIONS},            /* O'Reilly */
+       {L("sh"),       O_SHELL},               /*     4BSD */
+       {L("slow"),     O_SLOWOPEN},            /*     4BSD */
+       {L("sm"),       O_SHOWMATCH},           /*     4BSD */
+       {L("smd"),      O_SHOWMODE},            /*     4BSD */
+       {L("sw"),       O_SHIFTWIDTH},          /*     4BSD */
+       {L("tag"),      O_TAGS},                /*     4BSD (undocumented) */
+       {L("tl"),       O_TAGLENGTH},           /*     4BSD */
+       {L("to"),       O_TIMEOUT},             /*     4BSD (undocumented) */
+       {L("ts"),       O_TABSTOP},             /*     4BSD */
+       {L("tty"),      O_TERM},                /*     4BSD (undocumented) */
+       {L("ttytype"),  O_TERM},                /*     4BSD (undocumented) */
+       {L("w"),        O_WINDOW},              /* O'Reilly */
+       {L("wa"),       O_WRITEANY},            /*     4BSD */
+       {L("wi"),       O_WINDOW},              /*     4BSD (undocumented) */
+       {L("wl"),       O_WRAPLEN},             /*   4.4BSD */
+       {L("wm"),       O_WRAPMARGIN},          /*     4BSD */
+       {L("ws"),       O_WRAPSCAN},            /*     4BSD */
+       {NULL,          0},
+};
+
+/*
+ * opts_init --
+ *     Initialize some of the options.
+ *
+ * PUBLIC: int opts_init __P((SCR *, int *));
+ */
+int
+opts_init(SCR *sp, int *oargs)
+{
+       ARGS *argv[2], a, b;
+       OPTLIST const *op;
+       u_long isset, v;
+       int cnt, optindx = 0;
+       char *s;
+       CHAR_T b2[1024];
+
+       if (sizeof optlist / sizeof optlist[0] - 1 != O_OPTIONCOUNT) {
+               fprintf(stderr, "vi: option table size error (%d != %d)\n",
+                   (int)(sizeof optlist / sizeof optlist[0] - 1),
+                   O_OPTIONCOUNT);
+               exit(1);
+       }
+
+       a.bp = b2;
+       b.bp = NULL;
+       a.len = b.len = 0;
+       argv[0] = &a;
+       argv[1] = &b;
+
+       /* Set numeric and string default values. */
+#define        OI(indx, str) {                                                 \
+       a.len = STRLEN(str);                                            \
+       if ((const CHAR_T*)str != b2)/* GCC puts strings in text-space. */\
+               (void)MEMCPY(b2, str, a.len+1);                         \
+       if (opts_set(sp, argv, NULL)) {                                 \
+                optindx = indx;                                        \
+               goto err;                                               \
+       }                                                               \
+}
+       /*
+        * Indirect global options to global space.  Specifically, set up
+        * terminal, lines, columns first, they're used by other options.
+        * Note, don't set the flags until we've set up the indirection.
+        */
+       if (o_set(sp, O_TERM, 0, NULL, GO_TERM))
+               goto err;
+       F_SET(&sp->opts[O_TERM], OPT_GLOBAL);
+       if (o_set(sp, O_LINES, 0, NULL, GO_LINES))
+               goto err;
+       F_SET(&sp->opts[O_LINES], OPT_GLOBAL);
+       if (o_set(sp, O_COLUMNS, 0, NULL, GO_COLUMNS))
+               goto err;
+       F_SET(&sp->opts[O_COLUMNS], OPT_GLOBAL);
+       if (o_set(sp, O_SECURE, 0, NULL, GO_SECURE))
+               goto err;
+       F_SET(&sp->opts[O_SECURE], OPT_GLOBAL);
+
+       /* Initialize string values. */
+       (void)SPRINTF(b2, SIZE(b2),
+           L("cdpath=%s"), (s = getenv("CDPATH")) == NULL ? ":" : s);
+       OI(O_CDPATH, b2);
+
+       /*
+        * !!!
+        * Vi historically stored temporary files in /var/tmp.  We store them
+        * in /tmp by default, hoping it's a memory based file system.  There
+        * are two ways to change this -- the user can set either the directory
+        * option or the TMPDIR environmental variable.
+        */
+       (void)SPRINTF(b2, SIZE(b2),
+           L("directory=%s"), (s = getenv("TMPDIR")) == NULL ? _PATH_TMP : s);
+       OI(O_TMP_DIRECTORY, b2);
+       OI(O_ESCAPETIME, L("escapetime=1"));
+       OI(O_KEYTIME, L("keytime=6"));
+       OI(O_MATCHCHARS, L("matchchars=()[]{}<>"));
+       OI(O_MATCHTIME, L("matchtime=7"));
+       (void)SPRINTF(b2, SIZE(b2), L("msgcat=%s"), _PATH_MSGCAT);
+       OI(O_MSGCAT, b2);
+       OI(O_REPORT, L("report=5"));
+       OI(O_PARAGRAPHS, L("paragraphs=IPLPPPQPP LIpplpipbp"));
+       (void)SPRINTF(b2, SIZE(b2), L("path=%s"), "");
+       OI(O_PATH, b2);
+       (void)SPRINTF(b2, SIZE(b2), L("recdir=%s"), _PATH_PRESERVE);
+       OI(O_RECDIR, b2);
+       OI(O_SECTIONS, L("sections=NHSHH HUnhsh"));
+       (void)SPRINTF(b2, SIZE(b2),
+           L("shell=%s"), (s = getenv("SHELL")) == NULL ? _PATH_BSHELL : s);
+       OI(O_SHELL, b2);
+       OI(O_SHELLMETA, L("shellmeta=~{[*?$`'\"\\"));
+       OI(O_SHIFTWIDTH, L("shiftwidth=8"));
+       OI(O_SIDESCROLL, L("sidescroll=16"));
+       OI(O_TABSTOP, L("tabstop=8"));
+       (void)SPRINTF(b2, SIZE(b2), L("tags=%s"), _PATH_TAGS);
+       OI(O_TAGS, b2);
+
+       /*
+        * XXX
+        * Initialize O_SCROLL here, after term; initializing term should
+        * have created a LINES/COLUMNS value.
+        */
+       if ((v = (O_VAL(sp, O_LINES) - 1) / 2) == 0)
+               v = 1;
+       (void)SPRINTF(b2, SIZE(b2), L("scroll=%ld"), v);
+       OI(O_SCROLL, b2);
+
+       /*
+        * The default window option values are:
+        *              8 if baud rate <=  600
+        *             16 if baud rate <= 1200
+        *      LINES - 1 if baud rate  > 1200
+        *
+        * Note, the windows option code will correct any too-large value
+        * or when the O_LINES value is 1.
+        */
+       if (sp->gp->scr_baud(sp, &v))
+               return (1);
+       if (v <= 600)
+               v = 8;
+       else if (v <= 1200)
+               v = 16;
+       else if ((v = O_VAL(sp, O_LINES) - 1) == 0)
+               v = 1;
+
+       (void)SPRINTF(b2, SIZE(b2), L("window=%lu"), v);
+       OI(O_WINDOW, b2);
+
+       /*
+        * Set boolean default values, and copy all settings into the default
+        * information.  OS_NOFREE is set, we're copying, not replacing.
+        */
+       for (op = optlist, cnt = 0; op->name != NULL; ++op, ++cnt)
+               switch (op->type) {
+               case OPT_0BOOL:
+                       break;
+               case OPT_1BOOL:
+                       O_SET(sp, cnt);
+                       O_D_SET(sp, cnt);
+                       break;
+               case OPT_NUM:
+                       o_set(sp, cnt, OS_DEF, NULL, O_VAL(sp, cnt));
+                       break;
+               case OPT_STR:
+                       if (O_STR(sp, cnt) != NULL && o_set(sp, cnt,
+                           OS_DEF | OS_NOFREE | OS_STRDUP, O_STR(sp, cnt), 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+
+       /*
+        * !!!
+        * Some options can be initialized by the command name or the
+        * command-line arguments.  They don't set the default values,
+        * it's historic practice.
+        */
+       for (; *oargs != -1; ++oargs)
+               OI(*oargs, optlist[*oargs].name);
+#undef OI
+
+       /*
+        * Inform the underlying screen of the initial values of the
+        * edit options.
+        */
+       for (op = optlist, cnt = 0; op->name != NULL; ++op, ++cnt) {
+               isset = O_ISSET(sp, cnt);
+               (void)sp->gp->scr_optchange(sp, cnt, O_STR(sp, cnt), &isset);
+       }
+       return (0);
+
+err:   msgq_wstr(sp, M_ERR, optlist[optindx].name,
+           "031|Unable to set default %s option");
+       return (1);
+}
+
+/*
+ * opts_set --
+ *     Change the values of one or more options.
+ *
+ * PUBLIC: int opts_set __P((SCR *, ARGS *[], char *));
+ */
+int
+opts_set(SCR *sp, ARGS **argv, const char *usage)
+{
+       enum optdisp disp;
+       enum nresult nret;
+       OPTLIST const *op;
+       OPTION *spo;
+       u_long isset, turnoff, value;
+       int ch, equals, nf, nf2, offset, qmark, rval;
+       CHAR_T *endp, *name, *p, *sep;
+       char *p2, *t2;
+       const char *np;
+       size_t nlen;
+
+       disp = NO_DISPLAY;
+       for (rval = 0; argv[0]->len != 0; ++argv) {
+               /*
+                * The historic vi dumped the options for each occurrence of
+                * "all" in the set list.  Puhleeze.
+                */
+               if (!STRCMP(argv[0]->bp, L("all"))) {
+                       disp = ALL_DISPLAY;
+                       continue;
+               }
+
+               /* Find equals sign or question mark. */
+               for (sep = NULL, equals = qmark = 0,
+                   p = name = argv[0]->bp; (ch = *p) != '\0'; ++p)
+                       if (ch == '=' || ch == '?') {
+                               if (p == name) {
+                                       if (usage != NULL)
+                                               msgq(sp, M_ERR,
+                                                   "032|Usage: %s", usage);
+                                       return (1);
+                               }
+                               sep = p;
+                               if (ch == '=')
+                                       equals = 1;
+                               else
+                                       qmark = 1;
+                               break;
+                       }
+
+               turnoff = 0;
+               op = NULL;
+               if (sep != NULL)
+                       *sep++ = '\0';
+
+               /* Search for the name, then name without any leading "no". */
+               if ((op = opts_search(name)) == NULL &&
+                   name[0] == L('n') && name[1] == L('o')) {
+                       turnoff = 1;
+                       name += 2;
+                       op = opts_search(name);
+               }
+               if (op == NULL) {
+                       opts_nomatch(sp, name);
+                       rval = 1;
+                       continue;
+               }
+
+               /* Find current option values. */
+               offset = op - optlist;
+               spo = sp->opts + offset;
+
+               /*
+                * !!!
+                * Historically, the question mark could be a separate
+                * argument.
+                */
+               if (!equals && !qmark &&
+                   argv[1]->len == 1 && argv[1]->bp[0] == '?') {
+                       ++argv;
+                       qmark = 1;
+               }
+
+               /* Set name, value. */
+               switch (op->type) {
+               case OPT_0BOOL:
+               case OPT_1BOOL:
+                       /* Some options may not be reset. */
+                       if (F_ISSET(op, OPT_NOUNSET) && turnoff) {
+                               msgq_wstr(sp, M_ERR, name,
+                           "291|set: the %s option may not be turned off");
+                               rval = 1;
+                               break;
+                       }
+
+                       /* Some options may not be set. */
+                       if (F_ISSET(op, OPT_NOSET) && !turnoff) {
+                               msgq_wstr(sp, M_ERR, name,
+                           "313|set: the %s option may never be turned on");
+                               rval = 1;
+                               break;
+                       }
+
+                       if (equals) {
+                               msgq_wstr(sp, M_ERR, name,
+                           "034|set: [no]%s option doesn't take a value");
+                               rval = 1;
+                               break;
+                       }
+                       if (qmark) {
+                               if (!disp)
+                                       disp = SELECT_DISPLAY;
+                               F_SET(spo, OPT_SELECTED);
+                               break;
+                       }
+
+                       /*
+                        * Do nothing if the value is unchanged, the underlying
+                        * functions can be expensive.
+                        */
+                       isset = !turnoff;
+                       if (!F_ISSET(op, OPT_ALWAYS)) {
+                               if (isset) {
+                                       if (O_ISSET(sp, offset))
+                                               break;
+                               } else
+                                       if (!O_ISSET(sp, offset))
+                                               break;
+                       }
+
+                       /* Report to subsystems. */
+                       if ((op->func != NULL &&
+                           op->func(sp, spo, NULL, &isset)) ||
+                           ex_optchange(sp, offset, NULL, &isset) ||
+                           v_optchange(sp, offset, NULL, &isset) ||
+                           sp->gp->scr_optchange(sp, offset, NULL, &isset)) {
+                               rval = 1;
+                               break;
+                       }
+
+                       /* Set the value. */
+                       if (isset)
+                               O_SET(sp, offset);
+                       else
+                               O_CLR(sp, offset);
+                       break;
+               case OPT_NUM:
+                       if (turnoff) {
+                               msgq_wstr(sp, M_ERR, name,
+                                   "035|set: %s option isn't a boolean");
+                               rval = 1;
+                               break;
+                       }
+                       if (qmark || !equals) {
+                               if (!disp)
+                                       disp = SELECT_DISPLAY;
+                               F_SET(spo, OPT_SELECTED);
+                               break;
+                       }
+
+                       if (!ISDIGIT((UCHAR_T)sep[0]))
+                               goto badnum;
+                       if ((nret =
+                           nget_uslong(sp, &value, sep, &endp, 10)) != NUM_OK) {
+                               INT2CHAR(sp, name, STRLEN(name) + 1, 
+                                            np, nlen);
+                               p2 = msg_print(sp, np, &nf);
+                               INT2CHAR(sp, sep, STRLEN(sep) + 1, 
+                                            np, nlen);
+                               t2 = msg_print(sp, np, &nf2);
+                               switch (nret) {
+                               case NUM_ERR:
+                                       msgq(sp, M_SYSERR,
+                                           "036|set: %s option: %s", p2, t2);
+                                       break;
+                               case NUM_OVER:
+                                       msgq(sp, M_ERR,
+                           "037|set: %s option: %s: value overflow", p2, t2);
+                                       break;
+                               case NUM_OK:
+                               case NUM_UNDER:
+                                       abort();
+                               }
+                               if (nf)
+                                       FREE_SPACE(sp, p2, 0);
+                               if (nf2)
+                                       FREE_SPACE(sp, t2, 0);
+                               rval = 1;
+                               break;
+                       }
+                       if (*endp && !ISBLANK(*endp)) {
+badnum:                                INT2CHAR(sp, name, STRLEN(name) + 1, 
+                                            np, nlen);
+                               p2 = msg_print(sp, np, &nf);
+                               INT2CHAR(sp, sep, STRLEN(sep) + 1, 
+                                            np, nlen);
+                               t2 = msg_print(sp, np, &nf2);
+                               msgq(sp, M_ERR,
+                   "038|set: %s option: %s is an illegal number", p2, t2);
+                               if (nf)
+                                       FREE_SPACE(sp, p2, 0);
+                               if (nf2)
+                                       FREE_SPACE(sp, t2, 0);
+                               rval = 1;
+                               break;
+                       }
+
+                       /* Some options may never be set to zero. */
+                       if (F_ISSET(op, OPT_NOZERO) && value == 0) {
+                               msgq_wstr(sp, M_ERR, name,
+                           "314|set: the %s option may never be set to 0");
+                               rval = 1;
+                               break;
+                       }
+
+                       /*
+                        * Do nothing if the value is unchanged, the underlying
+                        * functions can be expensive.
+                        */
+                       if (!F_ISSET(op, OPT_ALWAYS) &&
+                           O_VAL(sp, offset) == value)
+                               break;
+
+                       /* Report to subsystems. */
+                       INT2CHAR(sp, sep, STRLEN(sep) + 1, np, nlen);
+                       if ((op->func != NULL &&
+                           op->func(sp, spo, np, &value)) ||
+                           ex_optchange(sp, offset, np, &value) ||
+                           v_optchange(sp, offset, np, &value) ||
+                           sp->gp->scr_optchange(sp, offset, np, &value)) {
+                               rval = 1;
+                               break;
+                       }
+
+                       /* Set the value. */
+                       if (o_set(sp, offset, 0, NULL, value))
+                               rval = 1;
+                       break;
+               case OPT_STR:
+                       if (turnoff) {
+                               msgq_wstr(sp, M_ERR, name,
+                                   "039|set: %s option isn't a boolean");
+                               rval = 1;
+                               break;
+                       }
+                       if (qmark || !equals) {
+                               if (!disp)
+                                       disp = SELECT_DISPLAY;
+                               F_SET(spo, OPT_SELECTED);
+                               break;
+                       }
+
+                       /* Check for strings that must have even length */
+                       if (F_ISSET(op, OPT_PAIRS) && STRLEN(sep) & 1) {
+                               msgq_wstr(sp, M_ERR, name,
+                                   "047|set: the %s option must be in two character groups");
+                               rval = 1;
+                               break;
+                       }
+
+                       /*
+                        * Do nothing if the value is unchanged, the underlying
+                        * functions can be expensive.
+                        */
+                       INT2CHAR(sp, sep, STRLEN(sep) + 1, np, nlen);
+                       if (!F_ISSET(op, OPT_ALWAYS) &&
+                           O_STR(sp, offset) != NULL &&
+                           !strcmp(O_STR(sp, offset), np))
+                               break;
+
+                       /* Report to subsystems. */
+                       if ((op->func != NULL &&
+                           op->func(sp, spo, np, NULL)) ||
+                           ex_optchange(sp, offset, np, NULL) ||
+                           v_optchange(sp, offset, np, NULL) ||
+                           sp->gp->scr_optchange(sp, offset, np, NULL)) {
+                               rval = 1;
+                               break;
+                       }
+
+                       /* Set the value. */
+                       if (o_set(sp, offset, OS_STRDUP, np, 0))
+                               rval = 1;
+                       break;
+               default:
+                       abort();
+               }
+       }
+       if (disp != NO_DISPLAY)
+               opts_dump(sp, disp);
+       return (rval);
+}
+
+/*
+ * o_set --
+ *     Set an option's value.
+ *
+ * PUBLIC: int o_set __P((SCR *, int, u_int, const char *, u_long));
+ */
+int
+o_set(SCR *sp, int opt, u_int flags, const char *str, u_long val)
+{
+       OPTION *op;
+
+       /* Set a pointer to the options area. */
+       op = F_ISSET(&sp->opts[opt], OPT_GLOBAL) ?
+           &sp->gp->opts[sp->opts[opt].o_cur.val] : &sp->opts[opt];
+
+       /* Copy the string, if requested. */
+       if (LF_ISSET(OS_STRDUP) && (str = strdup(str)) == NULL) {
+               msgq(sp, M_SYSERR, NULL);
+               return (1);
+       }
+
+       /* Free the previous string, if requested, and set the value. */
+       if LF_ISSET(OS_DEF)
+               if (LF_ISSET(OS_STR | OS_STRDUP)) {
+                       if (!LF_ISSET(OS_NOFREE) && op->o_def.str != NULL)
+                               free(__UNCONST(op->o_def.str));
+                       op->o_def.str = str;
+               } else
+                       op->o_def.val = val;
+       else
+               if (LF_ISSET(OS_STR | OS_STRDUP)) {
+                       if (!LF_ISSET(OS_NOFREE) && op->o_cur.str != NULL)
+                               free(__UNCONST(op->o_cur.str));
+                       op->o_cur.str = str;
+               } else
+                       op->o_cur.val = val;
+       return (0);
+}
+
+/*
+ * opts_empty --
+ *     Return 1 if the string option is invalid, 0 if it's OK.
+ *
+ * PUBLIC: int opts_empty __P((SCR *, int, int));
+ */
+int
+opts_empty(SCR *sp, int off, int silent)
+{
+       const char *p;
+
+       if ((p = O_STR(sp, off)) == NULL || p[0] == '\0') {
+               if (!silent)
+                       msgq_wstr(sp, M_ERR, optlist[off].name,
+                           "305|No %s edit option specified");
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * opts_dump --
+ *     List the current values of selected options.
+ *
+ * PUBLIC: void opts_dump __P((SCR *, enum optdisp));
+ */
+void
+opts_dump(SCR *sp, enum optdisp type)
+{
+       OPTLIST const *op;
+       int base, b_num, cnt, col, colwidth, curlen, s_num;
+       int numcols, numrows, row;
+       int b_op[O_OPTIONCOUNT], s_op[O_OPTIONCOUNT];
+       char nbuf[20];
+
+       /*
+        * Options are output in two groups -- those that fit in a column and
+        * those that don't.  Output is done on 6 character "tab" boundaries
+        * for no particular reason.  (Since we don't output tab characters,
+        * we can ignore the terminal's tab settings.)  Ignore the user's tab
+        * setting because we have no idea how reasonable it is.
+        *
+        * Find a column width we can live with, testing from 10 columns to 1.
+        */
+       for (numcols = 10; numcols > 1; --numcols) {
+               colwidth = sp->cols / numcols & ~(STANDARD_TAB - 1);
+               if (colwidth >= 10) {
+                       colwidth =
+                           (colwidth + STANDARD_TAB) & ~(STANDARD_TAB - 1);
+                       numcols = sp->cols / colwidth;
+                       break;
+               }
+               colwidth = 0;
+       }
+
+       /*
+        * Get the set of options to list, entering them into
+        * the column list or the overflow list.
+        */
+       for (b_num = s_num = 0, op = optlist; op->name != NULL; ++op) {
+               cnt = op - optlist;
+
+               /* If OPT_NDISP set, it's never displayed. */
+               if (F_ISSET(op, OPT_NDISP))
+                       continue;
+
+               switch (type) {
+               case ALL_DISPLAY:               /* Display all. */
+                       break;
+               case CHANGED_DISPLAY:           /* Display changed. */
+                       /* If OPT_ADISP set, it's always "changed". */
+                       if (F_ISSET(op, OPT_ADISP))
+                               break;
+                       switch (op->type) {
+                       case OPT_0BOOL:
+                       case OPT_1BOOL:
+                       case OPT_NUM:
+                               if (O_VAL(sp, cnt) == O_D_VAL(sp, cnt))
+                                       continue;
+                               break;
+                       case OPT_STR:
+                               if (O_STR(sp, cnt) == O_D_STR(sp, cnt) ||
+                                   (O_D_STR(sp, cnt) != NULL &&
+                                   !strcmp(O_STR(sp, cnt), O_D_STR(sp, cnt))))
+                                       continue;
+                               break;
+                       }
+                       break;
+               case SELECT_DISPLAY:            /* Display selected. */
+                       if (!F_ISSET(&sp->opts[cnt], OPT_SELECTED))
+                               continue;
+                       break;
+               default:
+               case NO_DISPLAY:
+                       abort();
+               }
+               F_CLR(&sp->opts[cnt], OPT_SELECTED);
+
+               curlen = STRLEN(op->name);
+               switch (op->type) {
+               case OPT_0BOOL:
+               case OPT_1BOOL:
+                       if (!O_ISSET(sp, cnt))
+                               curlen += 2;
+                       break;
+               case OPT_NUM:
+                       (void)snprintf(nbuf,
+                           sizeof(nbuf), "%ld", O_VAL(sp, cnt));
+                       curlen += strlen(nbuf);
+                       break;
+               case OPT_STR:
+                       if (O_STR(sp, cnt) != NULL)
+                               curlen += strlen(O_STR(sp, cnt));
+                       curlen += 3;
+                       break;
+               }
+               /* Offset by 2 so there's a gap. */
+               if (curlen <= colwidth - 2)
+                       s_op[s_num++] = cnt;
+               else
+                       b_op[b_num++] = cnt;
+       }
+
+       if (s_num > 0) {
+               /* Figure out the number of rows. */
+               if (s_num > numcols) {
+                       numrows = s_num / numcols;
+                       if (s_num % numcols)
+                               ++numrows;
+               } else
+                       numrows = 1;
+
+               /* Display the options in sorted order. */
+               for (row = 0; row < numrows;) {
+                       for (base = row, col = 0; col < numcols; ++col) {
+                               cnt = opts_print(sp, &optlist[s_op[base]]);
+                               if ((base += numrows) >= s_num)
+                                       break;
+                               (void)ex_printf(sp, "%*s",
+                                   (int)(colwidth - cnt), "");
+                       }
+                       if (++row < numrows || b_num)
+                               (void)ex_puts(sp, "\n");
+               }
+       }
+
+       for (row = 0; row < b_num;) {
+               (void)opts_print(sp, &optlist[b_op[row]]);
+               if (++row < b_num)
+                       (void)ex_puts(sp, "\n");
+       }
+       (void)ex_puts(sp, "\n");
+}
+
+/*
+ * opts_print --
+ *     Print out an option.
+ */
+static int
+opts_print(SCR *sp, const OPTLIST *op)
+{
+       int curlen, offset;
+
+       curlen = 0;
+       offset = op - optlist;
+       switch (op->type) {
+       case OPT_0BOOL:
+       case OPT_1BOOL:
+               curlen += ex_printf(sp,
+                   "%s"WS, O_ISSET(sp, offset) ? "" : "no", op->name);
+               break;
+       case OPT_NUM:
+               curlen += ex_printf(sp, WS"=%ld", op->name, O_VAL(sp, offset));
+               break;
+       case OPT_STR:
+               curlen += ex_printf(sp, WS"=\"%s\"", op->name,
+                   O_STR(sp, offset) == NULL ? "" : O_STR(sp, offset));
+               break;
+       }
+       return (curlen);
+}
+
+/*
+ * opts_save --
+ *     Write the current configuration to a file.
+ *
+ * PUBLIC: int opts_save __P((SCR *, FILE *));
+ */
+int
+opts_save(SCR *sp, FILE *fp)
+{
+       OPTLIST const *op;
+       CHAR_T ch;
+       const CHAR_T *p;
+       char nch;
+       const char *np;
+       int cnt;
+
+       for (op = optlist; op->name != NULL; ++op) {
+               if (F_ISSET(op, OPT_NOSAVE))
+                       continue;
+               cnt = op - optlist;
+               switch (op->type) {
+               case OPT_0BOOL:
+               case OPT_1BOOL:
+                       if (O_ISSET(sp, cnt))
+                               (void)fprintf(fp, "set "WS"\n", op->name);
+                       else
+                               (void)fprintf(fp, "set no"WS"\n", op->name);
+                       break;
+               case OPT_NUM:
+                       (void)fprintf(fp,
+                           "set "WS"=%-3ld\n", op->name, O_VAL(sp, cnt));
+                       break;
+               case OPT_STR:
+                       if (O_STR(sp, cnt) == NULL)
+                               break;
+                       (void)fprintf(fp, "set ");
+                       for (p = op->name; (ch = *p) != L('\0'); ++p) {
+                               if (ISBLANK(ch) || ch == L('\\'))
+                                       (void)putc('\\', fp);
+                               fprintf(fp, WC, ch);
+                       }
+                       (void)putc('=', fp);
+                       for (np = O_STR(sp, cnt); (nch = *np) != '\0'; ++np) {
+                               if (isblank((unsigned char)nch) || nch == '\\')
+                                       (void)putc('\\', fp);
+                               (void)putc(nch, fp);
+                       }
+                       (void)putc('\n', fp);
+                       break;
+               }
+               if (ferror(fp)) {
+                       msgq(sp, M_SYSERR, NULL);
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+/* 
+ * opts_search --
+ *     Search for an option.
+ *
+ * PUBLIC: OPTLIST const *opts_search __P((CHAR_T *));
+ */
+OPTLIST const *
+opts_search(const CHAR_T *name)
+{
+       OPTLIST const *op, *found;
+       OABBREV atmp, *ap;
+       OPTLIST otmp;
+       size_t len;
+
+       /* Check list of abbreviations. */
+       atmp.name = name;
+       if ((ap = bsearch(&atmp, abbrev, sizeof(abbrev) / sizeof(OABBREV) - 1,
+           sizeof(OABBREV), opts_abbcmp)) != NULL)
+               return (optlist + ap->offset);
+
+       /* Check list of options. */
+       otmp.name = name;
+       if ((op = bsearch(&otmp, optlist, sizeof(optlist) / sizeof(OPTLIST) - 1,
+           sizeof(OPTLIST), opts_cmp)) != NULL)
+               return (op);
+               
+       /*
+        * Check to see if the name is the prefix of one (and only one)
+        * option.  If so, return the option.
+        */
+       len = STRLEN(name);
+       for (found = NULL, op = optlist; op->name != NULL; ++op) {
+               if (op->name[0] < name[0])
+                       continue;
+               if (op->name[0] > name[0])
+                       break;
+               if (!MEMCMP(op->name, name, len)) {
+                       if (found != NULL)
+                               return (NULL);
+                       found = op;
+               }
+       }
+       return (found);
+}
+
+/* 
+ * opts_nomatch --
+ *     Standard nomatch error message for options.
+ *
+ * PUBLIC: void opts_nomatch __P((SCR *, CHAR_T *));
+ */
+void
+opts_nomatch(SCR *sp, const CHAR_T *name)
+{
+       msgq_wstr(sp, M_ERR, name,
+           "033|set: no %s option: 'set all' gives all option values");
+}
+
+static int
+opts_abbcmp(const void *a, const void *b)
+{
+        return(STRCMP(((const OABBREV *)a)->name, ((const OABBREV *)b)->name));
+}
+
+static int
+opts_cmp(const void *a, const void *b)
+{
+        return(STRCMP(((const OPTLIST *)a)->name, ((const OPTLIST *)b)->name));
+}
+
+/*
+ * opts_copy --
+ *     Copy a screen's OPTION array.
+ *
+ * PUBLIC: int opts_copy __P((SCR *, SCR *));
+ */
+int
+opts_copy(SCR *orig, SCR *sp)
+{
+       int cnt, rval;
+
+       /* Copy most everything without change. */
+       memcpy(sp->opts, orig->opts, sizeof(orig->opts));
+
+       /* Copy the string edit options. */
+       for (cnt = rval = 0; cnt < O_OPTIONCOUNT; ++cnt) {
+               if (optlist[cnt].type != OPT_STR ||
+                   F_ISSET(&sp->opts[cnt], OPT_GLOBAL))
+                       continue;
+               /*
+                * If never set, or already failed, NULL out the entries --
+                * have to continue after failure, otherwise would have two
+                * screens referencing the same memory.
+                */
+               if (rval || O_STR(sp, cnt) == NULL) {
+                       o_set(sp, cnt, OS_NOFREE | OS_STR, NULL, 0);
+                       o_set(sp, cnt, OS_DEF | OS_NOFREE | OS_STR, NULL, 0);
+                       continue;
+               }
+
+               /* Copy the current string. */
+               if (o_set(sp, cnt, OS_NOFREE | OS_STRDUP, O_STR(sp, cnt), 0)) {
+                       o_set(sp, cnt, OS_DEF | OS_NOFREE | OS_STR, NULL, 0);
+                       goto nomem;
+               }
+
+               /* Copy the default string. */
+               if (O_D_STR(sp, cnt) != NULL && o_set(sp, cnt,
+                   OS_DEF | OS_NOFREE | OS_STRDUP, O_D_STR(sp, cnt), 0)) {
+nomem:                 msgq(orig, M_SYSERR, NULL);
+                       rval = 1;
+               }
+       }
+       return (rval);
+}
+
+/*
+ * opts_free --
+ *     Free all option strings
+ *
+ * PUBLIC: void opts_free __P((SCR *));
+ */
+void
+opts_free(SCR *sp)
+{
+       int cnt;
+
+       for (cnt = 0; cnt < O_OPTIONCOUNT; ++cnt) {
+               if (optlist[cnt].type != OPT_STR ||
+                   F_ISSET(&sp->opts[cnt], OPT_GLOBAL))
+                       continue;
+               if (O_STR(sp, cnt) != NULL)
+                       free(__UNCONST(O_STR(sp, cnt)));
+               if (O_D_STR(sp, cnt) != NULL)
+                       free(__UNCONST(O_D_STR(sp, cnt)));
+       }
+}
diff --git a/dist/nvi/common/options.h b/dist/nvi/common/options.h
new file mode 100644 (file)
index 0000000..1a5825f
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: options.h,v 1.3 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: options.h,v 10.20 2001/06/09 18:26:28 skimo Exp (Berkeley) Date: 2001/06/09 18:26:28
+ */
+
+/*
+ * Edit option information.  Historically, if you set a boolean or numeric
+ * edit option value to its "default" value, it didn't show up in the :set
+ * display, i.e. it wasn't considered "changed".  String edit options would
+ * show up as changed, regardless.  We maintain a parallel set of values
+ * which are the default values and never consider an edit option changed
+ * if it was reset to the default value.
+ *
+ * Macros to retrieve boolean, integral and string option values, and to
+ * set, clear and test boolean option values.  Some options (secure, lines,
+ * columns, terminal type) are global in scope, and are therefore stored
+ * in the global area.  The offset in the global options array is stored
+ * in the screen's value field.  This is set up when the options are first
+ * initialized.
+ */
+#define        O_V(sp, o, fld)                                                 \
+       (F_ISSET(&(sp)->opts[(o)], OPT_GLOBAL) ?                        \
+           (sp)->gp->opts[(sp)->opts[(o)].o_cur.val].fld :             \
+           (sp)->opts[(o)].fld)
+
+/* Global option macros. */
+#define        OG_CLR(gp, o)           ((gp)->opts[(o)].o_cur.val) = 0
+#define        OG_SET(gp, o)           ((gp)->opts[(o)].o_cur.val) = 1
+#define        OG_STR(gp, o)           ((gp)->opts[(o)].o_cur.str)
+#define        OG_VAL(gp, o)           ((gp)->opts[(o)].o_cur.val)
+#define        OG_ISSET(gp, o)         OG_VAL(gp, o)
+
+#define        OG_D_STR(gp, o)         ((gp)->opts[(o)].o_def.str)
+#define        OG_D_VAL(gp, o)         ((gp)->opts[(o)].o_def.val)
+
+/*
+ * Flags to o_set(); need explicit OS_STR as can be setting the value to
+ * NULL.
+ */
+#define        OS_DEF          0x01            /* Set the default value. */
+#define        OS_NOFREE       0x02            /* Don't free the old string. */
+#define        OS_STR          0x04            /* Set to string argument. */
+#define        OS_STRDUP       0x08            /* Copy then set to string argument. */
+
+struct _option {
+       union {
+               u_long   val;           /* Value or boolean. */
+               const char *str;        /* String. */
+       } o_cur;
+#define        O_CLR(sp, o)            o_set(sp, o, 0, NULL, 0)
+#define        O_SET(sp, o)            o_set(sp, o, 0, NULL, 1)
+#define        O_STR(sp, o)            O_V(sp, o, o_cur.str)
+#define        O_VAL(sp, o)            O_V(sp, o, o_cur.val)
+#define        O_ISSET(sp, o)          O_VAL(sp, o)
+
+       union {
+               u_long   val;           /* Value or boolean. */
+               const char *str;        /* String. */
+       } o_def;
+#define        O_D_CLR(sp, o)          o_set(sp, o, OS_DEF, NULL, 0)
+#define        O_D_SET(sp, o)          o_set(sp, o, OS_DEF, NULL, 1)
+#define        O_D_STR(sp, o)          O_V(sp, o, o_def.str)
+#define        O_D_VAL(sp, o)          O_V(sp, o, o_def.val)
+#define        O_D_ISSET(sp, o)        O_D_VAL(sp, o)
+
+#define        OPT_GLOBAL      0x01            /* Option is global. */
+#define        OPT_SELECTED    0x02            /* Selected for display. */
+       u_int8_t flags;
+};
+
+/* List of option names, associated update functions and information. */
+struct _optlist {
+       const CHAR_T *name;             /* Name. */
+                                       /* Change function. */
+       int     (*func) __P((SCR *, OPTION *, const char *, u_long *));
+                                       /* Type of object. */
+       enum { OPT_0BOOL, OPT_1BOOL, OPT_NUM, OPT_STR } type;
+
+#define        OPT_ADISP       0x001           /* Always display the option. */
+#define        OPT_ALWAYS      0x002           /* Always call the support function. */
+#define        OPT_NDISP       0x004           /* Never display the option. */
+#define        OPT_NOSAVE      0x008           /* Mkexrc command doesn't save. */
+#define        OPT_NOSET       0x010           /* Option may not be set. */
+#define        OPT_NOUNSET     0x020           /* Option may not be unset. */
+#define        OPT_NOZERO      0x040           /* Option may not be set to 0. */
+#define        OPT_PAIRS       0x080           /* String with even length */
+       u_int8_t flags;
+};
+
+/* Option argument to opts_dump(). */
+enum optdisp { NO_DISPLAY, ALL_DISPLAY, CHANGED_DISPLAY, SELECT_DISPLAY };
+
+/* Options array. */
+extern OPTLIST const optlist[];
+
+#include "options_def.h"
diff --git a/dist/nvi/common/options_f.c b/dist/nvi/common/options_f.c
new file mode 100644 (file)
index 0000000..3807553
--- /dev/null
@@ -0,0 +1,299 @@
+/*     $NetBSD: options_f.c,v 1.3 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: options_f.c,v 10.33 2001/06/25 15:19:11 skimo Exp (Berkeley) Date: 2001/06/25 15:19:11";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+/*
+ * PUBLIC: int f_altwerase __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_altwerase(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       if (*valp)
+               O_CLR(sp, O_TTYWERASE);
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_columns __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_columns(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       /* Validate the number. */
+       if (*valp < MINIMUM_SCREEN_COLS) {
+               msgq(sp, M_ERR, "040|Screen columns too small, less than %d",
+                   MINIMUM_SCREEN_COLS);
+               return (1);
+       }
+
+       /*
+        * !!!
+        * It's not uncommon for allocation of huge chunks of memory to cause
+        * core dumps on various systems.  So, we prune out numbers that are
+        * "obviously" wrong.  Vi will not work correctly if it has the wrong
+        * number of lines/columns for the screen, but at least we don't drop
+        * core.
+        */
+#define        MAXIMUM_SCREEN_COLS     4000
+       if (*valp > MAXIMUM_SCREEN_COLS) {
+               msgq(sp, M_ERR, "041|Screen columns too large, greater than %d",
+                   MAXIMUM_SCREEN_COLS);
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_lines __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_lines(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       /* Validate the number. */
+       if (*valp < MINIMUM_SCREEN_ROWS) {
+               msgq(sp, M_ERR, "042|Screen lines too small, less than %d",
+                   MINIMUM_SCREEN_ROWS);
+               return (1);
+       }
+
+       /*
+        * !!!
+        * It's not uncommon for allocation of huge chunks of memory to cause
+        * core dumps on various systems.  So, we prune out numbers that are
+        * "obviously" wrong.  Vi will not work correctly if it has the wrong
+        * number of lines/columns for the screen, but at least we don't drop
+        * core.
+        */
+#define        MAXIMUM_SCREEN_ROWS     4000
+       if (*valp > MAXIMUM_SCREEN_ROWS) {
+               msgq(sp, M_ERR, "043|Screen lines too large, greater than %d",
+                   MAXIMUM_SCREEN_ROWS);
+               return (1);
+       }
+
+       /*
+        * Set the value, and the related scroll value.  If no window
+        * value set, set a new default window.
+        */
+       o_set(sp, O_LINES, 0, NULL, *valp);
+       if (*valp == 1) {
+               sp->defscroll = 1;
+
+               if (O_VAL(sp, O_WINDOW) == O_D_VAL(sp, O_WINDOW) ||
+                   O_VAL(sp, O_WINDOW) > *valp) {
+                       o_set(sp, O_WINDOW, 0, NULL, 1);
+                       o_set(sp, O_WINDOW, OS_DEF, NULL, 1);
+               }
+       } else {
+               sp->defscroll = (*valp - 1) / 2;
+
+               if (O_VAL(sp, O_WINDOW) == O_D_VAL(sp, O_WINDOW) ||
+                   O_VAL(sp, O_WINDOW) > *valp) {
+                       o_set(sp, O_WINDOW, 0, NULL, *valp - 1);
+                       o_set(sp, O_WINDOW, OS_DEF, NULL, *valp - 1);
+               }
+       }
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_lisp __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_lisp(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       msgq(sp, M_ERR, "044|The lisp option is not implemented");
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_msgcat __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_msgcat(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       (void)msg_open(sp, str);
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_print __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_print(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       int offset = op - sp->opts;
+
+       /* Preset the value, needed for reinitialization of lookup table. */
+       if (offset == O_OCTAL) {
+               if (*valp)
+                       O_SET(sp, offset);
+               else
+                       O_CLR(sp, offset);
+       } else if (o_set(sp, offset, OS_STRDUP, str, 0))
+               return(1);
+
+       /* Reinitialize the key fast lookup table. */
+       v_key_ilookup(sp);
+
+       /* Reformat the screen. */
+       F_SET(sp, SC_SCR_REFORMAT);
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_readonly __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_readonly(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       /*
+        * !!!
+        * See the comment in exf.c.
+        */
+       if (*valp)
+               F_SET(sp, SC_READONLY);
+       else
+               F_CLR(sp, SC_READONLY);
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_recompile __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_recompile(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       if (F_ISSET(sp, SC_RE_SEARCH)) {
+               regfree(&sp->re_c);
+               F_CLR(sp, SC_RE_SEARCH);
+       }
+       if (F_ISSET(sp, SC_RE_SUBST)) {
+               regfree(&sp->subre_c);
+               F_CLR(sp, SC_RE_SUBST);
+       }
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_reformat __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_reformat(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       F_SET(sp, SC_SCR_REFORMAT);
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_ttywerase __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_ttywerase(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       if (*valp)
+               O_CLR(sp, O_ALTWERASE);
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_w300 __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_w300(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       u_long v;
+
+       /* Historical behavior for w300 was < 1200. */
+       if (sp->gp->scr_baud(sp, &v))
+               return (1);
+       if (v >= 1200)
+               return (0);
+
+       return (f_window(sp, op, str, valp));
+}
+
+/*
+ * PUBLIC: int f_w1200 __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_w1200(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       u_long v;
+
+       /* Historical behavior for w1200 was == 1200. */
+       if (sp->gp->scr_baud(sp, &v))
+               return (1);
+       if (v < 1200 || v > 4800)
+               return (0);
+
+       return (f_window(sp, op, str, valp));
+}
+
+/*
+ * PUBLIC: int f_w9600 __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_w9600(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       u_long v;
+
+       /* Historical behavior for w9600 was > 1200. */
+       if (sp->gp->scr_baud(sp, &v))
+               return (1);
+       if (v <= 4800)
+               return (0);
+
+       return (f_window(sp, op, str, valp));
+}
+
+/*
+ * PUBLIC: int f_window __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_window(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       if (*valp >= O_VAL(sp, O_LINES) - 1 &&
+           (*valp = O_VAL(sp, O_LINES) - 1) == 0)
+               *valp = 1;
+       return (0);
+}
+
+/*
+ * PUBLIC: int f_encoding __P((SCR *, OPTION *, const char *, u_long *));
+ */
+int
+f_encoding(SCR *sp, OPTION *op, const char *str, u_long *valp)
+{
+       int offset = op - sp->opts;
+
+       return conv_enc(sp, offset, str);
+}
diff --git a/dist/nvi/common/pthread.c b/dist/nvi/common/pthread.c
new file mode 100644 (file)
index 0000000..8ea5789
--- /dev/null
@@ -0,0 +1,107 @@
+/*     $NetBSD: pthread.c,v 1.1.1.2 2008/05/18 14:29:50 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 2000
+ *     Sven Verdoolaege.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: pthread.c,v 1.4 2000/07/22 14:52:37 skimo Exp (Berkeley) Date: 2000/07/22 14:52:37";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <pthread.h>
+
+#include "../common/common.h"
+
+static int vi_pthread_run __P((WIN *wp, void *(*fun)(void*), void *data));
+static int vi_pthread_lock_init __P((WIN *, void **));
+static int vi_pthread_lock_end __P((WIN *, void **));
+static int vi_pthread_lock_try __P((WIN *, void **));
+static int vi_pthread_lock_unlock __P((WIN *, void **));
+
+/*
+ * thread_init
+ *
+ * PUBLIC: void thread_init __P((GS *gp));
+ */
+void 
+thread_init(GS *gp)
+{
+       gp->run = vi_pthread_run;
+       gp->lock_init = vi_pthread_lock_init;
+       gp->lock_end = vi_pthread_lock_end;
+       gp->lock_try = vi_pthread_lock_try;
+       gp->lock_unlock = vi_pthread_lock_unlock;
+}
+
+static int
+vi_pthread_run(WIN *wp, void *(*fun)(void*), void *data)
+{
+       pthread_t *t = malloc(sizeof(pthread_t));
+       pthread_create(t, NULL, fun, data);
+       return 0;
+}
+
+static int 
+vi_pthread_lock_init (WIN * wp, void **p)
+{
+       pthread_mutex_t *mutex;
+       int rc;
+
+       MALLOC_RET(NULL, mutex, pthread_mutex_t *, sizeof(*mutex));
+
+       if (rc = pthread_mutex_init(mutex, NULL)) {
+               free(mutex);
+               *p = NULL;
+               return rc;
+       }
+       *p = mutex;
+       return 0;
+}
+
+static int 
+vi_pthread_lock_end (WIN * wp, void **p)
+{
+       int rc;
+       pthread_mutex_t *mutex = (pthread_mutex_t *)*p;
+
+       if (rc = pthread_mutex_destroy(mutex))
+               return rc;
+
+       free(mutex);
+       *p = NULL;
+       return 0;
+}
+
+static int 
+vi_pthread_lock_try (WIN * wp, void **p)
+{
+       printf("try %p\n", *p);
+       fflush(stdout);
+       return 0;
+       return pthread_mutex_trylock((pthread_mutex_t *)*p);
+}
+
+static int 
+vi_pthread_lock_unlock (WIN * wp, void **p)
+{
+       printf("unlock %p\n", *p);
+       return 0;
+       return pthread_mutex_unlock((pthread_mutex_t *)*p);
+}
+
diff --git a/dist/nvi/common/put.c b/dist/nvi/common/put.c
new file mode 100644 (file)
index 0000000..e244150
--- /dev/null
@@ -0,0 +1,230 @@
+/*     $NetBSD: put.c,v 1.3 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: put.c,v 10.18 2001/06/25 15:19:11 skimo Exp (Berkeley) Date: 2001/06/25 15:19:11";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+/*
+ * put --
+ *     Put text buffer contents into the file.
+ *
+ * PUBLIC: int put __P((SCR *, CB *, CHAR_T *, MARK *, MARK *, int));
+ */
+int
+put(SCR *sp, CB *cbp, ARG_CHAR_T *namep, MARK *cp, MARK *rp, int append)
+{
+       ARG_CHAR_T name;
+       TEXT *ltp, *tp;
+       db_recno_t lno;
+       size_t blen, clen, len;
+       int rval;
+       CHAR_T *bp, *t;
+       CHAR_T *p;
+
+       if (cbp == NULL) {
+               if (namep == NULL) {
+                       cbp = sp->wp->dcbp;
+                       if (cbp == NULL) {
+                               msgq(sp, M_ERR,
+                                   "053|The default buffer is empty");
+                               return (1);
+                       }
+               } else {
+                       name = *namep;
+                       CBNAME(sp, cbp, name);
+                       if (cbp == NULL) {
+                               msgq(sp, M_ERR, "054|Buffer %s is empty",
+                                   KEY_NAME(sp, name));
+                               return (1);
+                       }
+               }
+       }
+       tp = cbp->textq.cqh_first;
+
+       /*
+        * It's possible to do a put into an empty file, meaning that the cut
+        * buffer simply becomes the file.  It's a special case so that we can
+        * ignore it in general.
+        *
+        * !!!
+        * Historically, pasting into a file with no lines in vi would preserve
+        * the single blank line.  This is surely a result of the fact that the
+        * historic vi couldn't deal with a file that had no lines in it.  This
+        * implementation treats that as a bug, and does not retain the blank
+        * line.
+        *
+        * Historical practice is that the cursor ends at the first character
+        * in the file.
+        */
+       if (cp->lno == 1) {
+               if (db_last(sp, &lno))
+                       return (1);
+               if (lno == 0) {
+                       for (; tp != (void *)&cbp->textq;
+                           ++lno, ++sp->rptlines[L_ADDED], tp = tp->q.cqe_next)
+                               if (db_append(sp, 1, lno, tp->lb, tp->len))
+                                       return (1);
+                       rp->lno = 1;
+                       rp->cno = 0;
+                       return (0);
+               }
+       }
+
+       /* If a line mode buffer, append each new line into the file. */
+       if (F_ISSET(cbp, CB_LMODE)) {
+               lno = append ? cp->lno : cp->lno - 1;
+               rp->lno = lno + 1;
+               for (; tp != (void *)&cbp->textq;
+                   ++lno, ++sp->rptlines[L_ADDED], tp = tp->q.cqe_next)
+                       if (db_append(sp, 1, lno, tp->lb, tp->len))
+                               return (1);
+               rp->cno = 0;
+               (void)nonblank(sp, rp->lno, &rp->cno);
+               return (0);
+       }
+
+       /*
+        * If buffer was cut in character mode, replace the current line with
+        * one built from the portion of the first line to the left of the
+        * split plus the first line in the CB.  Append each intermediate line
+        * in the CB.  Append a line built from the portion of the first line
+        * to the right of the split plus the last line in the CB.
+        *
+        * Get the first line.
+        */
+       lno = cp->lno;
+       if (db_get(sp, lno, DBG_FATAL, &p, &len))
+               return (1);
+
+       GET_SPACE_RETW(sp, bp, blen, tp->len + len + 1);
+       t = bp;
+
+       /* Original line, left of the split. */
+       if (len > 0 && (clen = cp->cno + (append ? 1 : 0)) > 0) {
+               MEMCPYW(bp, p, clen);
+               p += clen;
+               t += clen;
+       }
+
+       /* First line from the CB. */
+       if (tp->len != 0) {
+               MEMCPYW(t, tp->lb, tp->len);
+               t += tp->len;
+       }
+
+       /* Calculate length left in the original line. */
+       clen = len == 0 ? 0 : len - (cp->cno + (append ? 1 : 0));
+
+       /*
+        * !!!
+        * In the historical 4BSD version of vi, character mode puts within
+        * a single line have two cursor behaviors: if the put is from the
+        * unnamed buffer, the cursor moves to the character inserted which
+        * appears last in the file.  If the put is from a named buffer,
+        * the cursor moves to the character inserted which appears first
+        * in the file.  In System III/V, it was changed at some point and
+        * the cursor always moves to the first character.  In both versions
+        * of vi, character mode puts that cross line boundaries leave the
+        * cursor on the first character.  Nvi implements the System III/V
+        * behavior, and expect POSIX.2 to do so as well.
+        */
+       rp->lno = lno;
+       rp->cno = len == 0 ? 0 : sp->cno + (append && tp->len ? 1 : 0);
+
+       /*
+        * If no more lines in the CB, append the rest of the original
+        * line and quit.  Otherwise, build the last line before doing
+        * the intermediate lines, because the line changes will lose
+        * the cached line.
+        */
+       if (tp->q.cqe_next == (void *)&cbp->textq) {
+               if (clen > 0) {
+                       MEMCPYW(t, p, clen);
+                       t += clen;
+               }
+               if (db_set(sp, lno, bp, t - bp))
+                       goto err;
+               if (sp->rptlchange != lno) {
+                       sp->rptlchange = lno;
+                       ++sp->rptlines[L_CHANGED];
+               }
+       } else {
+               /*
+                * Have to build both the first and last lines of the
+                * put before doing any sets or we'll lose the cached
+                * line.  Build both the first and last lines in the
+                * same buffer, so we don't have to have another buffer
+                * floating around.
+                *
+                * Last part of original line; check for space, reset
+                * the pointer into the buffer.
+                */
+               ltp = cbp->textq.cqh_last;
+               len = t - bp;
+               ADD_SPACE_RETW(sp, bp, blen, ltp->len + clen);
+               t = bp + len;
+
+               /* Add in last part of the CB. */
+               MEMCPYW(t, ltp->lb, ltp->len);
+               if (clen)
+                       MEMCPYW(t + ltp->len, p, clen);
+               clen += ltp->len;
+
+               /*
+                * Now: bp points to the first character of the first
+                * line, t points to the last character of the last
+                * line, t - bp is the length of the first line, and
+                * clen is the length of the last.  Just figured you'd
+                * want to know.
+                *
+                * Output the line replacing the original line.
+                */
+               if (db_set(sp, lno, bp, t - bp))
+                       goto err;
+               if (sp->rptlchange != lno) {
+                       sp->rptlchange = lno;
+                       ++sp->rptlines[L_CHANGED];
+               }
+
+               /* Output any intermediate lines in the CB. */
+               for (tp = tp->q.cqe_next;
+                   tp->q.cqe_next != (void *)&cbp->textq;
+                   ++lno, ++sp->rptlines[L_ADDED], tp = tp->q.cqe_next)
+                       if (db_append(sp, 1, lno, tp->lb, tp->len))
+                               goto err;
+
+               if (db_append(sp, 1, lno, t, clen))
+                       goto err;
+               ++sp->rptlines[L_ADDED];
+       }
+       rval = 0;
+
+       if (0)
+err:           rval = 1;
+
+       FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
diff --git a/dist/nvi/common/recover.c b/dist/nvi/common/recover.c
new file mode 100644 (file)
index 0000000..5d426ff
--- /dev/null
@@ -0,0 +1,859 @@
+/*     $NetBSD: recover.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: recover.c,v 10.31 2001/11/01 15:24:44 skimo Exp (Berkeley) Date: 2001/11/01 15:24:44";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>         /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+/*
+ * We include <sys/file.h>, because the open #defines were found there
+ * on historical systems.  We also include <fcntl.h> because the open(2)
+ * #defines are found there on newer systems.
+ */
+#include <sys/file.h>
+
+#include <bitstring.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "pathnames.h"
+
+/*
+ * Recovery code.
+ *
+ * The basic scheme is as follows.  In the EXF structure, we maintain full
+ * paths of a b+tree file and a mail recovery file.  The former is the file
+ * used as backing store by the DB package.  The latter is the file that
+ * contains an email message to be sent to the user if we crash.  The two
+ * simple states of recovery are:
+ *
+ *     + first starting the edit session:
+ *             the b+tree file exists and is mode 700, the mail recovery
+ *             file doesn't exist.
+ *     + after the file has been modified:
+ *             the b+tree file exists and is mode 600, the mail recovery
+ *             file exists, and is exclusively locked.
+ *
+ * In the EXF structure we maintain a file descriptor that is the locked
+ * file descriptor for the mail recovery file.  NOTE: we sometimes have to
+ * do locking with fcntl(2).  This is a problem because if you close(2) any
+ * file descriptor associated with the file, ALL of the locks go away.  Be
+ * sure to remember that if you have to modify the recovery code.  (It has
+ * been rhetorically asked of what the designers could have been thinking
+ * when they did that interface.  The answer is simple: they weren't.)
+ *
+ * To find out if a recovery file/backing file pair are in use, try to get
+ * a lock on the recovery file.
+ *
+ * To find out if a backing file can be deleted at boot time, check for an
+ * owner execute bit.  (Yes, I know it's ugly, but it's either that or put
+ * special stuff into the backing file itself, or correlate the files at
+ * boot time, neither of which looks like fun.)  Note also that there's a
+ * window between when the file is created and the X bit is set.  It's small,
+ * but it's there.  To fix the window, check for 0 length files as well.
+ *
+ * To find out if a file can be recovered, check the F_RCV_ON bit.  Note,
+ * this DOES NOT mean that any initialization has been done, only that we
+ * haven't yet failed at setting up or doing recovery.
+ *
+ * To preserve a recovery file/backing file pair, set the F_RCV_NORM bit.
+ * If that bit is not set when ending a file session:
+ *     If the EXF structure paths (rcv_path and rcv_mpath) are not NULL,
+ *     they are unlink(2)'d, and free(3)'d.
+ *     If the EXF file descriptor (rcv_fd) is not -1, it is closed.
+ *
+ * The backing b+tree file is set up when a file is first edited, so that
+ * the DB package can use it for on-disk caching and/or to snapshot the
+ * file.  When the file is first modified, the mail recovery file is created,
+ * the backing file permissions are updated, the file is sync(2)'d to disk,
+ * and the timer is started.  Then, at RCV_PERIOD second intervals, the
+ * b+tree file is synced to disk.  RCV_PERIOD is measured using SIGALRM, which
+ * means that the data structures (SCR, EXF, the underlying tree structures)
+ * must be consistent when the signal arrives.
+ *
+ * The recovery mail file contains normal mail headers, with two additions,
+ * which occur in THIS order, as the FIRST TWO headers:
+ *
+ *     X-vi-recover-file: file_name
+ *     X-vi-recover-path: recover_path
+ *
+ * Since newlines delimit the headers, this means that file names cannot have
+ * newlines in them, but that's probably okay.  As these files aren't intended
+ * to be long-lived, changing their format won't be too painful.
+ *
+ * Btree files are named "vi.XXXX" and recovery files are named "recover.XXXX".
+ */
+
+#define        VI_FHEADER      "X-vi-recover-file: "
+#define        VI_PHEADER      "X-vi-recover-path: "
+
+static int      rcv_copy __P((SCR *, int, char *));
+static void     rcv_email __P((SCR *, char *));
+static char    *rcv_gets __P((char *, size_t, int));
+static int      rcv_mailfile __P((SCR *, int, char *));
+static int      rcv_mktemp __P((SCR *, char *, const char *, int));
+
+/*
+ * rcv_tmp --
+ *     Build a file name that will be used as the recovery file.
+ *
+ * PUBLIC: int rcv_tmp __P((SCR *, EXF *, char *));
+ */
+int
+rcv_tmp(SCR *sp, EXF *ep, char *name)
+{
+       struct stat sb;
+       int fd;
+       char path[MAXPATHLEN];
+       const char *dp;
+
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        *
+        *
+        * If the recovery directory doesn't exist, try and create it.  As
+        * the recovery files are themselves protected from reading/writing
+        * by other than the owner, the worst that can happen is that a user
+        * would have permission to remove other user's recovery files.  If
+        * the sticky bit has the BSD semantics, that too will be impossible.
+        */
+       if (opts_empty(sp, O_RECDIR, 0))
+               goto err;
+       dp = O_STR(sp, O_RECDIR);
+       if (stat(dp, &sb)) {
+               if (errno != ENOENT || mkdir(dp, 0)) {
+                       msgq(sp, M_SYSERR, "%s", dp);
+                       goto err;
+               }
+               (void)chmod(dp, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
+       }
+
+       /* Newlines delimit the mail messages. */
+       if (strchr(name, '\n')) {
+               msgq(sp, M_ERR,
+                   "055|Files with newlines in the name are unrecoverable");
+               goto err;
+       }
+
+       (void)snprintf(path, sizeof(path), "%s/vi.XXXXXX", dp);
+       if ((fd = rcv_mktemp(sp, path, dp, S_IRWXU)) == -1)
+               goto err;
+       (void)close(fd);
+
+       if ((ep->rcv_path = strdup(path)) == NULL) {
+               msgq(sp, M_SYSERR, NULL);
+               (void)unlink(path);
+err:           msgq(sp, M_ERR,
+                   "056|Modifications not recoverable if the session fails");
+               return (1);
+       }
+
+       /* We believe the file is recoverable. */
+       F_SET(ep, F_RCV_ON);
+       return (0);
+}
+
+/*
+ * rcv_init --
+ *     Force the file to be snapshotted for recovery.
+ *
+ * PUBLIC: int rcv_init __P((SCR *));
+ */
+int
+rcv_init(SCR *sp)
+{
+       EXF *ep;
+       db_recno_t lno;
+
+       ep = sp->ep;
+
+       /* Only do this once. */
+       F_CLR(ep, F_FIRSTMODIFY);
+
+       /* If we already know the file isn't recoverable, we're done. */
+       if (!F_ISSET(ep, F_RCV_ON))
+               return (0);
+
+       /* Turn off recoverability until we figure out if this will work. */
+       F_CLR(ep, F_RCV_ON);
+
+       /* Test if we're recovering a file, not editing one. */
+       if (ep->rcv_mpath == NULL) {
+               /* Build a file to mail to the user. */
+               if (rcv_mailfile(sp, 0, NULL))
+                       goto err;
+
+               /* Force a read of the entire file. */
+               if (db_last(sp, &lno))
+                       goto err;
+
+               /* Turn on a busy message, and sync it to backing store. */
+               sp->gp->scr_busy(sp,
+                   "057|Copying file for recovery...", BUSY_ON);
+               if (ep->db->sync(ep->db, 0)) {
+                       msgq_str(sp, M_SYSERR, ep->rcv_path,
+                           "058|Preservation failed: %s");
+                       sp->gp->scr_busy(sp, NULL, BUSY_OFF);
+                       goto err;
+               }
+               sp->gp->scr_busy(sp, NULL, BUSY_OFF);
+       }
+
+       /* Turn off the owner execute bit. */
+       (void)chmod(ep->rcv_path, S_IRUSR | S_IWUSR);
+
+       /* We believe the file is recoverable. */
+       F_SET(ep, F_RCV_ON);
+       return (0);
+
+err:   msgq(sp, M_ERR,
+           "059|Modifications not recoverable if the session fails");
+       return (1);
+}
+
+/*
+ * rcv_sync --
+ *     Sync the file, optionally:
+ *             flagging the backup file to be preserved
+ *             snapshotting the backup file and send email to the user
+ *             sending email to the user if the file was modified
+ *             ending the file session
+ *
+ * PUBLIC: int rcv_sync __P((SCR *, u_int));
+ */
+int
+rcv_sync(SCR *sp, u_int flags)
+{
+       EXF *ep;
+       int fd, rval;
+       char buf[1024];
+       const char *dp;
+
+       /* Make sure that there's something to recover/sync. */
+       ep = sp->ep;
+       if (ep == NULL || !F_ISSET(ep, F_RCV_ON))
+               return (0);
+
+       /* Sync the file if it's been modified. */
+       if (F_ISSET(ep, F_MODIFIED)) {
+               if (ep->db->sync(ep->db, 0)) {
+                       F_CLR(ep, F_RCV_ON | F_RCV_NORM);
+                       msgq_str(sp, M_SYSERR,
+                           ep->rcv_path, "060|File backup failed: %s");
+                       return (1);
+               }
+
+               /* REQUEST: don't remove backing file on exit. */
+               if (LF_ISSET(RCV_PRESERVE))
+                       F_SET(ep, F_RCV_NORM);
+
+               /* REQUEST: send email. */
+               if (LF_ISSET(RCV_EMAIL))
+                       rcv_email(sp, ep->rcv_mpath);
+       }
+
+       /*
+        * !!!
+        * Each time the user exec's :preserve, we have to snapshot all of
+        * the recovery information, i.e. it's like the user re-edited the
+        * file.  We copy the DB(3) backing file, and then create a new mail
+        * recovery file, it's simpler than exiting and reopening all of the
+        * underlying files.
+        *
+        * REQUEST: snapshot the file.
+        */
+       rval = 0;
+       if (LF_ISSET(RCV_SNAPSHOT)) {
+               if (opts_empty(sp, O_RECDIR, 0))
+                       goto err;
+               dp = O_STR(sp, O_RECDIR);
+               (void)snprintf(buf, sizeof(buf), "%s/vi.XXXXXX", dp);
+               if ((fd = rcv_mktemp(sp, buf, dp, S_IRUSR | S_IWUSR)) == -1)
+                       goto err;
+               sp->gp->scr_busy(sp,
+                   "061|Copying file for recovery...", BUSY_ON);
+               if (rcv_copy(sp, fd, ep->rcv_path) ||
+                   close(fd) || rcv_mailfile(sp, 1, buf)) {
+                       (void)unlink(buf);
+                       (void)close(fd);
+                       rval = 1;
+               }
+               sp->gp->scr_busy(sp, NULL, BUSY_OFF);
+       }
+       if (0) {
+err:           rval = 1;
+       }
+
+       /* REQUEST: end the file session. */
+       if (LF_ISSET(RCV_ENDSESSION) && file_end(sp, NULL, 1))
+               rval = 1;
+
+       return (rval);
+}
+
+/*
+ * rcv_mailfile --
+ *     Build the file to mail to the user.
+ */
+static int
+rcv_mailfile(SCR *sp, int issync, char *cp_path)
+{
+       EXF *ep;
+       GS *gp;
+       struct passwd *pw;
+       size_t len;
+       time_t now;
+       uid_t uid;
+       int fd;
+       char *p, *t, buf[4096], mpath[MAXPATHLEN];
+       const char *dp;
+       char *t1, *t2, *t3;
+
+       /*
+        * XXX
+        * MAXHOSTNAMELEN is in various places on various systems, including
+        * <netdb.h> and <sys/socket.h>.  If not found, use a large default.
+        */
+#ifndef MAXHOSTNAMELEN
+#define        MAXHOSTNAMELEN  1024
+#endif
+       char host[MAXHOSTNAMELEN];
+
+       gp = sp->gp;
+       if ((pw = getpwuid(uid = getuid())) == NULL) {
+               msgq(sp, M_ERR,
+                   "062|Information on user id %u not found", uid);
+               return (1);
+       }
+
+       if (opts_empty(sp, O_RECDIR, 0))
+               return (1);
+       dp = O_STR(sp, O_RECDIR);
+       (void)snprintf(mpath, sizeof(mpath), "%s/recover.XXXXXX", dp);
+       if ((fd = rcv_mktemp(sp, mpath, dp, S_IRUSR | S_IWUSR)) == -1)
+               return (1);
+
+       /*
+        * XXX
+        * We keep an open lock on the file so that the recover option can
+        * distinguish between files that are live and those that need to
+        * be recovered.  There's an obvious window between the mkstemp call
+        * and the lock, but it's pretty small.
+        */
+       ep = sp->ep;
+       if (file_lock(sp, NULL, NULL, fd, 1) != LOCK_SUCCESS)
+               msgq(sp, M_SYSERR, "063|Unable to lock recovery file");
+       if (!issync) {
+               /* Save the recover file descriptor, and mail path. */
+               ep->rcv_fd = fd;
+               if ((ep->rcv_mpath = strdup(mpath)) == NULL) {
+                       msgq(sp, M_SYSERR, NULL);
+                       goto err;
+               }
+               cp_path = ep->rcv_path;
+       }
+
+       /*
+        * XXX
+        * We can't use stdio(3) here.  The problem is that we may be using
+        * fcntl(2), so if ANY file descriptor into the file is closed, the
+        * lock is lost.  So, we could never close the FILE *, even if we
+        * dup'd the fd first.
+        */
+       t = sp->frp->name;
+       if ((p = strrchr(t, '/')) == NULL)
+               p = t;
+       else
+               ++p;
+       (void)time(&now);
+       (void)gethostname(host, sizeof(host));
+       len = snprintf(buf, sizeof(buf),
+           "%s%s\n%s%s\n%s\n%s\n%s%s\n%s%s\n%s\n\n",
+           VI_FHEADER, t,                      /* Non-standard. */
+           VI_PHEADER, cp_path,                /* Non-standard. */
+           "Reply-To: root",
+           "From: root (Nvi recovery program)",
+           "To: ", pw->pw_name,
+           "Subject: Nvi saved the file ", p,
+           "Precedence: bulk");                /* For vacation(1). */
+       if (len > sizeof(buf) - 1)
+               goto lerr;
+       if ((size_t)write(fd, buf, len) != len)
+               goto werr;
+
+       len = snprintf(buf, sizeof(buf),
+           "%s%.24s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n",
+           "On ", ctime(&now), ", the user ", pw->pw_name,
+           " was editing a file named ", t, " on the machine ",
+           host, ", when it was saved for recovery. ",
+           "You can recover most, if not all, of the changes ",
+           "to this file using the -r option to ", gp->progname, ":\n\n\t",
+           gp->progname, " -r ", t);
+       if (len > sizeof(buf) - 1) {
+lerr:          msgq(sp, M_ERR, "064|Recovery file buffer overrun");
+               goto err;
+       }
+
+       /*
+        * Format the message.  (Yes, I know it's silly.)
+        * Requires that the message end in a <newline>.
+        */
+#define        FMTCOLS 60
+       for (t1 = buf; len > 0; len -= t2 - t1, t1 = t2) {
+               /* Check for a short length. */
+               if (len <= FMTCOLS) {
+                       t2 = t1 + (len - 1);
+                       goto wout;
+               }
+
+               /* Check for a required <newline>. */
+               t2 = strchr(t1, '\n');
+               if (t2 - t1 <= FMTCOLS)
+                       goto wout;
+
+               /* Find the closest space, if any. */
+               for (t3 = t2; t2 > t1; --t2)
+                       if (*t2 == ' ') {
+                               if (t2 - t1 <= FMTCOLS)
+                                       goto wout;
+                               t3 = t2;
+                       }
+               t2 = t3;
+
+               /* t2 points to the last character to display. */
+wout:          *t2++ = '\n';
+
+               /* t2 points one after the last character to display. */
+               if (write(fd, t1, t2 - t1) != t2 - t1)
+                       goto werr;
+       }
+
+       if (issync) {
+               rcv_email(sp, mpath);
+               if (close(fd)) {
+werr:                  msgq(sp, M_SYSERR, "065|Recovery file");
+                       goto err;
+               }
+       }
+       return (0);
+
+err:   if (!issync)
+               ep->rcv_fd = -1;
+       if (fd != -1)
+               (void)close(fd);
+       return (1);
+}
+
+/*
+ *     people making love
+ *     never exactly the same
+ *     just like a snowflake
+ *
+ * rcv_list --
+ *     List the files that can be recovered by this user.
+ *
+ * PUBLIC: int rcv_list __P((SCR *));
+ */
+int
+rcv_list(SCR *sp)
+{
+       struct dirent *dp;
+       struct stat sb;
+       DIR *dirp;
+       FILE *fp;
+       int found;
+       char *p, *t;
+       const char *d;
+       char file[MAXPATHLEN], path[MAXPATHLEN];
+
+       /* Open the recovery directory for reading. */
+       if (opts_empty(sp, O_RECDIR, 0))
+               return (1);
+       d = O_STR(sp, O_RECDIR);
+       if (chdir(d) || (dirp = opendir(".")) == NULL) {
+               msgq_str(sp, M_SYSERR, d, "recdir: %s");
+               return (1);
+       }
+
+       /* Read the directory. */
+       for (found = 0; (dp = readdir(dirp)) != NULL;) {
+               if (strncmp(dp->d_name, "recover.", 8))
+                       continue;
+
+               /*
+                * If it's readable, it's recoverable.
+                *
+                * XXX
+                * Should be "r", we don't want to write the file.  However,
+                * if we're using fcntl(2), there's no way to lock a file
+                * descriptor that's not open for writing.
+                */
+               if ((fp = fopen(dp->d_name, "r+")) == NULL)
+                       continue;
+
+               switch (file_lock(sp, NULL, NULL, fileno(fp), 1)) {
+               case LOCK_FAILED:
+                       /*
+                        * XXX
+                        * Assume that a lock can't be acquired, but that we
+                        * should permit recovery anyway.  If this is wrong,
+                        * and someone else is using the file, we're going to
+                        * die horribly.
+                        */
+                       break;
+               case LOCK_SUCCESS:
+                       break;
+               case LOCK_UNAVAIL:
+                       /* If it's locked, it's live. */
+                       (void)fclose(fp);
+                       continue;
+               }
+
+               /* Check the headers. */
+               if (fgets(file, sizeof(file), fp) == NULL ||
+                   strncmp(file, VI_FHEADER, sizeof(VI_FHEADER) - 1) ||
+                   (p = strchr(file, '\n')) == NULL ||
+                   fgets(path, sizeof(path), fp) == NULL ||
+                   strncmp(path, VI_PHEADER, sizeof(VI_PHEADER) - 1) ||
+                   (t = strchr(path, '\n')) == NULL) {
+                       msgq_str(sp, M_ERR, dp->d_name,
+                           "066|%s: malformed recovery file");
+                       goto next;
+               }
+               *p = *t = '\0';
+
+               /*
+                * If the file doesn't exist, it's an orphaned recovery file,
+                * toss it.
+                *
+                * XXX
+                * This can occur if the backup file was deleted and we crashed
+                * before deleting the email file.
+                */
+               errno = 0;
+               if (stat(path + sizeof(VI_PHEADER) - 1, &sb) &&
+                   errno == ENOENT) {
+                       (void)unlink(dp->d_name);
+                       goto next;
+               }
+
+               /* Get the last modification time and display. */
+               (void)fstat(fileno(fp), &sb);
+               (void)printf("%.24s: %s\n",
+                   ctime(&sb.st_mtime), file + sizeof(VI_FHEADER) - 1);
+               found = 1;
+
+               /* Close, discarding lock. */
+next:          (void)fclose(fp);
+       }
+       if (found == 0)
+               (void)printf("vi: no files to recover.\n");
+       (void)closedir(dirp);
+       return (0);
+}
+
+/*
+ * rcv_read --
+ *     Start a recovered file as the file to edit.
+ *
+ * PUBLIC: int rcv_read __P((SCR *, FREF *));
+ */
+int
+rcv_read(SCR *sp, FREF *frp)
+{
+       struct dirent *dp;
+       struct stat sb;
+       DIR *dirp;
+       EXF *ep;
+       time_t rec_mtime;
+       int fd, found, locked = 0, requested, sv_fd;
+       char *name, *p, *t, *recp, *pathp;
+       const char *rp;
+       char file[MAXPATHLEN], path[MAXPATHLEN], recpath[MAXPATHLEN];
+
+       if (opts_empty(sp, O_RECDIR, 0))
+               return (1);
+       rp = O_STR(sp, O_RECDIR);
+       if ((dirp = opendir(rp)) == NULL) {
+               msgq_str(sp, M_ERR, rp, "%s");
+               return (1);
+       }
+
+       name = frp->name;
+       sv_fd = -1;
+       rec_mtime = 0;
+       recp = pathp = NULL;
+       for (found = requested = 0; (dp = readdir(dirp)) != NULL;) {
+               if (strncmp(dp->d_name, "recover.", 8))
+                       continue;
+               (void)snprintf(recpath,
+                   sizeof(recpath), "%s/%s", rp, dp->d_name);
+
+               /*
+                * If it's readable, it's recoverable.  It would be very
+                * nice to use stdio(3), but, we can't because that would
+                * require closing and then reopening the file so that we
+                * could have a lock and still close the FP.  Another tip
+                * of the hat to fcntl(2).
+                *
+                * XXX
+                * Should be O_RDONLY, we don't want to write it.  However,
+                * if we're using fcntl(2), there's no way to lock a file
+                * descriptor that's not open for writing.
+                */
+               if ((fd = open(recpath, O_RDWR, 0)) == -1)
+                       continue;
+
+               switch (file_lock(sp, NULL, NULL, fd, 1)) {
+               case LOCK_FAILED:
+                       /*
+                        * XXX
+                        * Assume that a lock can't be acquired, but that we
+                        * should permit recovery anyway.  If this is wrong,
+                        * and someone else is using the file, we're going to
+                        * die horribly.
+                        */
+                       locked = 0;
+                       break;
+               case LOCK_SUCCESS:
+                       locked = 1;
+                       break;
+               case LOCK_UNAVAIL:
+                       /* If it's locked, it's live. */
+                       (void)close(fd);
+                       continue;
+               }
+
+               /* Check the headers. */
+               if (rcv_gets(file, sizeof(file), fd) == NULL ||
+                   strncmp(file, VI_FHEADER, sizeof(VI_FHEADER) - 1) ||
+                   (p = strchr(file, '\n')) == NULL ||
+                   rcv_gets(path, sizeof(path), fd) == NULL ||
+                   strncmp(path, VI_PHEADER, sizeof(VI_PHEADER) - 1) ||
+                   (t = strchr(path, '\n')) == NULL) {
+                       msgq_str(sp, M_ERR, recpath,
+                           "067|%s: malformed recovery file");
+                       goto next;
+               }
+               *p = *t = '\0';
+               ++found;
+
+               /*
+                * If the file doesn't exist, it's an orphaned recovery file,
+                * toss it.
+                *
+                * XXX
+                * This can occur if the backup file was deleted and we crashed
+                * before deleting the email file.
+                */
+               errno = 0;
+               if (stat(path + sizeof(VI_PHEADER) - 1, &sb) &&
+                   errno == ENOENT) {
+                       (void)unlink(dp->d_name);
+                       goto next;
+               }
+
+               /* Check the file name. */
+               if (strcmp(file + sizeof(VI_FHEADER) - 1, name))
+                       goto next;
+
+               ++requested;
+
+               /*
+                * If we've found more than one, take the most recent.
+                *
+                * XXX
+                * Since we're using st_mtime, for portability reasons,
+                * we only get a single second granularity, instead of
+                * getting it right.
+                */
+               (void)fstat(fd, &sb);
+               if (recp == NULL || rec_mtime < sb.st_mtime) {
+                       p = recp;
+                       t = pathp;
+                       if ((recp = strdup(recpath)) == NULL) {
+                               msgq(sp, M_SYSERR, NULL);
+                               recp = p;
+                               goto next;
+                       }
+                       if ((pathp = strdup(path)) == NULL) {
+                               msgq(sp, M_SYSERR, NULL);
+                               free(recp);
+                               recp = p;
+                               pathp = t;
+                               goto next;
+                       }
+                       if (p != NULL) {
+                               free(p);
+                               free(t);
+                       }
+                       rec_mtime = sb.st_mtime;
+                       if (sv_fd != -1)
+                               (void)close(sv_fd);
+                       sv_fd = fd;
+               } else
+next:                  (void)close(fd);
+       }
+       (void)closedir(dirp);
+
+       if (recp == NULL) {
+               msgq_str(sp, M_INFO, name,
+                   "068|No files named %s, readable by you, to recover");
+               return (1);
+       }
+       if (found) {
+               if (requested > 1)
+                       msgq(sp, M_INFO,
+           "069|There are older versions of this file for you to recover");
+               if (found > requested)
+                       msgq(sp, M_INFO,
+                           "070|There are other files for you to recover");
+       }
+
+       /*
+        * Create the FREF structure, start the btree file.
+        *
+        * XXX
+        * file_init() is going to set ep->rcv_path.
+        */
+       if (file_init(sp, frp, pathp + sizeof(VI_PHEADER) - 1, 0)) {
+               free(recp);
+               free(pathp);
+               (void)close(sv_fd);
+               return (1);
+       }
+
+       /*
+        * We keep an open lock on the file so that the recover option can
+        * distinguish between files that are live and those that need to
+        * be recovered.  The lock is already acquired, just copy it.
+        */
+       ep = sp->ep;
+       ep->rcv_mpath = recp;
+       ep->rcv_fd = sv_fd;
+       if (!locked)
+               F_SET(frp, FR_UNLOCKED);
+
+       /* We believe the file is recoverable. */
+       F_SET(ep, F_RCV_ON);
+       return (0);
+}
+
+/*
+ * rcv_copy --
+ *     Copy a recovery file.
+ */
+static int
+rcv_copy(SCR *sp, int wfd, char *fname)
+{
+       int nr, nw, off, rfd;
+       char buf[8 * 1024];
+
+       if ((rfd = open(fname, O_RDONLY, 0)) == -1)
+               goto err;
+       while ((nr = read(rfd, buf, sizeof(buf))) > 0)
+               for (off = 0; nr; nr -= nw, off += nw)
+                       if ((nw = write(wfd, buf + off, nr)) < 0)
+                               goto err;
+       if (nr == 0)
+               return (0);
+
+err:   msgq_str(sp, M_SYSERR, fname, "%s");
+       return (1);
+}
+
+/*
+ * rcv_gets --
+ *     Fgets(3) for a file descriptor.
+ */
+static char *
+rcv_gets(char *buf, size_t len, int fd)
+{
+       int nr;
+       char *p;
+
+       if ((nr = read(fd, buf, len - 1)) == -1)
+               return (NULL);
+       if ((p = strchr(buf, '\n')) == NULL)
+               return (NULL);
+       (void)lseek(fd, (off_t)((p - buf) + 1), SEEK_SET);
+       return (buf);
+}
+
+/*
+ * rcv_mktemp --
+ *     Paranoid make temporary file routine.
+ */
+static int
+rcv_mktemp(SCR *sp, char *path, const char *dname, int perms)
+{
+       int fd;
+
+       /*
+        * !!!
+        * We expect mkstemp(3) to set the permissions correctly.  On
+        * historic System V systems, mkstemp didn't.  Do it here, on
+        * GP's.
+        *
+        * XXX
+        * The variable perms should really be a mode_t, and it would
+        * be nice to use fchmod(2) instead of chmod(2), here.
+        */
+       if ((fd = mkstemp(path)) == -1)
+               msgq_str(sp, M_SYSERR, dname, "%s");
+       else
+               (void)chmod(path, perms);
+       return (fd);
+}
+
+/*
+ * rcv_email --
+ *     Send email.
+ */
+static void
+rcv_email(SCR *sp, char *fname)
+{
+       struct stat sb;
+       char buf[MAXPATHLEN * 2 + 20];
+
+       if (_PATH_SENDMAIL[0] != '/' || stat(_PATH_SENDMAIL, &sb))
+               msgq_str(sp, M_SYSERR,
+                   _PATH_SENDMAIL, "071|not sending email: %s");
+       else {
+               /*
+                * !!!
+                * If you need to port this to a system that doesn't have
+                * sendmail, the -t flag causes sendmail to read the message
+                * for the recipients instead of specifying them some other
+                * way.
+                */
+               (void)snprintf(buf, sizeof(buf),
+                   "%s -t < %s", _PATH_SENDMAIL, fname);
+               (void)system(buf);
+       }
+}
diff --git a/dist/nvi/common/screen.c b/dist/nvi/common/screen.c
new file mode 100644 (file)
index 0000000..86981ed
--- /dev/null
@@ -0,0 +1,238 @@
+/*     $NetBSD: screen.c,v 1.1.1.2 2008/05/18 14:29:51 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: screen.c,v 10.22 2001/06/25 15:19:12 skimo Exp (Berkeley) Date: 2001/06/25 15:19:12";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+
+/*
+ * screen_init --
+ *     Do the default initialization of an SCR structure.
+ *
+ * PUBLIC: int screen_init __P((GS *, SCR *, SCR **));
+ */
+int
+screen_init(GS *gp, SCR *orig, SCR **spp)
+{
+       SCR *sp;
+       size_t len;
+
+       *spp = NULL;
+       CALLOC_RET(orig, sp, SCR *, 1, sizeof(SCR));
+       *spp = sp;
+
+/* INITIALIZED AT SCREEN CREATE. */
+       sp->id = ++gp->id;
+       sp->refcnt = 1;
+
+       sp->gp = gp;                    /* All ref the GS structure. */
+
+       sp->ccnt = 2;                   /* Anything > 1 */
+
+       /*
+        * XXX
+        * sp->defscroll is initialized by the opts_init() code because
+        * we don't have the option information yet.
+        */
+
+       CIRCLEQ_INIT(&sp->tiq);
+
+/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
+       if (orig == NULL) {
+               sp->searchdir = NOTSET;
+       } else {
+               sp->wp = orig->wp;
+
+               /* Alternate file name. */
+               if (orig->alt_name != NULL &&
+                   (sp->alt_name = strdup(orig->alt_name)) == NULL)
+                       goto mem;
+
+               /* Last executed at buffer. */
+               if (F_ISSET(orig, SC_AT_SET)) {
+                       F_SET(sp, SC_AT_SET);
+                       sp->at_lbuf = orig->at_lbuf;
+               }
+
+               /* Retain searching/substitution information. */
+               sp->searchdir = orig->searchdir == NOTSET ? NOTSET : FORWARD;
+               if (orig->re != NULL && (sp->re =
+                   v_wstrdup(sp, orig->re, orig->re_len)) == NULL)
+                       goto mem;
+               sp->re_len = orig->re_len;
+               if (orig->subre != NULL && (sp->subre =
+                   v_wstrdup(sp, orig->subre, orig->subre_len)) == NULL)
+                       goto mem;
+               sp->subre_len = orig->subre_len;
+               if (orig->repl != NULL && (sp->repl =
+                   v_wstrdup(sp, orig->repl, orig->repl_len)) == NULL)
+                       goto mem;
+               sp->repl_len = orig->repl_len;
+               if (orig->newl_len) {
+                       len = orig->newl_len * sizeof(size_t);
+                       MALLOC(sp, sp->newl, size_t *, len);
+                       if (sp->newl == NULL) {
+mem:                           msgq(orig, M_SYSERR, NULL);
+                               goto err;
+                       }
+                       sp->newl_len = orig->newl_len;
+                       sp->newl_cnt = orig->newl_cnt;
+                       memcpy(sp->newl, orig->newl, len);
+               }
+
+               if (opts_copy(orig, sp))
+                       goto err;
+
+               F_SET(sp, F_ISSET(orig, SC_EX | SC_VI));
+       }
+
+       if (ex_screen_copy(orig, sp))           /* Ex. */
+               goto err;
+       if (v_screen_copy(orig, sp))            /* Vi. */
+               goto err;
+       sp->cl_private = 0;                     /* XXX */
+       conv_init(orig, sp);                    /* XXX */
+
+       *spp = sp;
+       return (0);
+
+err:   screen_end(sp);
+       return (1);
+}
+
+/*
+ * screen_end --
+ *     Release a screen, no matter what had (and had not) been
+ *     initialized.
+ *
+ * PUBLIC: int screen_end __P((SCR *));
+ */
+int
+screen_end(SCR *sp)
+{
+       int rval;
+
+       /* If multiply referenced, just decrement the count and return. */
+        if (--sp->refcnt != 0)
+                return (0);
+
+       /*
+        * Remove the screen from the displayed queue.
+        *
+        * If a created screen failed during initialization, it may not
+        * be linked into the chain.
+        */
+       if (sp->q.cqe_next != NULL)
+               CIRCLEQ_REMOVE(&sp->wp->scrq, sp, q);
+
+       /* The screen is no longer real. */
+       F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+
+       rval = 0;
+#ifdef HAVE_PERL_INTERP
+       if (perl_screen_end(sp))                /* End perl. */
+               rval = 1;
+#endif
+       if (v_screen_end(sp))                   /* End vi. */
+               rval = 1;
+       if (ex_screen_end(sp))                  /* End ex. */
+               rval = 1;
+
+       /* Free file names. */
+       { char **ap;
+               if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
+                       for (ap = sp->argv; *ap != NULL; ++ap)
+                               free(*ap);
+                       free(sp->argv);
+               }
+       }
+
+       /* Free any text input. */
+       if (sp->tiq.cqh_first != NULL)
+               text_lfree(&sp->tiq);
+
+       /* Free alternate file name. */
+       if (sp->alt_name != NULL)
+               free(sp->alt_name);
+
+       /* Free up search information. */
+       if (sp->re != NULL)
+               free(sp->re);
+       if (F_ISSET(sp, SC_RE_SEARCH))
+               regfree(&sp->re_c);
+       if (sp->subre != NULL)
+               free(sp->subre);
+       if (F_ISSET(sp, SC_RE_SUBST))
+               regfree(&sp->subre_c);
+       if (sp->repl != NULL)
+               free(sp->repl);
+       if (sp->newl != NULL)
+               free(sp->newl);
+
+       /* Free all the options */
+       opts_free(sp);
+
+       /* Free the screen itself. */
+       free(sp);
+
+       return (rval);
+}
+
+/*
+ * screen_next --
+ *     Return the next screen in the queue.
+ *
+ * PUBLIC: SCR *screen_next __P((SCR *));
+ */
+SCR *
+screen_next(SCR *sp)
+{
+       GS *gp;
+       WIN *wp;
+       SCR *next;
+
+       /* Try the display queue, without returning the current screen. */
+       gp = sp->gp;
+       wp = sp->wp;
+       for (next = wp->scrq.cqh_first;
+           next != (void *)&wp->scrq; next = next->q.cqe_next)
+               if (next != sp)
+                       break;
+       if (next != (void *)&wp->scrq)
+               return (next);
+
+       /* Try the hidden queue; if found, move screen to the display queue. */
+       if (gp->hq.cqh_first != (void *)&gp->hq) {
+               next = gp->hq.cqh_first;
+               CIRCLEQ_REMOVE(&gp->hq, next, q);
+               CIRCLEQ_INSERT_HEAD(&wp->scrq, next, q);
+               next->wp = sp->wp;
+               return (next);
+       }
+       return (NULL);
+}
diff --git a/dist/nvi/common/screen.h b/dist/nvi/common/screen.h
new file mode 100644 (file)
index 0000000..8da0ad5
--- /dev/null
@@ -0,0 +1,283 @@
+/*     $NetBSD: screen.h,v 1.2 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: screen.h,v 10.49 2002/03/02 23:47:02 skimo Exp (Berkeley) Date: 2002/03/02 23:47:02
+ */
+
+/*
+ * There are minimum values that vi has to have to display a screen.  The row
+ * minimum is fixed at 1 (the svi code can share a line between the text line
+ * and the colon command/message line).  Column calculation is a lot trickier.
+ * For example, you have to have enough columns to display the line number,
+ * not to mention guaranteeing that tabstop and shiftwidth values are smaller
+ * than the current column value.  It's simpler to have a fixed value and not
+ * worry about it.
+ *
+ * XXX
+ * MINIMUM_SCREEN_COLS is almost certainly wrong.
+ */
+#define        MINIMUM_SCREEN_ROWS      1
+#define        MINIMUM_SCREEN_COLS     20
+
+/*
+ * WIN --
+ *     A list of screens that are displayed as a whole.
+ */
+struct _win {
+       CIRCLEQ_ENTRY(_win)         q;      /* Windows. */
+
+       CIRCLEQ_HEAD(_scrh, _scr)   scrq;   /* Screens */
+
+       GS      *gp;                    /* Pointer to global area. */
+
+       SCR     *ccl_sp;                /* Colon command-line screen. */
+
+       void    *perl_private;          /* Perl interpreter. */
+
+       void    *ip_private;            /* IP support private area. */
+
+       void    *th_private;            /* Threading support private area. */
+
+       /*
+        * Ex command structures (EXCMD).  Defined here because ex commands
+        * exist outside of any particular screen or file.
+        */
+#define        EXCMD_RUNNING(wp)       ((wp)->ecq.lh_first->clen != 0)
+       LIST_HEAD(_excmdh, _excmd) ecq; /* Ex command linked list. */
+       EXCMD           excmd;          /* Default ex command structure. */
+       char           *if_name;        /* Current associated file. */
+       db_recno_t      if_lno;         /* Current associated line number. */
+
+       EVENT   *i_event;               /* Array of input events. */
+       size_t   i_nelem;               /* Number of array elements. */
+       size_t   i_cnt;                 /* Count of events. */
+       size_t   i_next;                /* Offset of next event. */
+
+       CB      *dcbp;                  /* Default cut buffer pointer. */
+       CB       dcb_store;             /* Default cut buffer storage. */
+       LIST_HEAD(_cuth, _cb) cutq;     /* Linked list of cut buffers. */
+
+       /* For now, can be either char or CHAR_T buffer */
+       char    *tmp_bp;                /* Temporary buffer. */
+       size_t   tmp_blen;              /* Temporary buffer size. */
+
+       char    *l_lp;                  /* Log buffer. */
+       size_t   l_len;                 /* Log buffer length. */
+
+       CONVWIN  cw;
+
+/* Flags. */
+#define        W_TMP_INUSE     0x0001          /* Temporary buffer in use. */
+       u_int32_t flags;
+
+                                       /* Message or ex output. */
+       void    (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+};
+
+/*
+ * SCR --
+ *     The screen structure.  To the extent possible, all screen information
+ *     is stored in the various private areas.  The only information here
+ *     is used by global routines or is shared by too many screens.
+ */
+struct _scr {
+/* INITIALIZED AT SCREEN CREATE. */
+       CIRCLEQ_ENTRY(_scr) q;          /* Screens. */
+       CIRCLEQ_ENTRY(_scr) eq;         /* Screens. */
+
+       int      id;                    /* Screen id #. */
+       int      refcnt;                /* Reference count. */
+
+       WIN     *wp;                    /* Pointer to window. */
+       GS      *gp;                    /* Pointer to global area. */
+       SCR     *nextdisp;              /* Next display screen. */
+       SCR     *ccl_parent;            /* Colon command-line parent screen. */
+       EXF     *ep;                    /* Screen's current EXF structure. */
+
+       CHAR_T  *c_lp;                  /* Cached line. */
+       size_t   c_len;                 /* Cached line length. */
+       /* May move out again once we use DB 
+        * to cache internal representation
+        */
+       size_t   c_blen;                /* Cached line buffer length. */
+       db_recno_t       c_lno;         /* Cached line number. */
+
+       FREF    *frp;                   /* FREF being edited. */
+       char    **argv;                 /* NULL terminated file name array. */
+       char    **cargv;                /* Current file name. */
+
+       u_long   ccnt;                  /* Command count. */
+       u_long   q_ccnt;                /* Quit or ZZ command count. */
+
+                                       /* Screen's: */
+       size_t   rows;                  /* 1-N: number of rows. */
+       size_t   cols;                  /* 1-N: number of columns. */
+       size_t   t_rows;                /* 1-N: cur number of text rows. */
+       size_t   t_maxrows;             /* 1-N: max number of text rows. */
+       size_t   t_minrows;             /* 1-N: min number of text rows. */
+       size_t   coff;                  /* 0-N: screen col offset in display. */
+       size_t   roff;                  /* 0-N: screen row offset in display. */
+
+                                       /* Cursor's: */
+       db_recno_t       lno;                   /* 1-N: file line. */
+       size_t   cno;                   /* 0-N: file character in line. */
+
+       size_t   rcm;                   /* Vi: 0-N: Most attractive column. */
+
+#define        L_ADDED         0               /* Added lines. */
+#define        L_CHANGED       1               /* Changed lines. */
+#define        L_DELETED       2               /* Deleted lines. */
+#define        L_JOINED        3               /* Joined lines. */
+#define        L_MOVED         4               /* Moved lines. */
+#define        L_SHIFT         5               /* Shift lines. */
+#define        L_YANKED        6               /* Yanked lines. */
+       db_recno_t       rptlchange;            /* Ex/vi: last L_CHANGED lno. */
+       db_recno_t       rptlines[L_YANKED + 1];/* Ex/vi: lines changed by last op. */
+
+       TEXTH    tiq;                   /* Ex/vi: text input queue. */
+
+       SCRIPT  *script;                /* Vi: script mode information .*/
+
+       db_recno_t       defscroll;     /* Vi: ^D, ^U scroll information. */
+
+                                       /* Display character. */
+       u_char   cname[MAX_CHARACTER_COLUMNS + 1];
+       size_t   clen;                  /* Length of display character. */
+
+       enum {                          /* Vi editor mode. */
+           SM_APPEND = 0, SM_CHANGE, SM_COMMAND, SM_INSERT,
+           SM_REPLACE } showmode;
+
+       void    *ex_private;            /* Ex private area. */
+       void    *vi_private;            /* Vi private area. */
+       void    *perl_private;          /* Perl private area. */
+       void    *cl_private;            /* Curses private area. */
+
+       CONV    conv;
+
+       struct _log_state  state;       /* State during log traversal. */
+
+/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
+       char    *alt_name;              /* Ex/vi: alternate file name. */
+
+       ARG_CHAR_T       at_lbuf;       /* Ex/vi: Last executed at buffer. */
+
+                                       /* Ex/vi: re_compile flags. */
+#define        RE_WSTART       L("[[:<:]]")    /* Ex/vi: not-in-word search pattern. */
+#define        RE_WSTOP        L("[[:>:]]")
+#define RE_WSTART_LEN  (sizeof(RE_WSTART)/sizeof(CHAR_T)-1)
+#define RE_WSTOP_LEN   (sizeof(RE_WSTOP)/sizeof(CHAR_T)-1)
+                                       /* Ex/vi: flags to search routines. */
+#define        SEARCH_CSCOPE   0x000001        /* Search for a cscope pattern. */
+#define        SEARCH_CSEARCH  0x000002        /* Compile search replacement. */
+#define        SEARCH_CSUBST   0x000004        /* Compile substitute replacement. */
+#define        SEARCH_EOL      0x000008        /* Offset past EOL is okay. */
+#define        SEARCH_EXTEND   0x000010        /* Extended RE. */
+#define        SEARCH_FIRST    0x000020        /* Search from the first line. */
+#define        SEARCH_IC       0x000040        /* Ignore case. */
+#define        SEARCH_ICL      0x000080        /* Ignore case. */
+#define        SEARCH_INCR     0x000100        /* Search incrementally. */
+#define        SEARCH_LITERAL  0x000200        /* Literal string. */
+#define        SEARCH_MSG      0x000400        /* Display search messages. */
+#define        SEARCH_NOOPT    0x000800        /* Ignore edit options. */
+#define        SEARCH_PARSE    0x001000        /* Parse the search pattern. */
+#define        SEARCH_SET      0x002000        /* Set search direction. */
+#define        SEARCH_TAG      0x004000        /* Search for a tag pattern. */
+#define        SEARCH_WMSG     0x008000        /* Display search-wrapped messages. */
+#define        SEARCH_WRAP     0x010000        /* Wrap past sof/eof. */
+
+                                       /* Ex/vi: RE information. */
+       dir_t    searchdir;             /* Last file search direction. */
+       regex_t  re_c;                  /* Search RE: compiled form. */
+       CHAR_T  *re;                    /* Search RE: uncompiled form. */
+       size_t   re_len;                /* Search RE: uncompiled length. */
+       regex_t  subre_c;               /* Substitute RE: compiled form. */
+       CHAR_T  *subre;                 /* Substitute RE: uncompiled form. */
+       size_t   subre_len;             /* Substitute RE: uncompiled length). */
+       CHAR_T  *repl;                  /* Substitute replacement. */
+       size_t   repl_len;              /* Substitute replacement length.*/
+       size_t  *newl;                  /* Newline offset array. */
+       size_t   newl_len;              /* Newline array size. */
+       size_t   newl_cnt;              /* Newlines in replacement. */
+       u_int8_t c_suffix;              /* Edcompatible 'c' suffix value. */
+       u_int8_t g_suffix;              /* Edcompatible 'g' suffix value. */
+
+       OPTION   opts[O_OPTIONCOUNT];   /* Ex/vi: Options. */
+
+/*
+ * Screen flags.
+ *
+ * Editor screens.
+ */
+#define        SC_EX           0x00000001      /* Ex editor. */
+#define        SC_VI           0x00000002      /* Vi editor. */
+
+/*
+ * Screen formatting flags, first major, then minor.
+ *
+ * SC_SCR_EX
+ *     Ex screen, i.e. cooked mode.
+ * SC_SCR_VI
+ *     Vi screen, i.e. raw mode.
+ * SC_SCR_EXWROTE
+ *     The editor had to write on the screen behind curses' back, and we can't
+ *     let curses change anything until the user agrees, e.g. entering the
+ *     commands :!utility followed by :set.  We have to switch back into the
+ *     vi "editor" to read the user's command input, but we can't touch the
+ *     rest of the screen because it's known to be wrong.
+ * SC_SCR_REFORMAT
+ *     The expected presentation of the lines on the screen have changed,
+ *     requiring that the intended screen lines be recalculated.  Implies
+ *     SC_SCR_REDRAW.
+ * SC_SCR_REDRAW
+ *     The screen doesn't correctly represent the file; repaint it.  Note,
+ *     setting SC_SCR_REDRAW in the current window causes *all* windows to
+ *     be repainted.
+ * SC_SCR_CENTER
+ *     If the current line isn't already on the screen, center it.
+ * SC_SCR_TOP
+ *     If the current line isn't already on the screen, put it at the to@.
+ */
+#define        SC_SCR_EX       0x00000004      /* Screen is in ex mode. */
+#define        SC_SCR_VI       0x00000008      /* Screen is in vi mode. */
+#define        SC_SCR_EXWROTE  0x00000010      /* Ex overwrite: see comment above. */
+#define        SC_SCR_REFORMAT 0x00000020      /* Reformat (refresh). */
+#define        SC_SCR_REDRAW   0x00000040      /* Refresh. */
+
+#define        SC_SCR_CENTER   0x00000080      /* Center the line if not visible. */
+#define        SC_SCR_TOP      0x00000100      /* Top the line if not visible. */
+
+/* Screen/file changes. */
+#define        SC_EXIT         0x00000200      /* Exiting (not forced). */
+#define        SC_EXIT_FORCE   0x00000400      /* Exiting (forced). */
+#define        SC_FSWITCH      0x00000800      /* Switch underlying files. */
+#define        SC_SSWITCH      0x00001000      /* Switch screens. */
+
+#define        SC_ARGNOFREE    0x00002000      /* Argument list wasn't allocated. */
+#define        SC_ARGRECOVER   0x00004000      /* Argument list is recovery files. */
+#define        SC_AT_SET       0x00008000      /* Last at buffer set. */
+#define        SC_COMEDIT      0x00010000      /* Colon command-line edit window. */
+#define        SC_EX_GLOBAL    0x00020000      /* Ex: executing a global command. */
+#define        SC_EX_SILENT    0x00040000      /* Ex: batch script. */
+#define        SC_EX_WAIT_NO   0x00080000      /* Ex: don't wait for the user. */
+#define        SC_EX_WAIT_YES  0x00100000      /* Ex:    do wait for the user. */
+#define        SC_READONLY     0x00200000      /* Persistent readonly state. */
+#define        SC_RE_SEARCH    0x00400000      /* Search RE has been compiled. */
+#define        SC_RE_SUBST     0x00800000      /* Substitute RE has been compiled. */
+#define        SC_SCRIPT       0x01000000      /* Shell script window. */
+#define        SC_STATUS       0x02000000      /* Welcome message. */
+#define        SC_STATUS_CNT   0x04000000      /* Welcome message plus file count. */
+#define        SC_TINPUT       0x08000000      /* Doing text input. */
+#define        SC_TINPUT_INFO  0x10000000      /* Doing text input on info line. */
+#define SC_CONV_ERROR  0x20000000      /* Met with a conversion error. */
+       u_int32_t flags;
+
+       int         db_error;           /* Return code from db function. */
+};
diff --git a/dist/nvi/common/search.c b/dist/nvi/common/search.c
new file mode 100644 (file)
index 0000000..5317e6b
--- /dev/null
@@ -0,0 +1,482 @@
+/*     $NetBSD: search.c,v 1.3 2009/01/22 10:33:58 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: search.c,v 10.31 2001/06/25 15:19:12 skimo Exp (Berkeley) Date: 2001/06/25 15:19:12";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+typedef enum { S_EMPTY, S_EOF, S_NOPREV, S_NOTFOUND, S_SOF, S_WRAP } smsg_t;
+
+static void    search_msg __P((SCR *, smsg_t));
+static int     search_init __P((SCR *, dir_t, CHAR_T *, size_t, CHAR_T **, u_int));
+
+/*
+ * search_init --
+ *     Set up a search.
+ */
+static int
+search_init(SCR *sp, dir_t dir, CHAR_T *ptrn, size_t plen, CHAR_T **epp, u_int flags)
+{
+       db_recno_t lno;
+       int delim;
+       CHAR_T *p, *t;
+
+       /* If the file is empty, it's a fast search. */
+       if (sp->lno <= 1) {
+               if (db_last(sp, &lno))
+                       return (1);
+               if (lno == 0) {
+                       if (LF_ISSET(SEARCH_MSG))
+                               search_msg(sp, S_EMPTY);
+                       return (1);
+               }
+       }
+
+       if (LF_ISSET(SEARCH_PARSE)) {           /* Parse the string. */
+               /*
+                * Use the saved pattern if no pattern specified, or if only
+                * one or two delimiter characters specified.
+                *
+                * !!!
+                * Historically, only the pattern itself was saved, vi didn't
+                * preserve addressing or delta information.
+                */
+               if (ptrn == NULL)
+                       goto prev;
+               if (plen == 1) {
+                       if (epp != NULL)
+                               *epp = ptrn + 1;
+                       goto prev;
+               }
+               if (ptrn[0] == ptrn[1]) {
+                       if (epp != NULL)
+                               *epp = ptrn + 2;
+
+                       /* Complain if we don't have a previous pattern. */
+prev:                  if (sp->re == NULL) {
+                               search_msg(sp, S_NOPREV);
+                               return (1);
+                       }
+                       /* Re-compile the search pattern if necessary. */
+                       if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
+                           sp->re, sp->re_len, NULL, NULL, &sp->re_c,
+                           SEARCH_CSEARCH | SEARCH_MSG))
+                               return (1);
+
+                       /* Set the search direction. */
+                       if (LF_ISSET(SEARCH_SET))
+                               sp->searchdir = dir;
+                       return (0);
+               }
+
+               /*
+                * Set the delimiter, and move forward to the terminating
+                * delimiter, handling escaped delimiters.
+                *
+                * QUOTING NOTE:
+                * Only discard an escape character if it escapes a delimiter.
+                */
+               for (delim = *ptrn, p = t = ++ptrn;; *t++ = *p++) {
+                       if (--plen == 0 || p[0] == delim) {
+                               if (plen != 0)
+                                       ++p;
+                               break;
+                       }
+                       if (plen > 1 && p[0] == '\\' && p[1] == delim) {
+                               ++p;
+                               --plen;
+                       }
+               }
+               if (epp != NULL)
+                       *epp = p;
+
+               plen = t - ptrn;
+       }
+
+       /* Compile the RE. */
+       if (re_compile(sp, ptrn, plen, &sp->re, &sp->re_len, &sp->re_c,
+           SEARCH_CSEARCH | LF_ISSET(SEARCH_CSCOPE | SEARCH_IC |
+           SEARCH_LITERAL | SEARCH_MSG | SEARCH_TAG)))
+               return (1);
+
+       /* Set the search direction. */
+       if (LF_ISSET(SEARCH_SET))
+               sp->searchdir = dir;
+
+       return (0);
+}
+
+/*
+ * f_search --
+ *     Do a forward search.
+ *
+ * PUBLIC: int f_search __P((SCR *,
+ * PUBLIC:    MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int));
+ */
+int
+f_search(SCR *sp, MARK *fm, MARK *rm, CHAR_T *ptrn, size_t plen, CHAR_T **eptrn, u_int flags)
+{
+       busy_t btype;
+       db_recno_t lno;
+       regmatch_t match[1];
+       size_t coff, len;
+       int cnt, eval, rval, wrapped;
+       CHAR_T *l;
+
+       if (search_init(sp, FORWARD, ptrn, plen, eptrn, flags))
+               return (1);
+
+       /* Figure out if we're going to wrap. */
+       if (!LF_ISSET(SEARCH_NOOPT) && O_ISSET(sp, O_WRAPSCAN))
+               LF_SET(SEARCH_WRAP);
+
+       if (LF_ISSET(SEARCH_FIRST)) {
+               lno = 1;
+               coff = 0;
+       } else {
+               if (db_get(sp, fm->lno, DBG_FATAL, &l, &len))
+                       return (1);
+               lno = fm->lno;
+
+               /*
+                * If doing incremental search, start searching at the previous
+                * column, so that we search a minimal distance and still match
+                * special patterns, e.g., \< for beginning of a word.
+                *
+                * Otherwise, start searching immediately after the cursor.  If
+                * at the end of the line, start searching on the next line.
+                * This is incompatible (read bug fix) with the historic vi --
+                * searches for the '$' pattern never moved forward, and the
+                * "-t foo" didn't work if the 'f' was the first character in
+                * the file.
+                */
+               if (LF_ISSET(SEARCH_INCR)) {
+                       if ((coff = fm->cno) != 0)
+                               --coff;
+               } else if (fm->cno + 1 >= len) {
+                       coff = 0;
+                       lno = fm->lno + 1;
+                       if (db_get(sp, lno, 0, &l, &len)) {
+                               if (!LF_ISSET(SEARCH_WRAP)) {
+                                       if (LF_ISSET(SEARCH_MSG))
+                                               search_msg(sp, S_EOF);
+                                       return (1);
+                               }
+                               lno = 1;
+                       }
+               } else
+                       coff = fm->cno + 1;
+       }
+
+       btype = BUSY_ON;
+       for (cnt = INTERRUPT_CHECK, rval = 1, wrapped = 0;; ++lno, coff = 0) {
+               if (cnt-- == 0) {
+                       if (INTERRUPTED(sp))
+                               break;
+                       if (LF_ISSET(SEARCH_MSG)) {
+                               search_busy(sp, btype);
+                               btype = BUSY_UPDATE;
+                       }
+                       cnt = INTERRUPT_CHECK;
+               }
+               if ((wrapped && lno > fm->lno) ||
+                   db_get(sp, lno, 0, &l, &len)) {
+                       if (wrapped) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       search_msg(sp, S_NOTFOUND);
+                               break;
+                       }
+                       if (!LF_ISSET(SEARCH_WRAP)) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       search_msg(sp, S_EOF);
+                               break;
+                       }
+                       lno = 0;
+                       wrapped = 1;
+                       continue;
+               }
+
+               /* If already at EOL, just keep going. */
+               if (len != 0 && coff == len)
+                       continue;
+
+               /* Set the termination. */
+               match[0].rm_so = coff;
+               match[0].rm_eo = len;
+
+#if defined(DEBUG) && 0
+               vtrace(sp, "F search: %lu from %u to %u\n",
+                   lno, coff, len != 0 ? len - 1 : len);
+#endif
+               /* Search the line. */
+               eval = regexec(&sp->re_c, l, 1, match,
+                   (match[0].rm_so == 0 ? 0 : REG_NOTBOL) | REG_STARTEND);
+               if (eval == REG_NOMATCH)
+                       continue;
+               if (eval != 0) {
+                       if (LF_ISSET(SEARCH_MSG))
+                               re_error(sp, eval, &sp->re_c);
+                       else
+                               (void)sp->gp->scr_bell(sp);
+                       break;
+               }
+
+               /* Warn if the search wrapped. */
+               if (wrapped && LF_ISSET(SEARCH_WMSG))
+                       search_msg(sp, S_WRAP);
+
+#if defined(DEBUG) && 0
+               vtrace(sp, "F search: %qu to %qu\n",
+                   match[0].rm_so, match[0].rm_eo);
+#endif
+               rm->lno = lno;
+               rm->cno = match[0].rm_so;
+
+               /*
+                * If a change command, it's possible to move beyond the end
+                * of a line.  Historic vi generally got this wrong (e.g. try
+                * "c?$<cr>").  Not all that sure this gets it right, there
+                * are lots of strange cases.
+                */
+               if (!LF_ISSET(SEARCH_EOL) && rm->cno >= len)
+                       rm->cno = len != 0 ? len - 1 : 0;
+
+               rval = 0;
+               break;
+       }
+
+       if (LF_ISSET(SEARCH_MSG))
+               search_busy(sp, BUSY_OFF);
+       return (rval);
+}
+
+/*
+ * b_search --
+ *     Do a backward search.
+ *
+ * PUBLIC: int b_search __P((SCR *,
+ * PUBLIC:    MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int));
+ */
+int
+b_search(SCR *sp, MARK *fm, MARK *rm, CHAR_T *ptrn, size_t plen, CHAR_T **eptrn, u_int flags)
+{
+       busy_t btype;
+       db_recno_t lno;
+       regmatch_t match[1];
+       size_t coff, last, len;
+       int cnt, eval, rval, wrapped;
+       CHAR_T *l;
+
+       if (search_init(sp, BACKWARD, ptrn, plen, eptrn, flags))
+               return (1);
+
+       /* Figure out if we're going to wrap. */
+       if (!LF_ISSET(SEARCH_NOOPT) && O_ISSET(sp, O_WRAPSCAN))
+               LF_SET(SEARCH_WRAP);
+
+       /*
+        * If doing incremental search, set the "starting" position past the
+        * current column, so that we search a minimal distance and still
+        * match special patterns, e.g., \> for the end of a word.  This is
+        * safe when the cursor is at the end of a line because we only use
+        * it for comparison with the location of the match.
+        *
+        * Otherwise, start searching immediately before the cursor.  If in
+        * the first column, start search on the previous line.
+        */
+       if (LF_ISSET(SEARCH_INCR)) {
+               lno = fm->lno;
+               coff = fm->cno + 1;
+       } else {
+               if (fm->cno == 0) {
+                       if (fm->lno == 1 && !LF_ISSET(SEARCH_WRAP)) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       search_msg(sp, S_SOF);
+                               return (1);
+                       }
+                       lno = fm->lno - 1;
+               } else
+                       lno = fm->lno;
+               coff = fm->cno;
+       }
+
+       btype = BUSY_ON;
+       for (cnt = INTERRUPT_CHECK, rval = 1, wrapped = 0;; --lno, coff = 0) {
+               if (cnt-- == 0) {
+                       if (INTERRUPTED(sp))
+                               break;
+                       if (LF_ISSET(SEARCH_MSG)) {
+                               search_busy(sp, btype);
+                               btype = BUSY_UPDATE;
+                       }
+                       cnt = INTERRUPT_CHECK;
+               }
+               if ((wrapped && lno < fm->lno) || lno == 0) {
+                       if (wrapped) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       search_msg(sp, S_NOTFOUND);
+                               break;
+                       }
+                       if (!LF_ISSET(SEARCH_WRAP)) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       search_msg(sp, S_SOF);
+                               break;
+                       }
+                       if (db_last(sp, &lno))
+                               break;
+                       if (lno == 0) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       search_msg(sp, S_EMPTY);
+                               break;
+                       }
+                       ++lno;
+                       wrapped = 1;
+                       continue;
+               }
+
+               if (db_get(sp, lno, 0, &l, &len))
+                       break;
+
+               /* Set the termination. */
+               match[0].rm_so = 0;
+               match[0].rm_eo = len;
+
+#if defined(DEBUG) && 0
+               vtrace(sp,
+                   "B search: %lu from 0 to %qu\n", lno, match[0].rm_eo);
+#endif
+               /* Search the line. */
+               eval = regexec(&sp->re_c, l, 1, match,
+                   ((size_t)match[0].rm_eo == len ? 0 : REG_NOTEOL) | REG_STARTEND);
+               if (eval == REG_NOMATCH)
+                       continue;
+               if (eval != 0) {
+                       if (LF_ISSET(SEARCH_MSG))
+                               re_error(sp, eval, &sp->re_c);
+                       else
+                               (void)sp->gp->scr_bell(sp);
+                       break;
+               }
+
+               /* Check for a match starting past the cursor. */
+               if (coff != 0 && (size_t)match[0].rm_so >= coff)
+                       continue;
+
+               /* Warn if the search wrapped. */
+               if (wrapped && LF_ISSET(SEARCH_WMSG))
+                       search_msg(sp, S_WRAP);
+
+#if defined(DEBUG) && 0
+               vtrace(sp, "B found: %qu to %qu\n",
+                   match[0].rm_so, match[0].rm_eo);
+#endif
+               /*
+                * We now have the first match on the line.  Step through the
+                * line character by character until find the last acceptable
+                * match.  This is painful, we need a better interface to regex
+                * to make this work.
+                */
+               for (;;) {
+                       last = match[0].rm_so++;
+                       if ((size_t)match[0].rm_so >= len)
+                               break;
+                       match[0].rm_eo = len;
+                       eval = regexec(&sp->re_c, l, 1, match,
+                           (match[0].rm_so == 0 ? 0 : REG_NOTBOL) |
+                           REG_STARTEND);
+                       if (eval == REG_NOMATCH)
+                               break;
+                       if (eval != 0) {
+                               if (LF_ISSET(SEARCH_MSG))
+                                       re_error(sp, eval, &sp->re_c);
+                               else
+                                       (void)sp->gp->scr_bell(sp);
+                               goto err;
+                       }
+                       if (coff && (size_t)match[0].rm_so >= coff)
+                               break;
+               }
+               rm->lno = lno;
+
+               /* See comment in f_search(). */
+               if (!LF_ISSET(SEARCH_EOL) && last >= len)
+                       rm->cno = len != 0 ? len - 1 : 0;
+               else
+                       rm->cno = last;
+               rval = 0;
+               break;
+       }
+
+err:   if (LF_ISSET(SEARCH_MSG))
+               search_busy(sp, BUSY_OFF);
+       return (rval);
+}
+
+/*
+ * search_msg --
+ *     Display one of the search messages.
+ */
+static void
+search_msg(SCR *sp, smsg_t msg)
+{
+       switch (msg) {
+       case S_EMPTY:
+               msgq(sp, M_ERR, "072|File empty; nothing to search");
+               break;
+       case S_EOF:
+               msgq(sp, M_ERR,
+                   "073|Reached end-of-file without finding the pattern");
+               break;
+       case S_NOPREV:
+               msgq(sp, M_ERR, "074|No previous search pattern");
+               break;
+       case S_NOTFOUND:
+               msgq(sp, M_ERR, "075|Pattern not found");
+               break;
+       case S_SOF:
+               msgq(sp, M_ERR,
+                   "076|Reached top-of-file without finding the pattern");
+               break;
+       case S_WRAP:
+               msgq(sp, M_ERR, "077|Search wrapped");
+               break;
+       default:
+               abort();
+       }
+}
+
+/*
+ * search_busy --
+ *     Put up the busy searching message.
+ *
+ * PUBLIC: void search_busy __P((SCR *, busy_t));
+ */
+void
+search_busy(SCR *sp, busy_t btype)
+{
+       sp->gp->scr_busy(sp, "078|Searching...", btype);
+}
diff --git a/dist/nvi/common/seq.c b/dist/nvi/common/seq.c
new file mode 100644 (file)
index 0000000..4361ba2
--- /dev/null
@@ -0,0 +1,369 @@
+/*     $NetBSD: seq.c,v 1.3 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: seq.c,v 10.15 2001/06/25 15:19:12 skimo Exp (Berkeley) Date: 2001/06/25 15:19:12";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+/*
+ * seq_set --
+ *     Internal version to enter a sequence.
+ *
+ * PUBLIC: int seq_set __P((SCR *, CHAR_T *,
+ * PUBLIC:    size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int));
+ */
+int
+seq_set(SCR *sp, CHAR_T *name, size_t nlen, CHAR_T *input, size_t ilen, CHAR_T *output, size_t olen, seq_t stype, int flags)
+{
+       CHAR_T *p;
+       SEQ *lastqp, *qp;
+       int sv_errno;
+
+       /*
+        * An input string must always be present.  The output string
+        * can be NULL, when set internally, that's how we throw away
+        * input.
+        *
+        * Just replace the output field if the string already set.
+        */
+       if ((qp =
+           seq_find(sp, &lastqp, NULL, input, ilen, stype, NULL)) != NULL) {
+               if (LF_ISSET(SEQ_NOOVERWRITE))
+                       return (0);
+               if (output == NULL || olen == 0) {
+                       p = NULL;
+                       olen = 0;
+               } else if ((p = v_wstrdup(sp, output, olen)) == NULL) {
+                       sv_errno = errno;
+                       goto mem1;
+               }
+               if (qp->output != NULL)
+                       free(qp->output);
+               qp->olen = olen;
+               qp->output = p;
+               return (0);
+       }
+
+       /* Allocate and initialize SEQ structure. */
+       CALLOC(sp, qp, SEQ *, 1, sizeof(SEQ));
+       if (qp == NULL) {
+               sv_errno = errno;
+               goto mem1;
+       }
+
+       /* Name. */
+       if (name == NULL || nlen == 0)
+               qp->name = NULL;
+       else if ((qp->name = v_wstrdup(sp, name, nlen)) == NULL) {
+               sv_errno = errno;
+               goto mem2;
+       }
+       qp->nlen = nlen;
+
+       /* Input. */
+       if ((qp->input = v_wstrdup(sp, input, ilen)) == NULL) {
+               sv_errno = errno;
+               goto mem3;
+       }
+       qp->ilen = ilen;
+
+       /* Output. */
+       if (output == NULL) {
+               qp->output = NULL;
+               olen = 0;
+       } else if ((qp->output = v_wstrdup(sp, output, olen)) == NULL) {
+               sv_errno = errno;
+               free(qp->input);
+mem3:          if (qp->name != NULL)
+                       free(qp->name);
+mem2:          free(qp);
+mem1:          errno = sv_errno;
+               msgq(sp, M_SYSERR, NULL);
+               return (1);
+       }
+       qp->olen = olen;
+
+       /* Type, flags. */
+       qp->stype = stype;
+       qp->flags = flags;
+
+       /* Link into the chain. */
+       if (lastqp == NULL) {
+               LIST_INSERT_HEAD(&sp->gp->seqq, qp, q);
+       } else {
+               LIST_INSERT_AFTER(lastqp, qp, q);
+       }
+
+       /* Set the fast lookup bit. */
+       if ((qp->input[0] & ~MAX_BIT_SEQ) == 0)
+               bit_set(sp->gp->seqb, qp->input[0]);
+
+       return (0);
+}
+
+/*
+ * seq_delete --
+ *     Delete a sequence.
+ *
+ * PUBLIC: int seq_delete __P((SCR *, CHAR_T *, size_t, seq_t));
+ */
+int
+seq_delete(SCR *sp, CHAR_T *input, size_t ilen, seq_t stype)
+{
+       SEQ *qp;
+
+       if ((qp = seq_find(sp, NULL, NULL, input, ilen, stype, NULL)) == NULL)
+               return (1);
+       return (seq_mdel(qp));
+}
+
+/*
+ * seq_mdel --
+ *     Delete a map entry, without lookup.
+ *
+ * PUBLIC: int seq_mdel __P((SEQ *));
+ */
+int
+seq_mdel(SEQ *qp)
+{
+       LIST_REMOVE(qp, q);
+       if (qp->name != NULL)
+               free(qp->name);
+       free(qp->input);
+       if (qp->output != NULL)
+               free(qp->output);
+       free(qp);
+       return (0);
+}
+
+/*
+ * seq_find --
+ *     Search the sequence list for a match to a buffer, if ispartial
+ *     isn't NULL, partial matches count.
+ *
+ * PUBLIC: SEQ *seq_find
+ * PUBLIC:    __P((SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *));
+ */
+SEQ *
+seq_find(SCR *sp, SEQ **lastqp, EVENT *e_input, CHAR_T *c_input, size_t ilen, seq_t stype, int *ispartialp)
+{
+       SEQ *lqp, *qp;
+       int diff;
+
+       /*
+        * Ispartialp is a location where we return if there was a
+        * partial match, i.e. if the string were extended it might
+        * match something.
+        *
+        * XXX
+        * Overload the meaning of ispartialp; only the terminal key
+        * search doesn't want the search limited to complete matches,
+        * i.e. ilen may be longer than the match.
+        */
+       if (ispartialp != NULL)
+               *ispartialp = 0;
+       for (lqp = NULL, qp = sp->gp->seqq.lh_first;
+           qp != NULL; lqp = qp, qp = qp->q.le_next) {
+               /*
+                * Fast checks on the first character and type, and then
+                * a real comparison.
+                */
+               if (e_input == NULL) {
+                       if (qp->input[0] > c_input[0])
+                               break;
+                       if (qp->input[0] < c_input[0] ||
+                           qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
+                               continue;
+                       diff = MEMCMP(qp->input, c_input, MIN(qp->ilen, ilen));
+               } else {
+                       if (qp->input[0] > e_input->e_c)
+                               break;
+                       if (qp->input[0] < e_input->e_c ||
+                           qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
+                               continue;
+                       diff =
+                           e_memcmp(qp->input, e_input, MIN(qp->ilen, ilen));
+               }
+               if (diff > 0)
+                       break;
+               if (diff < 0)
+                       continue;
+               /*
+                * If the entry is the same length as the string, return a
+                * match.  If the entry is shorter than the string, return a
+                * match if called from the terminal key routine.  Otherwise,
+                * keep searching for a complete match.
+                */
+               if (qp->ilen <= ilen) {
+                       if (qp->ilen == ilen || ispartialp != NULL) {
+                               if (lastqp != NULL)
+                                       *lastqp = lqp;
+                               return (qp);
+                       }
+                       continue;
+               }
+               /*
+                * If the entry longer than the string, return partial match
+                * if called from the terminal key routine.  Otherwise, no
+                * match.
+                */
+               if (ispartialp != NULL)
+                       *ispartialp = 1;
+               break;
+       }
+       if (lastqp != NULL)
+               *lastqp = lqp;
+       return (NULL);
+}
+
+/*
+ * seq_close --
+ *     Discard all sequences.
+ *
+ * PUBLIC: void seq_close __P((GS *));
+ */
+void
+seq_close(GS *gp)
+{
+       SEQ *qp;
+
+       while ((qp = gp->seqq.lh_first) != NULL) {
+               if (qp->name != NULL)
+                       free(qp->name);
+               if (qp->input != NULL)
+                       free(qp->input);
+               if (qp->output != NULL)
+                       free(qp->output);
+               LIST_REMOVE(qp, q);
+               free(qp);
+       }
+}
+
+/*
+ * seq_dump --
+ *     Display the sequence entries of a specified type.
+ *
+ * PUBLIC: int seq_dump __P((SCR *, seq_t, int));
+ */
+int
+seq_dump(SCR *sp, seq_t stype, int isname)
+{
+       CHAR_T *p;
+       GS *gp;
+       SEQ *qp;
+       int cnt, len, olen;
+
+       cnt = 0;
+       gp = sp->gp;
+       for (qp = gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
+               if (stype != qp->stype || F_ISSET(qp, SEQ_FUNCMAP))
+                       continue;
+               ++cnt;
+               for (p = qp->input,
+                   olen = qp->ilen, len = 0; olen > 0; --olen, ++p)
+                       len += ex_puts(sp, (char *)KEY_NAME(sp, *p));
+               for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
+                       len -= ex_puts(sp, " ");
+
+               if (qp->output != NULL)
+                       for (p = qp->output,
+                           olen = qp->olen, len = 0; olen > 0; --olen, ++p)
+                               len += ex_puts(sp, (char *)KEY_NAME(sp, *p));
+               else
+                       len = 0;
+
+               if (isname && qp->name != NULL) {
+                       for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
+                               len -= ex_puts(sp, " ");
+                       for (p = qp->name,
+                           olen = qp->nlen; olen > 0; --olen, ++p)
+                               (void)ex_puts(sp, (char *)KEY_NAME(sp, *p));
+               }
+               (void)ex_puts(sp, "\n");
+       }
+       return (cnt);
+}
+
+/*
+ * seq_save --
+ *     Save the sequence entries to a file.
+ *
+ * PUBLIC: int seq_save __P((SCR *, FILE *, char *, seq_t));
+ */
+int
+seq_save(SCR *sp, FILE *fp, const char *prefix, seq_t stype)
+{
+       CHAR_T *p;
+       SEQ *qp;
+       size_t olen;
+       ARG_CHAR_T ch;
+
+       /* Write a sequence command for all keys the user defined. */
+       for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
+               if (stype != qp->stype || !F_ISSET(qp, SEQ_USERDEF))
+                       continue;
+               if (prefix)
+                       (void)fprintf(fp, "%s", prefix);
+               for (p = qp->input, olen = qp->ilen; olen > 0; --olen) {
+                       ch = (UCHAR_T)*p++;
+                       if (ch == CH_LITERAL || ch == '|' ||
+                           ISBLANK(ch) || KEY_VAL(sp, ch) == K_NL)
+                               (void)putc(CH_LITERAL, fp);
+                       (void)fprintf(fp, WC, ch);
+               }
+               (void)putc(' ', fp);
+               if (qp->output != NULL)
+                       for (p = qp->output,
+                           olen = qp->olen; olen > 0; --olen) {
+                               ch = (UCHAR_T)*p++;
+                               if (ch == CH_LITERAL || ch == '|' ||
+                                   KEY_VAL(sp, ch) == K_NL)
+                                       (void)putc(CH_LITERAL, fp);
+                               (void)fprintf(fp, WC, ch);
+                       }
+               (void)putc('\n', fp);
+       }
+       return (0);
+}
+
+/*
+ * e_memcmp --
+ *     Compare a string of EVENT's to a string of CHAR_T's.
+ *
+ * PUBLIC: int e_memcmp __P((CHAR_T *, EVENT *, size_t));
+ */
+int
+e_memcmp(CHAR_T *p1, EVENT *ep, size_t n)
+{
+       if (n != 0) {
+                do {
+                        if (*p1++ != ep->e_c)
+                                return (*--p1 - ep->e_c);
+                       ++ep;
+                } while (--n != 0);
+        }
+        return (0);
+}
diff --git a/dist/nvi/common/seq.h b/dist/nvi/common/seq.h
new file mode 100644 (file)
index 0000000..41c5013
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: seq.h,v 1.1.1.2 2008/05/18 14:29:52 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: seq.h,v 10.3 1996/03/06 19:51:03 bostic Exp (Berkeley) Date: 1996/03/06 19:51:03
+ */
+
+/*
+ * Map and abbreviation structures.
+ *
+ * The map structure is doubly linked list, sorted by input string and by
+ * input length within the string.  (The latter is necessary so that short
+ * matches will happen before long matches when the list is searched.)
+ * Additionally, there is a bitmap which has bits set if there are entries
+ * starting with the corresponding character.  This keeps us from walking
+ * the list unless it's necessary.
+ *
+ * The name and the output fields of a SEQ can be empty, i.e. NULL.
+ * Only the input field is required.
+ *
+ * XXX
+ * The fast-lookup bits are never turned off -- users don't usually unmap
+ * things, though, so it's probably not a big deal.
+ */
+struct _seq {
+       LIST_ENTRY(_seq) q;             /* Linked list of all sequences. */
+       seq_t    stype;                 /* Sequence type. */
+       CHAR_T  *name;                  /* Sequence name (if any). */
+       size_t   nlen;                  /* Name length. */
+       CHAR_T  *input;                 /* Sequence input keys. */
+       size_t   ilen;                  /* Input keys length. */
+       CHAR_T  *output;                /* Sequence output keys. */
+       size_t   olen;                  /* Output keys length. */
+
+#define        SEQ_FUNCMAP     0x01            /* If unresolved function key.*/
+#define        SEQ_NOOVERWRITE 0x02            /* Don't replace existing entry. */
+#define        SEQ_SCREEN      0x04            /* If screen specific. */
+#define        SEQ_USERDEF     0x08            /* If user defined. */
+       u_int8_t flags;
+};
diff --git a/dist/nvi/common/trace.c b/dist/nvi/common/trace.c
new file mode 100644 (file)
index 0000000..ae0c5b9
--- /dev/null
@@ -0,0 +1,93 @@
+/*     $NetBSD: trace.c,v 1.1.1.2 2008/05/18 14:29:52 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: trace.c,v 8.4 1997/08/03 15:04:23 bostic Exp (Berkeley) Date: 1997/08/03 15:04:23";
+#endif /* not lint */
+
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "common.h"
+
+#ifdef TRACE
+
+static FILE *tfp;
+
+/*
+ * vtrace_end --
+ *     End tracing.
+ *
+ * PUBLIC: void vtrace_end __P((void));
+ */
+void
+vtrace_end()
+{
+       if (tfp != NULL && tfp != stderr)
+               (void)fclose(tfp);
+}
+
+/*
+ * vtrace_init --
+ *     Initialize tracing.
+ *
+ * PUBLIC: void vtrace_init __P((char *));
+ */
+void
+vtrace_init(name)
+       char *name;
+{
+       if (name == NULL || (tfp = fopen(name, "w")) == NULL)
+               tfp = stderr;
+       vtrace("\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\nTRACE\n");
+}
+
+/*
+ * vtrace --
+ *     Debugging trace routine.
+ *
+ * PUBLIC: void vtrace __P((const char *, ...));
+ */
+void
+#ifdef __STDC__
+vtrace(const char *fmt, ...)
+#else
+vtrace(fmt, va_alist)
+       char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+
+       if (tfp == NULL)
+               vtrace_init(NULL);
+
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)vfprintf(tfp, fmt, ap);
+       va_end(ap);
+
+       (void)fflush(tfp);
+}
+#endif
diff --git a/dist/nvi/common/util.c b/dist/nvi/common/util.c
new file mode 100644 (file)
index 0000000..6fc793f
--- /dev/null
@@ -0,0 +1,196 @@
+/*     $NetBSD: util.c,v 1.4 2011/03/21 14:53:02 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: util.c,v 10.22 2001/06/25 15:19:12 skimo Exp (Berkeley) Date: 2001/06/25 15:19:12";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+/*
+ * binc --
+ *     Increase the size of a buffer.
+ *
+ * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
+ */
+void *
+binc(SCR *sp, void *bp, size_t *bsizep, size_t min)
+                                       /* sp MAY BE NULL!!! */
+                
+                           
+{
+       size_t csize;
+
+       /* If already larger than the minimum, just return. */
+       if (min && *bsizep >= min)
+               return (bp);
+
+       csize = *bsizep + MAX(min, 256);
+       REALLOC(sp, bp, void *, csize);
+
+       if (bp == NULL) {
+               /*
+                * Theoretically, realloc is supposed to leave any already
+                * held memory alone if it can't get more.  Don't trust it.
+                */
+               *bsizep = 0;
+               return (NULL);
+       }
+       /*
+        * Memory is guaranteed to be zero-filled, various parts of
+        * nvi depend on this.
+        */
+       memset((char *)bp + *bsizep, 0, csize - *bsizep);
+       *bsizep = csize;
+       return (bp);
+}
+
+/*
+ * nonblank --
+ *     Set the column number of the first non-blank character
+ *     including or after the starting column.  On error, set
+ *     the column to 0, it's safest.
+ *
+ * PUBLIC: int nonblank __P((SCR *, db_recno_t, size_t *));
+ */
+int
+nonblank(SCR *sp, db_recno_t lno, size_t *cnop)
+{
+       CHAR_T *p;
+       size_t cnt, len, off;
+       int isempty;
+
+       /* Default. */
+       off = *cnop;
+       *cnop = 0;
+
+       /* Get the line, succeeding in an empty file. */
+       if (db_eget(sp, lno, &p, &len, &isempty))
+               return (!isempty);
+
+       /* Set the offset. */
+       if (len == 0 || off >= len)
+               return (0);
+
+       for (cnt = off, p = &p[off],
+           len -= off; len && ISBLANK((UCHAR_T)*p); ++cnt, ++p, --len);
+
+       /* Set the return. */
+       *cnop = len ? cnt : cnt - 1;
+       return (0);
+}
+
+/*
+ * tail --
+ *     Return tail of a path.
+ *
+ * PUBLIC: char *tail __P((char *));
+ */
+const char *
+tail(const char *path)
+{
+       const char *p;
+
+       if ((p = strrchr(path, '/')) == NULL)
+               return (path);
+       return (p + 1);
+}
+
+/*
+ * v_strdup --
+ *     Strdup for wide character strings with an associated length.
+ *
+ * PUBLIC: char *v_strdup __P((SCR *, const char *, size_t));
+ */
+char *
+v_strdup(SCR *sp, const char *str, size_t len)
+{
+       char *copy;
+
+       MALLOC(sp, copy, char *, (len + 1));
+       if (copy == NULL)
+               return (NULL);
+       memcpy(copy, str, len);
+       copy[len] = '\0';
+       return (copy);
+}
+
+/*
+ * v_strdup --
+ *     Strdup for wide character strings with an associated length.
+ *
+ * PUBLIC: CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t));
+ */
+CHAR_T *
+v_wstrdup(SCR *sp, const CHAR_T *str, size_t len)
+{
+       CHAR_T *copy;
+
+       MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T));
+       if (copy == NULL)
+               return (NULL);
+       MEMCPYW(copy, str, len);
+       copy[len] = '\0';
+       return (copy);
+}
+
+/*
+ * nget_uslong --
+ *      Get an unsigned long, checking for overflow.
+ *
+ * PUBLIC: enum nresult nget_uslong __P((SCR *, u_long *, const CHAR_T *, CHAR_T **, int));
+ */
+enum nresult
+nget_uslong(SCR *sp, u_long *valp, const CHAR_T *p, CHAR_T **endp, int base)
+{
+       errno = 0;
+       *valp = STRTOUL(p, (RCHAR_T **)endp, base);
+       if (errno == 0)
+               return (NUM_OK);
+       if (errno == ERANGE && *valp == ULONG_MAX)
+               return (NUM_OVER);
+       return (NUM_ERR);
+}
+
+/*
+ * nget_slong --
+ *      Convert a signed long, checking for overflow and underflow.
+ *
+ * PUBLIC: enum nresult nget_slong __P((SCR *, long *, const CHAR_T *, CHAR_T **, int));
+ */
+enum nresult
+nget_slong(SCR *sp, long int *valp, const CHAR_T *p, CHAR_T **endp, int base)
+{
+       errno = 0;
+       *valp = STRTOL(p, (RCHAR_T **)endp, base);
+       if (errno == 0)
+               return (NUM_OK);
+       if (errno == ERANGE) {
+               if (*valp == LONG_MAX)
+                       return (NUM_OVER);
+               if (*valp == LONG_MIN)
+                       return (NUM_UNDER);
+       }
+       return (NUM_ERR);
+}
diff --git a/dist/nvi/common/util.h b/dist/nvi/common/util.h
new file mode 100644 (file)
index 0000000..3777c00
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: util.h,v 1.2 2009/01/18 03:43:45 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: util.h,v 10.5 1996/03/16 14:42:47 bostic Exp (Berkeley) Date: 1996/03/16 14:42:47
+ */
+
+/* Macros to init/set/clear/test flags. */
+#define        FL_INIT(l, f)   (l) = (f)               /* Specific flags location. */
+#define        FL_SET(l, f)    ((l) |= (f))
+#define        FL_CLR(l, f)    ((l) &= ~(f))
+#define        FL_ISSET(l, f)  ((l) & (f))
+
+#define        LF_INIT(f)      FL_INIT(flags, f)       /* Local variable flags. */
+#define        LF_SET(f)       FL_SET(flags, f)
+#define        LF_CLR(f)       FL_CLR(flags, f)
+#define        LF_ISSET(f)     FL_ISSET(flags, f)
+
+#define        F_INIT(p, f)    FL_INIT((p)->flags, f)  /* Structure element flags. */
+#define        F_SET(p, f)     FL_SET((p)->flags, f)
+#define        F_CLR(p, f)     FL_CLR((p)->flags, f)
+#define        F_ISSET(p, f)   FL_ISSET((p)->flags, f)
+
+/* Offset to next column of stop size, e.g. tab offsets. */
+#define        COL_OFF(c, stop)        ((stop) - ((c) % (stop)))
+
+/* Busy message types. */
+typedef enum { B_NONE, B_OFF, B_READ, B_RECOVER, B_SEARCH, B_WRITE } bmsg_t;
+
+/*
+ * Number handling defines and protoypes.
+ *
+ * NNFITS:     test for addition of two negative numbers under a limit
+ * NPFITS:     test for addition of two positive numbers under a limit
+ * NADD_SLONG: test for addition of two signed longs
+ * NADD_USLONG:        test for addition of two unsigned longs
+ */
+enum nresult { NUM_ERR, NUM_OK, NUM_OVER, NUM_UNDER };
+#define        NNFITS(min, cur, add)                                           \
+       (((long)(min)) - (cur) <= (add))
+#define        NPFITS(max, cur, add)                                           \
+       (((unsigned long)(max)) - (cur) >= (add))
+#define        NADD_SLONG(sp, v1, v2)                                          \
+       ((v1) < 0 ?                                                     \
+           ((v2) < 0 &&                                                \
+           NNFITS(LONG_MIN, (v1), (v2))) ? NUM_UNDER : NUM_OK :        \
+        (v1) > 0 ?                                                     \
+           (v2) > 0 &&                                                 \
+           NPFITS(LONG_MAX, (unsigned long)(v1), (unsigned long)(v2)) ? \
+             NUM_OK : NUM_OVER :                                       \
+        NUM_OK)
+#define        NADD_USLONG(sp, v1, v2)                                         \
+       (NPFITS(ULONG_MAX, (v1), (v2)) ? NUM_OK : NUM_OVER)
diff --git a/dist/nvi/common/util2.c b/dist/nvi/common/util2.c
new file mode 100644 (file)
index 0000000..56391de
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $NetBSD: util2.c,v 1.1.1.2 2008/05/18 14:29:52 aymeric Exp $ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "multibyte.h"
+
+int
+ucs2utf8(const CHAR_T *src, size_t len, char *dst)
+{
+    int i, j;
+
+    for (i = 0, j = 0; i < len; ++i) {
+       if (src[i] < 0x80)
+           dst[j++] = src[i];
+       else if (src[i] < 0x800) {
+           dst[j++] = (src[i] >> 6) | 0xc0;
+           dst[j++] = (src[i] & 0x3f) | 0x80;
+       } else {
+           dst[j++] = (src[i] >> 12) | 0xe0;
+           dst[j++] = ((src[i] >> 6) & 0x3f) | 0x80;
+           dst[j++] = (src[i] & 0x3f) | 0x80;
+       }
+    }
+
+    return j;
+}
diff --git a/dist/nvi/common/vi.src b/dist/nvi/common/vi.src
new file mode 100644 (file)
index 0000000..713c164
--- /dev/null
@@ -0,0 +1,37 @@
+PREFIX vi
+
+INCLUDE #include <sys/types.h>
+INCLUDE #include <sys/queue.h>
+INCLUDE #include <sys/stat.h>
+INCLUDE #include <bitstring.h>
+INCLUDE #include <errno.h>
+INCLUDE #include <fcntl.h>
+INCLUDE #include <limits.h>
+INCLUDE #include <stdio.h>
+INCLUDE #include <stdlib.h>
+INCLUDE #include <string.h>
+INCLUDE #include "common.h"
+INCLUDE #include <db_int.h>
+INCLUDE #include "db_page.h"
+INCLUDE #include "db_am.h"
+INCLUDE #include "rep.h"
+INCLUDE #include "txn.h"
+
+BEGIN  marker          200
+ARG    opcode          u_int32_t       lu
+END
+
+BEGIN  cursor          201
+ARG    opcode          u_int32_t       lu
+ARG    lno             db_recno_t      lu
+ARG    cno             size_t          d
+END
+
+BEGIN  mark            202
+POINTER        lmp             LMARK *         %
+END
+
+BEGIN  change          203
+ARG    opcode          u_int32_t       lu
+ARG    lno             db_recno_t      lu
+END
diff --git a/dist/nvi/common/vi_auto.c b/dist/nvi/common/vi_auto.c
new file mode 100644 (file)
index 0000000..b0f33f1
--- /dev/null
@@ -0,0 +1,810 @@
+/*     $NetBSD: vi_auto.c,v 1.1.1.2 2008/05/18 14:29:53 aymeric Exp $ */
+
+/* Do not edit: automatically built by gen_rec.awk. */
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "common.h"
+#include <db_int.h>
+#include "db_page.h"
+#include "db_am.h"
+#include "rep.h"
+#include "txn.h"
+/*
+ * PUBLIC: #ifdef USE_DB4_LOGGING
+ */
+/*
+ * PUBLIC: int __vi_marker_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:      u_int32_t));
+ */
+int
+__vi_marker_log(dbenv, txnid, ret_lsnp, flags,
+       opcode)
+       DB_ENV *dbenv;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t opcode;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t uinttmp;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_vi_marker;
+       if (txnid != NULL &&
+           TAILQ_FIRST(&txnid->kids) != NULL &&
+           (ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
+               return (ret);
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               ZERO_LSN(null_lsn);
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(u_int32_t);
+       if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+               return (ret);
+
+       bp = logrec.data;
+
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       uinttmp = (u_int32_t)opcode;
+       memcpy(bp, &uinttmp, sizeof(uinttmp));
+       bp += sizeof(uinttmp);
+
+       DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) == logrec.size);
+       ret = dbenv->log_put(dbenv, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL && ret == 0)
+               txnid->last_lsn = *ret_lsnp;
+#ifdef LOG_DIAGNOSTIC
+       if (ret != 0)
+               (void)__vi_marker_print(dbenv,
+                   (DBT *)&logrec, ret_lsnp, NULL, NULL);
+#endif
+       __os_free(dbenv, logrec.data, logrec.size);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __vi_marker_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_marker_getpgnos(dbenv, rec, lsnp, notused1, summary)
+       DB_ENV *dbenv;
+       DBT *rec;
+       DB_LSN *lsnp;
+       db_recops notused1;
+       void *summary;
+{
+       TXN_RECS *t;
+       int ret;
+       COMPQUIET(rec, NULL);
+       COMPQUIET(notused1, DB_TXN_ABORT);
+
+       t = (TXN_RECS *)summary;
+
+       if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
+               return (ret);
+
+       t->array[t->npages].flags = LSN_PAGE_NOLOCK;
+       t->array[t->npages].lsn = *lsnp;
+       t->array[t->npages].fid = DB_LOGFILEID_INVALID;
+       memset(&t->array[t->npages].pgdesc, 0,
+           sizeof(t->array[t->npages].pgdesc));
+
+       t->npages++;
+
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_marker_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_marker_print(dbenv, dbtp, lsnp, notused2, notused3)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops notused2;
+       void *notused3;
+{
+       __vi_marker_args *argp;
+       int ret;
+
+       notused2 = DB_TXN_ABORT;
+       notused3 = NULL;
+
+       if ((ret = __vi_marker_read(dbenv, dbtp->data, &argp)) != 0)
+               return (ret);
+       (void)printf(
+           "[%lu][%lu]vi_marker: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       (void)printf("\topcode: %lu\n", (u_long)argp->opcode);
+       (void)printf("\n");
+       __os_free(dbenv, argp, 0);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_marker_read __P((DB_ENV *, void *, __vi_marker_args **));
+ */
+int
+__vi_marker_read(dbenv, recbuf, argpp)
+       DB_ENV *dbenv;
+       void *recbuf;
+       __vi_marker_args **argpp;
+{
+       __vi_marker_args *argp;
+       int ret;
+       u_int32_t uinttmp;
+       u_int8_t *bp;
+
+       ret = __os_malloc(dbenv, sizeof(__vi_marker_args) +
+           sizeof(DB_TXN), &argp);
+       if (ret != 0)
+               return (ret);
+       argp->txnid = (DB_TXN *)&argp[1];
+
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       memcpy(&uinttmp, bp, sizeof(uinttmp));
+       argp->opcode = (u_int32_t)uinttmp;
+       bp += sizeof(uinttmp);
+
+       *argpp = argp;
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_cursor_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:      u_int32_t, db_recno_t, size_t));
+ */
+int
+__vi_cursor_log(dbenv, txnid, ret_lsnp, flags,
+       opcode, lno, cno)
+       DB_ENV *dbenv;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t opcode;
+       db_recno_t lno;
+       size_t cno;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t uinttmp;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_vi_cursor;
+       if (txnid != NULL &&
+           TAILQ_FIRST(&txnid->kids) != NULL &&
+           (ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
+               return (ret);
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               ZERO_LSN(null_lsn);
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(u_int32_t)
+           + sizeof(u_int32_t)
+           + sizeof(u_int32_t);
+       if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+               return (ret);
+
+       bp = logrec.data;
+
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       uinttmp = (u_int32_t)opcode;
+       memcpy(bp, &uinttmp, sizeof(uinttmp));
+       bp += sizeof(uinttmp);
+
+       uinttmp = (u_int32_t)lno;
+       memcpy(bp, &uinttmp, sizeof(uinttmp));
+       bp += sizeof(uinttmp);
+
+       uinttmp = (u_int32_t)cno;
+       memcpy(bp, &uinttmp, sizeof(uinttmp));
+       bp += sizeof(uinttmp);
+
+       DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) == logrec.size);
+       ret = dbenv->log_put(dbenv, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL && ret == 0)
+               txnid->last_lsn = *ret_lsnp;
+#ifdef LOG_DIAGNOSTIC
+       if (ret != 0)
+               (void)__vi_cursor_print(dbenv,
+                   (DBT *)&logrec, ret_lsnp, NULL, NULL);
+#endif
+       __os_free(dbenv, logrec.data, logrec.size);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __vi_cursor_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_cursor_getpgnos(dbenv, rec, lsnp, notused1, summary)
+       DB_ENV *dbenv;
+       DBT *rec;
+       DB_LSN *lsnp;
+       db_recops notused1;
+       void *summary;
+{
+       TXN_RECS *t;
+       int ret;
+       COMPQUIET(rec, NULL);
+       COMPQUIET(notused1, DB_TXN_ABORT);
+
+       t = (TXN_RECS *)summary;
+
+       if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
+               return (ret);
+
+       t->array[t->npages].flags = LSN_PAGE_NOLOCK;
+       t->array[t->npages].lsn = *lsnp;
+       t->array[t->npages].fid = DB_LOGFILEID_INVALID;
+       memset(&t->array[t->npages].pgdesc, 0,
+           sizeof(t->array[t->npages].pgdesc));
+
+       t->npages++;
+
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_cursor_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_cursor_print(dbenv, dbtp, lsnp, notused2, notused3)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops notused2;
+       void *notused3;
+{
+       __vi_cursor_args *argp;
+       int ret;
+
+       notused2 = DB_TXN_ABORT;
+       notused3 = NULL;
+
+       if ((ret = __vi_cursor_read(dbenv, dbtp->data, &argp)) != 0)
+               return (ret);
+       (void)printf(
+           "[%lu][%lu]vi_cursor: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       (void)printf("\topcode: %lu\n", (u_long)argp->opcode);
+       (void)printf("\tlno: %lu\n", (u_long)argp->lno);
+       (void)printf("\tcno: %d\n", argp->cno);
+       (void)printf("\n");
+       __os_free(dbenv, argp, 0);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_cursor_read __P((DB_ENV *, void *, __vi_cursor_args **));
+ */
+int
+__vi_cursor_read(dbenv, recbuf, argpp)
+       DB_ENV *dbenv;
+       void *recbuf;
+       __vi_cursor_args **argpp;
+{
+       __vi_cursor_args *argp;
+       int ret;
+       u_int32_t uinttmp;
+       u_int8_t *bp;
+
+       ret = __os_malloc(dbenv, sizeof(__vi_cursor_args) +
+           sizeof(DB_TXN), &argp);
+       if (ret != 0)
+               return (ret);
+       argp->txnid = (DB_TXN *)&argp[1];
+
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       memcpy(&uinttmp, bp, sizeof(uinttmp));
+       argp->opcode = (u_int32_t)uinttmp;
+       bp += sizeof(uinttmp);
+
+       memcpy(&uinttmp, bp, sizeof(uinttmp));
+       argp->lno = (db_recno_t)uinttmp;
+       bp += sizeof(uinttmp);
+
+       memcpy(&uinttmp, bp, sizeof(uinttmp));
+       argp->cno = (size_t)uinttmp;
+       bp += sizeof(uinttmp);
+
+       *argpp = argp;
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_mark_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:      LMARK *));
+ */
+int
+__vi_mark_log(dbenv, txnid, ret_lsnp, flags,
+       lmp)
+       DB_ENV *dbenv;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       LMARK * lmp;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_vi_mark;
+       if (txnid != NULL &&
+           TAILQ_FIRST(&txnid->kids) != NULL &&
+           (ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
+               return (ret);
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               ZERO_LSN(null_lsn);
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(*lmp);
+       if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+               return (ret);
+
+       bp = logrec.data;
+
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       if (lmp != NULL)
+               memcpy(bp, lmp, sizeof(*lmp));
+       else
+               memset(bp, 0, sizeof(*lmp));
+       bp += sizeof(*lmp);
+
+       DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) == logrec.size);
+       ret = dbenv->log_put(dbenv, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL && ret == 0)
+               txnid->last_lsn = *ret_lsnp;
+#ifdef LOG_DIAGNOSTIC
+       if (ret != 0)
+               (void)__vi_mark_print(dbenv,
+                   (DBT *)&logrec, ret_lsnp, NULL, NULL);
+#endif
+       __os_free(dbenv, logrec.data, logrec.size);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __vi_mark_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_mark_getpgnos(dbenv, rec, lsnp, notused1, summary)
+       DB_ENV *dbenv;
+       DBT *rec;
+       DB_LSN *lsnp;
+       db_recops notused1;
+       void *summary;
+{
+       TXN_RECS *t;
+       int ret;
+       COMPQUIET(rec, NULL);
+       COMPQUIET(notused1, DB_TXN_ABORT);
+
+       t = (TXN_RECS *)summary;
+
+       if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
+               return (ret);
+
+       t->array[t->npages].flags = LSN_PAGE_NOLOCK;
+       t->array[t->npages].lsn = *lsnp;
+       t->array[t->npages].fid = DB_LOGFILEID_INVALID;
+       memset(&t->array[t->npages].pgdesc, 0,
+           sizeof(t->array[t->npages].pgdesc));
+
+       t->npages++;
+
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_mark_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_mark_print(dbenv, dbtp, lsnp, notused2, notused3)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops notused2;
+       void *notused3;
+{
+       __vi_mark_args *argp;
+       int ret;
+
+       notused2 = DB_TXN_ABORT;
+       notused3 = NULL;
+
+       if ((ret = __vi_mark_read(dbenv, dbtp->data, &argp)) != 0)
+               return (ret);
+       (void)printf(
+           "[%lu][%lu]vi_mark: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       (void)printf("\tlmp: %%\n", argp->lmp);
+       (void)printf("\n");
+       __os_free(dbenv, argp, 0);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_mark_read __P((DB_ENV *, void *, __vi_mark_args **));
+ */
+int
+__vi_mark_read(dbenv, recbuf, argpp)
+       DB_ENV *dbenv;
+       void *recbuf;
+       __vi_mark_args **argpp;
+{
+       __vi_mark_args *argp;
+       int ret;
+       u_int8_t *bp;
+
+       ret = __os_malloc(dbenv, sizeof(__vi_mark_args) +
+           sizeof(DB_TXN), &argp);
+       if (ret != 0)
+               return (ret);
+       argp->txnid = (DB_TXN *)&argp[1];
+
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       memcpy(&argp->lmp, bp,  sizeof(argp->lmp));
+       bp += sizeof(argp->lmp);
+
+       *argpp = argp;
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_change_log __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t,
+ * PUBLIC:      u_int32_t, db_recno_t));
+ */
+int
+__vi_change_log(dbenv, txnid, ret_lsnp, flags,
+       opcode, lno)
+       DB_ENV *dbenv;
+       DB_TXN *txnid;
+       DB_LSN *ret_lsnp;
+       u_int32_t flags;
+       u_int32_t opcode;
+       db_recno_t lno;
+{
+       DBT logrec;
+       DB_LSN *lsnp, null_lsn;
+       u_int32_t uinttmp;
+       u_int32_t rectype, txn_num;
+       int ret;
+       u_int8_t *bp;
+
+       rectype = DB_vi_change;
+       if (txnid != NULL &&
+           TAILQ_FIRST(&txnid->kids) != NULL &&
+           (ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
+               return (ret);
+       txn_num = txnid == NULL ? 0 : txnid->txnid;
+       if (txnid == NULL) {
+               ZERO_LSN(null_lsn);
+               lsnp = &null_lsn;
+       } else
+               lsnp = &txnid->last_lsn;
+       logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
+           + sizeof(u_int32_t)
+           + sizeof(u_int32_t);
+       if ((ret = __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+               return (ret);
+
+       bp = logrec.data;
+
+       memcpy(bp, &rectype, sizeof(rectype));
+       bp += sizeof(rectype);
+
+       memcpy(bp, &txn_num, sizeof(txn_num));
+       bp += sizeof(txn_num);
+
+       memcpy(bp, lsnp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       uinttmp = (u_int32_t)opcode;
+       memcpy(bp, &uinttmp, sizeof(uinttmp));
+       bp += sizeof(uinttmp);
+
+       uinttmp = (u_int32_t)lno;
+       memcpy(bp, &uinttmp, sizeof(uinttmp));
+       bp += sizeof(uinttmp);
+
+       DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) == logrec.size);
+       ret = dbenv->log_put(dbenv, ret_lsnp, (DBT *)&logrec, flags);
+       if (txnid != NULL && ret == 0)
+               txnid->last_lsn = *ret_lsnp;
+#ifdef LOG_DIAGNOSTIC
+       if (ret != 0)
+               (void)__vi_change_print(dbenv,
+                   (DBT *)&logrec, ret_lsnp, NULL, NULL);
+#endif
+       __os_free(dbenv, logrec.data, logrec.size);
+       return (ret);
+}
+
+/*
+ * PUBLIC: int __vi_change_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_change_getpgnos(dbenv, rec, lsnp, notused1, summary)
+       DB_ENV *dbenv;
+       DBT *rec;
+       DB_LSN *lsnp;
+       db_recops notused1;
+       void *summary;
+{
+       TXN_RECS *t;
+       int ret;
+       COMPQUIET(rec, NULL);
+       COMPQUIET(notused1, DB_TXN_ABORT);
+
+       t = (TXN_RECS *)summary;
+
+       if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
+               return (ret);
+
+       t->array[t->npages].flags = LSN_PAGE_NOLOCK;
+       t->array[t->npages].lsn = *lsnp;
+       t->array[t->npages].fid = DB_LOGFILEID_INVALID;
+       memset(&t->array[t->npages].pgdesc, 0,
+           sizeof(t->array[t->npages].pgdesc));
+
+       t->npages++;
+
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_change_print __P((DB_ENV *, DBT *, DB_LSN *, db_recops,
+ * PUBLIC:      void *));
+ */
+int
+__vi_change_print(dbenv, dbtp, lsnp, notused2, notused3)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops notused2;
+       void *notused3;
+{
+       __vi_change_args *argp;
+       int ret;
+
+       notused2 = DB_TXN_ABORT;
+       notused3 = NULL;
+
+       if ((ret = __vi_change_read(dbenv, dbtp->data, &argp)) != 0)
+               return (ret);
+       (void)printf(
+           "[%lu][%lu]vi_change: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+           (u_long)lsnp->file,
+           (u_long)lsnp->offset,
+           (u_long)argp->type,
+           (u_long)argp->txnid->txnid,
+           (u_long)argp->prev_lsn.file,
+           (u_long)argp->prev_lsn.offset);
+       (void)printf("\topcode: %lu\n", (u_long)argp->opcode);
+       (void)printf("\tlno: %lu\n", (u_long)argp->lno);
+       (void)printf("\n");
+       __os_free(dbenv, argp, 0);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_change_read __P((DB_ENV *, void *, __vi_change_args **));
+ */
+int
+__vi_change_read(dbenv, recbuf, argpp)
+       DB_ENV *dbenv;
+       void *recbuf;
+       __vi_change_args **argpp;
+{
+       __vi_change_args *argp;
+       int ret;
+       u_int32_t uinttmp;
+       u_int8_t *bp;
+
+       ret = __os_malloc(dbenv, sizeof(__vi_change_args) +
+           sizeof(DB_TXN), &argp);
+       if (ret != 0)
+               return (ret);
+       argp->txnid = (DB_TXN *)&argp[1];
+
+       bp = recbuf;
+       memcpy(&argp->type, bp, sizeof(argp->type));
+       bp += sizeof(argp->type);
+
+       memcpy(&argp->txnid->txnid,  bp, sizeof(argp->txnid->txnid));
+       bp += sizeof(argp->txnid->txnid);
+
+       memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN));
+       bp += sizeof(DB_LSN);
+
+       memcpy(&uinttmp, bp, sizeof(uinttmp));
+       argp->opcode = (u_int32_t)uinttmp;
+       bp += sizeof(uinttmp);
+
+       memcpy(&uinttmp, bp, sizeof(uinttmp));
+       argp->lno = (db_recno_t)uinttmp;
+       bp += sizeof(uinttmp);
+
+       *argpp = argp;
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_init_print __P((DB_ENV *, int (***)(DB_ENV *, DBT *,
+ * PUBLIC:      DB_LSN *, db_recops, void *), size_t *));
+ */
+int
+__vi_init_print(dbenv, dtabp, dtabsizep)
+       DB_ENV *dbenv;
+       int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+       size_t *dtabsizep;
+{
+       int ret;
+
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_marker_print, DB_vi_marker)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_cursor_print, DB_vi_cursor)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_mark_print, DB_vi_mark)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_change_print, DB_vi_change)) != 0)
+               return (ret);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_init_getpgnos __P((DB_ENV *, int (***)(DB_ENV *, DBT *,
+ * PUBLIC:      DB_LSN *, db_recops, void *), size_t *));
+ */
+int
+__vi_init_getpgnos(dbenv, dtabp, dtabsizep)
+       DB_ENV *dbenv;
+       int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+       size_t *dtabsizep;
+{
+       int ret;
+
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_marker_getpgnos, DB_vi_marker)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_cursor_getpgnos, DB_vi_cursor)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_mark_getpgnos, DB_vi_mark)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+           __vi_change_getpgnos, DB_vi_change)) != 0)
+               return (ret);
+       return (0);
+}
+
+/*
+ * PUBLIC: int __vi_init_recover __P((DB_ENV *));
+ */
+int
+__vi_init_recover(dbenv)
+       DB_ENV *dbenv;
+{
+       int ret;
+
+       if ((ret = __db_add_recovery(dbenv, &dbenv->dtab, &dbenv->dtab_size,
+           __vi_marker_recover, DB_vi_marker)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, &dbenv->dtab, &dbenv->dtab_size,
+           __vi_cursor_recover, DB_vi_cursor)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, &dbenv->dtab, &dbenv->dtab_size,
+           __vi_mark_recover, DB_vi_mark)) != 0)
+               return (ret);
+       if ((ret = __db_add_recovery(dbenv, &dbenv->dtab, &dbenv->dtab_size,
+           __vi_change_recover, DB_vi_change)) != 0)
+               return (ret);
+       return (0);
+}
+/*
+ * PUBLIC: #endif
+ */
diff --git a/dist/nvi/common/vi_auto.h b/dist/nvi/common/vi_auto.h
new file mode 100644 (file)
index 0000000..e19509e
--- /dev/null
@@ -0,0 +1,42 @@
+/*     $NetBSD: vi_auto.h,v 1.1.1.2 2008/05/18 14:29:53 aymeric Exp $ */
+
+/* Do not edit: automatically built by gen_rec.awk. */
+
+#ifndef        vi_AUTO_H
+#define        vi_AUTO_H
+#define        DB_vi_marker    200
+typedef struct _vi_marker_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       u_int32_t       opcode;
+} __vi_marker_args;
+
+#define        DB_vi_cursor    201
+typedef struct _vi_cursor_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       u_int32_t       opcode;
+       db_recno_t      lno;
+       size_t  cno;
+} __vi_cursor_args;
+
+#define        DB_vi_mark      202
+typedef struct _vi_mark_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       LMARK   lmp;
+} __vi_mark_args;
+
+#define        DB_vi_change    203
+typedef struct _vi_change_args {
+       u_int32_t type;
+       DB_TXN *txnid;
+       DB_LSN prev_lsn;
+       u_int32_t       opcode;
+       db_recno_t      lno;
+} __vi_change_args;
+
+#endif
diff --git a/dist/nvi/common/vi_rec.c b/dist/nvi/common/vi_rec.c
new file mode 100644 (file)
index 0000000..f11bd52
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $NetBSD: vi_rec.c,v 1.1.1.2 2008/05/18 14:29:53 aymeric Exp $ */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <string.h>
+#endif
+
+#include "common.h"
+
+#include "db_int.h"
+#include "db_page.h"
+#include <log.h>
+#include "hash.h"
+#include "btree.h"
+
+#define LOG_CURSOR_HIT     -1000
+
+/*
+ * PUBLIC: #ifdef USE_DB4_LOGGING
+ */
+/*
+ * __vi_marker_recover --
+ *     Recovery function for marker.
+ *
+ * PUBLIC: int __vi_marker_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__vi_marker_recover(dbenv, dbtp, lsnp, op, info)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops op;
+       void *info;
+{
+       __vi_marker_args *argp;
+       int ret;
+
+       REC_PRINT(__vi_marker_print);
+       REC_NOOP_INTRO(__vi_marker_read);
+
+       *lsnp = argp->prev_lsn;
+       ret = 0;
+
+       REC_NOOP_CLOSE;
+}
+
+/*
+ * __vi_cursor_recover --
+ *     Recovery function for cursor.
+ *
+ * PUBLIC: int __vi_cursor_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__vi_cursor_recover(dbenv, dbtp, lsnp, op, info)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops op;
+       void *info;
+{
+       __vi_cursor_args *argp;
+       int ret;
+       SCR *sp;
+
+       REC_PRINT(__vi_cursor_print);
+       REC_NOOP_INTRO(__vi_cursor_read);
+
+       sp = (SCR *)dbenv->app_private;
+
+       *lsnp = argp->prev_lsn;
+       if (sp->state.undo == UNDO_SETLINE) {
+               /* Why the check for ep->l_cur ? (copied from log.c)
+                */
+               ret = (argp->lno != sp->lno || 
+                   (argp->opcode == LOG_CURSOR_INIT && sp->ep->l_cur == 1))
+                         ? LOG_CURSOR_HIT : 0;
+       }
+       else {
+               ret = argp->opcode == 
+                       (DB_UNDO(op) ? LOG_CURSOR_INIT : LOG_CURSOR_END)
+                         ? LOG_CURSOR_HIT : 0;
+               if (ret) {
+                       sp->state.pos.lno = argp->lno;
+                       sp->state.pos.cno = argp->cno;
+               }
+       }
+
+       REC_NOOP_CLOSE;
+}
+
+/*
+ * __vi_mark_recover --
+ *     Recovery function for mark.
+ *
+ * PUBLIC: int __vi_mark_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__vi_mark_recover(dbenv, dbtp, lsnp, op, info)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops op;
+       void *info;
+{
+       __vi_mark_args *argp;
+       int ret;
+       MARK m;
+       SCR *sp;
+
+       REC_PRINT(__vi_mark_print);
+       REC_NOOP_INTRO(__vi_mark_read);
+
+       sp = (SCR *)dbenv->app_private;
+       *lsnp = argp->prev_lsn;
+       m.lno = argp->lmp.lno;
+       m.cno = argp->lmp.cno;
+       ret = mark_set(sp, argp->lmp.name, &m, 0);
+
+       REC_NOOP_CLOSE;
+}
+
+/*
+ * __vi_change_recover --
+ *     Recovery function for change.
+ *
+ * PUBLIC: int __vi_change_recover
+ * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__vi_change_recover(dbenv, dbtp, lsnp, op, info)
+       DB_ENV *dbenv;
+       DBT *dbtp;
+       DB_LSN *lsnp;
+       db_recops op;
+       void *info;
+{
+       __vi_change_args *argp;
+       int ret;
+       SCR *sp;
+
+       REC_PRINT(__vi_change_print);
+       REC_NOOP_INTRO(__vi_change_read);
+
+       ret = 0;
+
+       sp = (SCR *)dbenv->app_private;
+       if (DB_UNDO(op) != (argp->opcode & 1))
+           switch (argp->opcode) {
+           case LOG_LINE_RESET_B:
+           case LOG_LINE_RESET_F:
+                   ret = line_insdel(sp, LINE_RESET, argp->lno);
+                   update_cache(sp, LINE_RESET, argp->lno);
+                   ret = scr_update(sp, argp->lno, LINE_RESET, 1) || ret;
+                   break;
+           case LOG_LINE_APPEND_B:
+           case LOG_LINE_DELETE_F:
+                   ret = line_insdel(sp, LINE_DELETE, argp->lno);
+                   update_cache(sp, LINE_DELETE, argp->lno);
+                   ret = scr_update(sp, argp->lno, LINE_DELETE, 1) || ret;
+                   break;
+           case LOG_LINE_DELETE_B:
+           case LOG_LINE_APPEND_F:
+                   ret = line_insdel(sp, LINE_INSERT, argp->lno);
+                   update_cache(sp, LINE_INSERT, argp->lno);
+                   ret = scr_update(sp, argp->lno, LINE_INSERT, 1) || ret;
+                   break;
+           }
+
+       *lsnp = argp->prev_lsn;
+
+       REC_NOOP_CLOSE;
+}
+
+/*
+ *
+ * PUBLIC: int __vi_log_truncate __P((EXF *ep));
+ */
+int
+__vi_log_truncate(EXF *ep)
+{
+       DB_LSN ckplsn;
+
+       ZERO_LSN(ckplsn);
+       return __log_vtruncate(ep->env, &ep->lsn_cur, &ckplsn);
+       /*return __log_vtruncate(ep->env, &ep->lsn_cur, &ep->lsn_first);*/
+}
+
+/*
+ *
+ * PUBLIC: int __vi_log_dispatch __P((DB_ENV *dbenv, DBT *data, DB_LSN *lsn, db_recops ops));
+ */
+int
+__vi_log_dispatch(DB_ENV *dbenv, DBT *data, DB_LSN *lsn, db_recops ops)
+{
+       u_int32_t rectype;
+       char    s[100];
+
+       memcpy(&rectype, data->data, sizeof(rectype));
+       snprintf(s,100,"%d\n", rectype);
+       return dbenv->dtab[rectype](dbenv, data, lsn, ops, NULL);
+}
+
+static int 
+vi_log_get(SCR *sp, DB_LOGC *logc, DBT *data, u_int32_t which)
+{
+       size_t nlen;
+       EXF *ep;
+
+       ep = sp->ep;
+
+       nlen = 1024;
+retry:
+       BINC_GOTO(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
+       memset(data, 0, sizeof(*data));
+       data->data = sp->wp->l_lp;
+       data->ulen = sp->wp->l_len;
+       data->flags = DB_DBT_USERMEM;
+       switch ((sp->db_error = logc->get(logc, &ep->lsn_cur, data, which))) {
+       case ENOMEM:
+               nlen = data->size;
+               goto retry;
+       default:
+alloc_err:
+               msgq(sp, M_DBERR, "logc->get");
+               F_SET(ep, F_NOLOG);
+               return (1);
+       case 0:
+               ;
+       }
+       return 0;
+}
+
+/*
+ *
+ * PUBLIC: int __vi_log_traverse __P((SCR *sp, undo_t undo, MARK *));
+ */
+int
+__vi_log_traverse(SCR *sp, undo_t undo, MARK *rp)
+{
+       DB_LOGC *logc;
+       DBT data;
+       EXF *ep;
+       int         ret;
+       DB_LSN      lsn;
+       u_int32_t   which;
+       db_recops   ops;
+
+       ep = sp->ep;
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       sp->state.undo = undo;
+       ep->env->app_private = sp;
+       if ((sp->db_error = ep->env->log_cursor(ep->env, &logc, 0)) 
+                   != 0) {
+               msgq(sp, M_DBERR, "env->log_cursor");
+               return (1);
+       }
+       if (vi_log_get(sp, logc, &data, DB_SET))
+               return 1;
+       if (undo == UNDO_FORWARD) {
+               ops = DB_TXN_FORWARD_ROLL;
+               which = DB_NEXT;
+               if (vi_log_get(sp, logc, &data, DB_NEXT))
+                       return 1;
+       } else {
+               ops = DB_TXN_BACKWARD_ROLL;
+               which = DB_PREV;
+       }
+
+       for (;;) {
+               MEMCPY(&lsn, &ep->lsn_cur, 1);
+               ret = __vi_log_dispatch(ep->env, &data, &lsn, ops);
+               if (ret != 0) {
+                       if (ret == LOG_CURSOR_HIT)
+                               break;
+               }
+
+               if (vi_log_get(sp, logc, &data, which))
+                       return 1;
+               if (undo == UNDO_SETLINE && 
+                   log_compare(&ep->lsn_cur, &ep->lsn_first) <= 0) {
+                       /* Move to previous record without dispatching. */
+                       undo = UNDO_BACKWARD;
+                       break;
+               }
+       }
+       if (undo == UNDO_BACKWARD)
+               if (vi_log_get(sp, logc, &data, DB_PREV))
+                       return 1;
+
+       logc->close(logc, 0);
+
+       ep->env->app_private = NULL;
+
+       MEMMOVE(rp, &sp->state.pos, 1);
+
+       F_CLR(ep, F_NOLOG);
+
+       return 0;
+}
+
+int
+vi_db_init_recover(DB_ENV *dbenv)
+{
+       int     ret;
+
+       if ((ret = __db_init_recover(dbenv)) != 0)
+               return (ret);
+       if ((ret = __bam_init_recover(dbenv)) != 0)
+               return (ret);
+
+       return 0;
+}
+/*
+ * PUBLIC: #endif
+ */
diff --git a/dist/nvi/dist/ExtUtils/Embed.pm b/dist/nvi/dist/ExtUtils/Embed.pm
new file mode 100644 (file)
index 0000000..4cb9785
--- /dev/null
@@ -0,0 +1,473 @@
+# Id: Embed.pm,v 10.2 1996/09/19 09:12:51 bostic Exp
+require 5.002;
+
+package ExtUtils::Embed;
+require Exporter;
+require FileHandle;
+use Config;
+use Getopt::Std;
+
+#Only when we need them
+#require ExtUtils::MakeMaker;
+#require ExtUtils::Liblist;
+
+use vars qw(@ISA @EXPORT $VERSION
+           @Extensions $Verbose $lib_ext
+           $opt_o $opt_s 
+           );
+use strict;
+
+$VERSION = sprintf("%d.%02d", qRevision: 10.2 =~ /(\d+)\.(\d+)/);
+#for the namespace change
+$Devel::embed::VERSION = "99.99";
+
+sub Version { $VERSION; }
+
+@ISA = qw(Exporter);
+@EXPORT = qw(&xsinit &ldopts 
+            &ccopts &ccflags &ccdlflags &perl_inc
+            &xsi_header &xsi_protos &xsi_body);
+
+#let's have Miniperl borrow from us instead
+#require ExtUtils::Miniperl;
+#*canon = \&ExtUtils::Miniperl::canon;
+
+$Verbose = 0;
+$lib_ext = $Config{lib_ext} || '.a';
+
+sub xsinit { 
+    my($file, $std, $mods) = @_;
+    my($fh,@mods,%seen);
+    $file ||= "perlxsi.c";
+
+    if (@_) {
+       @mods = @$mods if $mods;
+    }
+    else {
+       getopts('o:s:');
+       $file = $opt_o if defined $opt_o;
+       $std  = $opt_s  if defined $opt_s;
+       @mods = @ARGV;
+    }
+    $std = 1 unless scalar @mods;
+
+    if ($file eq "STDOUT") {
+       $fh = \*STDOUT;
+    }
+    else {
+       $fh = new FileHandle "> $file";
+    }
+
+    push(@mods, static_ext()) if defined $std;
+    @mods = grep(!$seen{$_}++, @mods);
+
+    print $fh &xsi_header();
+    print $fh "EXTERN_C void xs_init _((void));\n\n";     
+    print $fh &xsi_protos(@mods);
+
+    print $fh "\nEXTERN_C void\nxs_init()\n{\n";
+    print $fh &xsi_body(@mods);
+    print $fh "}\n";
+
+}
+
+sub xsi_header {
+    return <<EOF;
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#ifdef __cplusplus
+}
+#  ifndef EXTERN_C
+#    define EXTERN_C extern "C"
+#  endif
+#else
+#  ifndef EXTERN_C
+#    define EXTERN_C extern
+#  endif
+#endif
+
+EOF
+}    
+
+sub xsi_protos {
+    my(@exts) = @_;
+    my(@retval,%seen);
+
+    foreach $_ (@exts){
+        my($pname) = canon('/', $_);
+        my($mname, $cname);
+        ($mname = $pname) =~ s!/!::!g;
+        ($cname = $pname) =~ s!/!__!g;
+       my($ccode) = "EXTERN_C void boot_${cname} _((CV* cv));\n";
+       next if $seen{$ccode}++;
+        push(@retval, $ccode);
+    }
+    return join '', @retval;
+}
+
+sub xsi_body {
+    my(@exts) = @_;
+    my($pname,@retval,%seen);
+    my($dl) = canon('/','DynaLoader');
+    push(@retval, "\tdXSUB_SYS;\n") if $] > 5.002;
+    push(@retval, "\tchar *file = __FILE__;\n\n");
+
+    foreach $_ (@exts){
+        my($pname) = canon('/', $_);
+        my($mname, $cname, $ccode);
+        ($mname = $pname) =~ s!/!::!g;
+        ($cname = $pname) =~ s!/!__!g;
+        if ($pname eq $dl){
+            # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
+            # boot_DynaLoader is called directly in DynaLoader.pm
+            $ccode = "\t/* DynaLoader is a special case */\n\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
+            push(@retval, $ccode) unless $seen{$ccode}++;
+        } else {
+            $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
+            push(@retval, $ccode) unless $seen{$ccode}++;
+        }
+    }
+    return join '', @retval;
+}
+
+sub static_ext {
+    unless (scalar @Extensions) {
+       @Extensions = sort split /\s+/, $Config{static_ext};
+       unshift @Extensions, qw(DynaLoader);
+    }
+    @Extensions;
+}
+
+sub ldopts {
+    require ExtUtils::MakeMaker;
+    require ExtUtils::Liblist;
+    my($std,$mods,$link_args,$path) = @_;
+    my(@mods,@link_args,@argv);
+    my($dllib,$config_libs,@potential_libs,@path);
+    local($") = ' ' unless $" eq ' ';
+    my $MM = bless {} => 'MY';
+    if (scalar @_) {
+       @link_args = @$link_args if $link_args;
+       @mods = @$mods if $mods;
+    }
+    else {
+       @argv = @ARGV;
+       #hmm
+       while($_ = shift @argv) {
+          /^-std$/  && do { $std = 1; next; };
+          /^--$/    && do { @link_args = @argv; last; };
+          /^-I(.*)/ && do { $path = $1 || shift @argv; next; };
+          push(@mods, $_); 
+       }
+    }
+    $std = 1 unless scalar @link_args;
+    @path = $path ? split(/:/, $path) : @INC;
+
+    push(@potential_libs, @link_args)    if scalar @link_args;
+    push(@potential_libs, $Config{libs}) if defined $std;
+
+    push(@mods, static_ext()) if $std;
+
+    my($mod,@ns,$root,$sub,$extra,$archive,@archives);
+    print STDERR "Searching (@path) for archives\n" if $Verbose;
+    foreach $mod (@mods) {
+       @ns = split('::', $mod);
+       $sub = $ns[-1];
+       $root = $MM->catdir(@ns);
+       
+       print STDERR "searching for '$sub${lib_ext}'\n" if $Verbose;
+       foreach (@path) {
+           next unless -e ($archive = $MM->catdir($_,"auto",$root,"$sub$lib_ext"));
+           push @archives, $archive;
+           if(-e ($extra = $MM->catdir($_,"auto",$root,"extralibs.ld"))) {
+               local(*FH); 
+               if(open(FH, $extra)) {
+                   my($libs) = <FH>; chomp $libs;
+                   push @potential_libs, split /\s+/, $libs;
+               }
+               else {  
+                   warn "Couldn't open '$extra'"; 
+               }
+           }
+           last;
+       }
+    }
+    #print STDERR "\@potential_libs = @potential_libs\n";
+
+    my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
+       $MM->ext(join ' ', 
+                $MM->catdir("-L$Config{archlib}", "CORE"), " -lperl", 
+                @potential_libs);
+
+    my $ld_or_bs = $bsloadlibs || $ldloadlibs;
+    print STDERR "bs: $bsloadlibs ** ld: $ldloadlibs" if $Verbose;
+    my $linkage = "$Config{ldflags} @archives $ld_or_bs";
+    print STDERR "ldopts: '$linkage'\n" if $Verbose;
+
+    return $linkage if scalar @_;
+    print "$linkage\n";
+}
+
+sub ccflags {
+   print " $Config{ccflags} ";
+}
+
+sub ccdlflags {
+   print " $Config{ccdlflags} ";
+}
+
+sub perl_inc {
+   print " -I$Config{archlib}/CORE ";
+}
+
+sub ccopts {
+   ccflags;
+   ccdlflags;
+   perl_inc;
+}
+
+sub canon {
+    my($as, @ext) = @_;
+    foreach(@ext) {
+       # might be X::Y or lib/auto/X/Y/Y.a
+       next if s!::!/!g;
+       s:^(lib|ext)/(auto/)?::;
+       s:/\w+\.\w+$::;
+    }
+    grep(s:/:$as:, @ext) if ($as ne '/');
+    @ext;
+}
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications
+
+=head1 SYNOPSIS
+
+
+ perl -MExtUtils::Embed -e xsinit 
+ perl -MExtUtils::Embed -e ldopts 
+
+=head1 DESCRIPTION
+
+ExtUtils::Embed provides utility functions for embedding a Perl interpreter
+and extensions in your C/C++ applications.  
+Typically, an application B<Makefile> will invoke ExtUtils::Embed
+functions while building your application.  
+
+=head1 @EXPORT
+
+ExtUtils::Embed exports the following functions:
+L<xsinit()>, L<ldopts()>, L<ccopts()>, L<perl_inc()>, L<ccflags()>, 
+L<ccdlflags()>, L<xsi_header()>, L<xsi_protos()>, L<xsi_body()>
+
+=head1 FUNCTIONS
+
+=item xsinit()
+
+Generate C/C++ code for the XS intializer function.
+
+When invoked as C<`perl -MExtUtils::Embed -e xsinit --`>
+the following options are recognized:
+
+B<-o> <output filename> (Defaults to B<perlxsi.c>)
+
+B<-o STDOUT> will print to STDOUT.
+
+B<-std> (Write code for extensions that are linked with the current Perl.)
+
+Any additional arguments are expected to be names of modules
+to generate code for.
+
+When invoked with parameters the following are accepted and optional:
+
+C<xsinit($filename,$std,[@modules])>
+
+Where,
+
+B<$filename> is equivalent to the B<-o> option.
+
+B<$std> is boolean, equivalent to the B<-std> option.  
+
+B<[@modules]> is an array ref, same as additional arguments mentioned above.
+
+=item Examples
+
+ perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket
+
+
+This will generate code with an B<xs_init> function that glues the perl B<Socket::bootstrap> function 
+to the C B<boot_Socket> function and writes it to a file named "xsinit.c".
+
+Note that B<DynaLoader> is a special case where it must call B<boot_DynaLoader> directly.
+
+ perl -MExtUtils::Embed -e xsinit
+
+
+This will generate code for linking with B<DynaLoader> and 
+each static extension found in B<$Config{static_ext}>.
+The code is written to the default file name B<perlxsi.c>.
+
+
+ perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std DBI DBD::Oracle
+
+
+Here, code is written for all the currently linked extensions along with code
+for B<DBI> and B<DBD::Oracle>.
+
+If you have a working B<DynaLoader> then there is rarely any need to statically link in any 
+other extensions.
+
+=item ldopts()
+
+Output arguments for linking the Perl library and extensions to your
+application.
+
+When invoked as C<`perl -MExtUtils::Embed -e ldopts --`>
+the following options are recognized:
+
+B<-std> 
+
+Output arguments for linking the Perl library and any extensions linked
+with the current Perl.
+
+B<-I> <path1:path2>
+
+Search path for ModuleName.a archives.  
+Default path is B<@INC>.
+Library archives are expected to be found as 
+B</some/path/auto/ModuleName/ModuleName.a>
+For example, when looking for B<Socket.a> relative to a search path, 
+we should find B<auto/Socket/Socket.a>  
+
+When looking for B<DBD::Oracle> relative to a search path,
+we should find B<auto/DBD/Oracle/Oracle.a>
+
+Keep in mind, you can always supply B</my/own/path/ModuleName.a>
+as an additional linker argument.
+
+B<-->  <list of linker args>
+
+Additional linker arguments to be considered.
+
+Any additional arguments found before the B<--> token 
+are expected to be names of modules to generate code for.
+
+When invoked with parameters the following are accepted and optional:
+
+C<ldopts($std,[@modules],[@link_args],$path)>
+
+Where,
+
+B<$std> is boolean, equivalent to the B<-std> option.  
+
+B<[@modules]> is equivalent to additional arguments found before the B<--> token.
+
+B<[@link_args]> is equivalent to arguments found after the B<--> token.
+
+B<$path> is equivalent to the B<-I> option.
+
+In addition, when ldopts is called with parameters, it will return the argument string
+rather than print it to STDOUT.
+
+=item Examples
+
+
+ perl -MExtUtils::Embed -e ldopts
+
+
+This will print arguments for linking with B<libperl.a>, B<DynaLoader> and 
+extensions found in B<$Config{static_ext}>.  This includes libraries
+found in B<$Config{libs}> and the first ModuleName.a library
+for each extension that is found by searching B<@INC> or the path 
+specifed by the B<-I> option.  
+In addition, when ModuleName.a is found, additional linker arguments
+are picked up from the B<extralibs.ld> file in the same directory.
+
+
+ perl -MExtUtils::Embed -e ldopts -- -std Socket
+
+This will do the same as the above example, along with printing additional arguments for linking with the B<Socket> extension.
+
+
+ perl -MExtUtils::Embed -e ldopts -- DynaLoader
+
+
+This will print arguments for linking with just the B<DynaLoader> extension
+and B<libperl.a>.
+
+
+ perl -MExtUtils::Embed -e ldopts -- -std Msql -- -L/usr/msql/lib -lmsql
+
+
+Any arguments after the second '--' token are additional linker
+arguments that will be examined for potential conflict.  If there is no
+conflict, the additional arguments will be part of the output.  
+
+
+=item perl_inc()
+
+For including perl header files this function simply prints:
+
+ -I $Config{archlib}/CORE  
+
+So, rather than having to say:
+
+ perl -MConfig -e 'print "-I $Config{archlib}/CORE"'
+
+Just say:
+
+ perl -MExtUtils::Embed -e perl_inc
+
+=item ccflags(), ccdlflags()
+
+These functions simply print $Config{ccflags} and $Config{ccdlflags}
+
+=item ccopts()
+
+This function combines perl_inc(), ccflags() and ccdlflags() into one.
+
+=item xsi_header()
+
+This function simply returns a string defining the same B<EXTERN_C> macro as
+B<perlmain.c> along with #including B<perl.h> and B<EXTERN.h>.  
+
+=item xsi_protos(@modules)
+
+This function returns a string of B<boot_$ModuleName> prototypes for each @modules.
+
+=item xsi_body(@modules)
+
+This function returns a string of calls to B<newXS()> that glue the module B<bootstrap>
+function to B<boot_ModuleName> for each @modules.
+
+B<xsinit()> uses the xsi_* functions to generate most of it's code.
+
+=head1 EXAMPLES
+
+For examples on how to use B<ExtUtils::Embed> for building C/C++ applications
+with embedded perl, see the eg/ directory and the I<perlembed> man page.
+=head1 SEE ALSO
+
+the I<perlembed> man page
+
+=head1 AUTHOR
+
+Doug MacEachern <dougm@osf.org>
+
+Based on ideas from Tim Bunce <Tim.Bunce@ig.co.uk> and
+B<minimod.pl> by Andreas Koenig <k@anna.in-berlin.de> and Tim Bunce.
+
+=cut
+
diff --git a/dist/nvi/dist/INSTALL b/dist/nvi/dist/INSTALL
new file mode 100644 (file)
index 0000000..b42a17a
--- /dev/null
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/dist/nvi/dist/Makefile.am b/dist/nvi/dist/Makefile.am
new file mode 100644 (file)
index 0000000..c1d6871
--- /dev/null
@@ -0,0 +1,381 @@
+visrcdir= @srcdir@/..
+
+ACLOCAL_AMFLAGS = -I m4
+
+lib_LTLIBRARIES = libvi.la
+libvi_la_SOURCES = \
+       $(visrcdir)/common/api.c \
+       $(visrcdir)/common/conv.c \
+       $(visrcdir)/common/conv.h \
+       $(visrcdir)/common/cut.c \
+       $(visrcdir)/common/delete.c \
+       $(visrcdir)/common/args.h \
+       $(visrcdir)/common/common.h \
+       $(visrcdir)/common/cut.h \
+       $(visrcdir)/common/db.h \
+       $(visrcdir)/common/exf.h \
+       $(visrcdir)/common/gs.h \
+       $(visrcdir)/common/key.h \
+       $(visrcdir)/common/log.h \
+       $(visrcdir)/common/mark.h \
+       $(visrcdir)/common/mem.h \
+       $(visrcdir)/common/multibyte.h \
+       $(visrcdir)/common/msg.h \
+       $(visrcdir)/common/options.h \
+       $(visrcdir)/common/options_def.h \
+       $(visrcdir)/common/screen.h \
+       $(visrcdir)/common/seq.h \
+       $(visrcdir)/common/util.h \
+       $(visrcdir)/ex/ex.c \
+       $(visrcdir)/ex/ex_abbrev.c \
+       $(visrcdir)/ex/ex_append.c \
+       $(visrcdir)/ex/ex_args.c \
+       $(visrcdir)/ex/ex_argv.c \
+       $(visrcdir)/ex/ex_at.c \
+       $(visrcdir)/ex/ex_bang.c \
+       $(visrcdir)/ex/ex_cd.c \
+       $(visrcdir)/ex/ex_cmd.c \
+       $(visrcdir)/ex/ex_cscope.c \
+       $(visrcdir)/ex/ex_delete.c \
+       $(visrcdir)/ex/ex_display.c \
+       $(visrcdir)/ex/ex_edit.c \
+       $(visrcdir)/ex/ex_equal.c \
+       $(visrcdir)/ex/ex_file.c \
+       $(visrcdir)/ex/ex_filter.c \
+       $(visrcdir)/ex/ex_global.c \
+       $(visrcdir)/ex/ex_init.c \
+       $(visrcdir)/ex/ex_join.c \
+       $(visrcdir)/ex/ex_map.c \
+       $(visrcdir)/ex/ex_mark.c \
+       $(visrcdir)/ex/ex_mkexrc.c \
+       $(visrcdir)/ex/ex_move.c \
+       $(visrcdir)/ex/ex_open.c \
+       $(visrcdir)/ex/ex_perl.c \
+       $(visrcdir)/ex/ex_preserve.c \
+       $(visrcdir)/ex/ex_print.c \
+       $(visrcdir)/ex/ex_put.c \
+       $(visrcdir)/ex/ex_quit.c \
+       $(visrcdir)/ex/ex_read.c \
+       $(visrcdir)/ex/ex_screen.c \
+       $(visrcdir)/ex/ex_script.c \
+       $(visrcdir)/ex/ex_set.c \
+       $(visrcdir)/ex/ex_shell.c \
+       $(visrcdir)/ex/ex_shift.c \
+       $(visrcdir)/ex/ex_source.c \
+       $(visrcdir)/ex/ex_stop.c \
+       $(visrcdir)/ex/ex_subst.c \
+       $(visrcdir)/ex/ex_tag.c \
+       $(visrcdir)/ex/ex_tcl.c \
+       $(visrcdir)/ex/ex_txt.c \
+       $(visrcdir)/ex/ex_undo.c \
+       $(visrcdir)/ex/ex_usage.c \
+       $(visrcdir)/ex/ex_util.c \
+       $(visrcdir)/ex/ex_version.c \
+       $(visrcdir)/ex/ex_visual.c \
+       $(visrcdir)/ex/ex_write.c \
+       $(visrcdir)/ex/ex_yank.c \
+       $(visrcdir)/ex/ex_z.c \
+       $(visrcdir)/ex/ex.h \
+       $(visrcdir)/ex/ex_def.h \
+       $(visrcdir)/ex/script.h \
+       $(visrcdir)/ex/tag.h \
+       $(visrcdir)/ex/version.h \
+       $(visrcdir)/common/exf.c \
+       $(visrcdir)/vi/getc.c \
+       $(visrcdir)/vi/vi.h \
+       $(visrcdir)/common/gs.c \
+       $(visrcdir)/common/key.c \
+       $(visrcdir)/common/db.c \
+       $(visrcdir)/common/main.c \
+       $(visrcdir)/common/mark.c \
+       $(visrcdir)/common/msg.c \
+       $(visrcdir)/common/options.c \
+       $(visrcdir)/common/options_f.c \
+       $(visrcdir)/common/put.c \
+       $(visrcdir)/common/recover.c \
+       $(visrcdir)/common/screen.c \
+       $(visrcdir)/common/search.c \
+       $(visrcdir)/common/seq.c \
+       $(visrcdir)/common/trace.c \
+       $(visrcdir)/common/util.c \
+       $(visrcdir)/common/util2.c \
+       $(visrcdir)/vi/v_at.c \
+       $(visrcdir)/vi/v_ch.c \
+       $(visrcdir)/vi/v_cmd.c \
+       $(visrcdir)/vi/v_delete.c \
+       $(visrcdir)/vi/v_event.c \
+       $(visrcdir)/vi/v_ex.c \
+       $(visrcdir)/vi/v_increment.c \
+       $(visrcdir)/vi/v_init.c \
+       $(visrcdir)/vi/v_itxt.c \
+       $(visrcdir)/vi/v_left.c \
+       $(visrcdir)/vi/v_mark.c \
+       $(visrcdir)/vi/v_match.c \
+       $(visrcdir)/vi/v_paragraph.c \
+       $(visrcdir)/vi/v_put.c \
+       $(visrcdir)/vi/v_redraw.c \
+       $(visrcdir)/vi/v_replace.c \
+       $(visrcdir)/vi/v_right.c \
+       $(visrcdir)/vi/v_screen.c \
+       $(visrcdir)/vi/v_scroll.c \
+       $(visrcdir)/vi/v_search.c \
+       $(visrcdir)/vi/v_section.c \
+       $(visrcdir)/vi/v_sentence.c \
+       $(visrcdir)/vi/v_status.c \
+       $(visrcdir)/vi/v_txt.c \
+       $(visrcdir)/vi/v_ulcase.c \
+       $(visrcdir)/vi/v_undo.c \
+       $(visrcdir)/vi/v_util.c \
+       $(visrcdir)/vi/v_word.c \
+       $(visrcdir)/vi/v_xchar.c \
+       $(visrcdir)/vi/v_yank.c \
+       $(visrcdir)/vi/v_z.c \
+       $(visrcdir)/vi/v_zexit.c \
+       $(visrcdir)/vi/vi.c \
+       $(visrcdir)/vi/vs_line.c \
+       $(visrcdir)/vi/vs_msg.c \
+       $(visrcdir)/vi/vs_refresh.c \
+       $(visrcdir)/vi/vs_relative.c \
+       $(visrcdir)/vi/vs_smap.c \
+       $(visrcdir)/vi/vs_split.c
+EXTRA_libvi_la_SOURCES = \
+       $(visrcdir)/regex/regcomp.c \
+       $(visrcdir)/regex/regerror.c \
+       $(visrcdir)/regex/regexec.c \
+       $(visrcdir)/regex/regfree.c \
+       $(visrcdir)/regex/cclass.h \
+       $(visrcdir)/regex/cname.h \
+       $(visrcdir)/regex/regex.h \
+       $(visrcdir)/regex/regex2.h \
+       $(visrcdir)/regex/utils.h \
+       $(visrcdir)/common/dldb.c \
+       $(visrcdir)/common/log.c \
+       $(visrcdir)/common/log4.c \
+       $(visrcdir)/clib/bsearch.c \
+       $(visrcdir)/clib/env.c \
+       $(visrcdir)/clib/gethostname.c \
+       $(visrcdir)/clib/iswblank.c \
+       $(visrcdir)/clib/memchr.c \
+       $(visrcdir)/clib/memset.c \
+       $(visrcdir)/clib/mkstemp.c \
+       $(visrcdir)/clib/mmap.c \
+       $(visrcdir)/clib/snprintf.c \
+       $(visrcdir)/clib/strdup.c \
+       $(visrcdir)/clib/strpbrk.c \
+       $(visrcdir)/clib/strsep.c \
+       $(visrcdir)/clib/strtol.c \
+       $(visrcdir)/clib/strtoul.c \
+       $(visrcdir)/clib/vsnprintf.c \
+       $(visrcdir)/common/pthread.c \
+       $(visrcdir)/common/vi_auto.c \
+       $(visrcdir)/common/vi_rec.c \
+       $(visrcdir)/perl_api/perl.xs \
+       $(visrcdir)/perl_api/perlsfio.c \
+       $(visrcdir)/tcl_api/tcl.c
+# Is this the way to do it ?
+libvi_la_DEPENDENCIES = @LTLIBOBJS@
+libvi_la_LIBADD = @LTLIBOBJS@
+
+bin_PROGRAMS = @vi_programs@ @vi_ipc@
+EXTRA_PROGRAMS = vi vi-ipc vi-motif vi-gtk
+
+vi_SOURCES = \
+       $(visrcdir)/cl/cl.h \
+       $(visrcdir)/cl/cl_bsd.c \
+       $(visrcdir)/cl/cl_funcs.c \
+       $(visrcdir)/cl/cl_main.c \
+       $(visrcdir)/cl/cl_read.c \
+       $(visrcdir)/cl/cl_screen.c \
+       $(visrcdir)/cl/cl_term.c \
+       $(visrcdir)/common/nothread.c
+vi_LDADD = libvi.la @perllibs@ @CURSLIBS@
+vi_CPPFLAGS = @CURSCPPFLAGS@ @perlldflags@ $(AM_CPPFLAGS)
+vi_LDFLAGS = @CURSLDFLAGS@ @perlldflags@
+
+vi_ipc_SOURCES = \
+       $(visrcdir)/ip/ip_funcs.c \
+       $(visrcdir)/ip/ip_main.c \
+       $(visrcdir)/ip/ip_read.c \
+       $(visrcdir)/ip/ip_screen.c \
+       $(visrcdir)/ipc/ip_send.c \
+       $(visrcdir)/ipc/ip.h \
+       $(visrcdir)/ip/ip_term.c 
+vi_ipc_LDADD = libvi.la @perllibs@ @IPCOBJS@
+vi_ipc_LDFLAGS = @perlldflags@
+vi_ipc_DEPENDENCIES = @IPCOBJS@
+
+vi_gtk_SOURCES = \
+       $(visrcdir)/common/util2.c \
+       $(visrcdir)/ipc/ip_run.c \
+       $(visrcdir)/ipc/ip_send.c \
+       $(visrcdir)/ipc/ip_trans.c \
+       $(visrcdir)/ipc/ipc_cmd.c \
+       $(visrcdir)/ipc/ipc_method.c \
+       $(visrcdir)/gtk/gtk_main.c \
+       $(visrcdir)/gtk/gtkvi.c \
+       $(visrcdir)/gtk/gtkviscreen.c \
+       $(visrcdir)/gtk/gtkviwindow.c
+vi_gtk_LDADD = @GTKLIBS@ @LIBOBJS@
+vi_gtk_CFLAGS = @GTKINCS@ @XINCS@
+
+vi_motif_SOURCES = \
+       $(visrcdir)/ipc/ip_run.c \
+       $(visrcdir)/ipc/ip_send.c \
+       $(visrcdir)/ipc/ip_trans.c \
+       $(visrcdir)/ipc/ipc_cmd.c \
+       $(visrcdir)/ipc/ipc_method.c \
+       $(visrcdir)/motif/m_main.c \
+       $(visrcdir)/motif/m_cde.c \
+       $(visrcdir)/common/trace.c \
+       $(visrcdir)/motif_l/m_copypaste.c \
+       $(visrcdir)/motif_l/m_func.c \
+       $(visrcdir)/motif_l/m_menu.c \
+       $(visrcdir)/motif_l/m_options.c \
+       $(visrcdir)/motif_l/m_prompt.c \
+       $(visrcdir)/motif_l/m_ruler.c \
+       $(visrcdir)/motif_l/m_search.c \
+       $(visrcdir)/motif_l/m_tags.c \
+       $(visrcdir)/motif_l/m_util.c \
+       $(visrcdir)/motif_l/m_vi.c \
+       $(visrcdir)/motif_l/xtabbed.c
+vi_motif_LDADD = @MOTIFLIBS@ @LIBOBJS@
+vi_motif_CFLAGS = @XINCS@
+
+VI=-DVI=\"$(bindir)/`echo vi-ipc | sed '$(transform)'`\"
+CFLAGS=        $(OPTFLAG)
+AM_CPPFLAGS=    -D__REGEX_PRIVATE -I. -I$(visrcdir)/include $(VI)
+PERL=  @vi_cv_path_perl@
+PERLLIB=@vi_cv_perllib@
+SHRPENV=@shrpenv@
+
+perl.c: $(visrcdir)/perl_api/perl.xs $(visrcdir)/perl_api/typemap
+       echo "#define _PATH_PERLSCRIPTS \"$(datadir)/vi/perl\"" > $@
+       $(PERL) -e 'unless ($$] >= 5.005) {' \
+               -e   'for (qw(incgv sv_undef errgv na)) {' \
+               -e     'print "#define PL_$$_ $$_\n" }} ' >> $@
+       $(PERL) $(PERLLIB)/ExtUtils/xsubpp -typemap \
+           $(PERLLIB)/ExtUtils/typemap $(visrcdir)/perl_api/perl.xs >> $@
+       ($(PERL) -ne 'print "sub $$1 {\$$curscr->$$1(\@_)}\n"' \
+                 -e   'if /newXS\("VI::([^\":]*)"/;' $@ ; echo "1;") > VI.pm
+perlxsi.c:
+       perl -MExtUtils::Embed -e xsinit -- -std VI
+
+chmod= @vi_cv_path_chmod@
+cp=    @vi_cv_path_cp@
+ln=    @vi_cv_path_ln@
+mkdir= @vi_cv_path_mkdir@
+rm=    @vi_cv_path_rm@
+strip= @vi_cv_path_strip@
+
+dmode= 755
+emode= 555
+fmode= 444
+
+install-exec-local:
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo ex | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo view | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(ln) \
+               `echo vi | sed '$(transform)'` `echo ex | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(ln) \
+               `echo vi | sed '$(transform)'` `echo view | sed '$(transform)'`
+
+install-data-local: install_common
+       @[ -d $(DESTDIR)$(mandir) ] || \
+           ($(mkdir) $(DESTDIR)$(mandir) && \
+            $(chmod) $(dmode) $(DESTDIR)$(mandir))
+       @[ -d $(DESTDIR)$(mandir)/cat1 ] || \
+           ($(mkdir) $(DESTDIR)$(mandir)/cat1 && \
+            $(chmod) $(dmode) $(DESTDIR)$(mandir)/cat1)
+       @echo "Installing man pages: $(DESTDIR)$(mandir) ..."
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo vi.0 | sed '$(transform)'`
+       @$(cp) $(visrcdir)/docs/vi.man/vi.0 \
+           $(DESTDIR)$(mandir)/cat1/`echo vi.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(chmod) $(fmode) `echo vi.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo ex.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo view.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && $(ln) \
+           `echo vi.0 | sed '$(transform)'` `echo ex.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && $(ln) \
+           `echo vi.0 | sed '$(transform)'` `echo view.0 | sed '$(transform)'`
+       @[ -d $(DESTDIR)$(mandir)/man1 ] || \
+           ($(mkdir) $(DESTDIR)$(mandir)/man1 && \
+            $(chmod) $(dmode) $(DESTDIR)$(mandir)/man1)
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo vi.1 | sed '$(transform)'`
+       @$(cp) $(visrcdir)/docs/vi.man/vi.1 \
+           $(DESTDIR)$(mandir)/man1/`echo vi.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(chmod) $(fmode) `echo vi.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo ex.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo view.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && $(ln) \
+           `echo vi.1 | sed '$(transform)'` `echo ex.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && $(ln) \
+           `echo vi.1 | sed '$(transform)'` `echo view.1 | sed '$(transform)'`
+
+cat=   dutch english french german ru_SU.KOI8-R spanish swedish
+install_common:
+       @[ -f $(chmod) ] || (echo 'chmod not found.'; exit 1)
+       @[ -f $(cp) ] || (echo 'cp not found.'; exit 1)
+       @[ -f $(ln) ] || (echo 'ln not found.'; exit 1)
+       @[ -f $(mkdir) ] || (echo 'mkdir not found.'; exit 1)
+       @[ -f $(rm) ] || (echo 'rm not found.'; exit 1)
+       @[ -d $(DESTDIR)$(prefix) ] || \
+           ($(mkdir) $(DESTDIR)$(prefix) && \
+               $(chmod) $(dmode) $(DESTDIR)$(prefix))
+       @[ -d $(DESTDIR)$(exec_prefix) ] || \
+           ($(mkdir) $(DESTDIR)$(exec_prefix) && \
+               $(chmod) $(dmode) $(DESTDIR)$(exec_prefix))
+       @[ -d $(DESTDIR)$(datadir) ] || \
+           ($(mkdir) $(DESTDIR)$(datadir) && \
+               $(chmod) $(dmode) $(DESTDIR)$(datadir))
+       @$(rm) -rf $(DESTDIR)$(datadir)/vi
+       @$(mkdir) $(DESTDIR)$(datadir)/vi && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi
+       @echo "Installing message catalogs: $(datadir)/vi/catalog ..."
+       @$(mkdir) $(DESTDIR)$(datadir)/vi/catalog && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi/catalog
+       @(cd $(visrcdir)/catalog && \
+           $(cp) $(cat) $(DESTDIR)$(datadir)/vi/catalog && \
+           cd $(DESTDIR)$(datadir)/vi/catalog && $(chmod) $(fmode) *)
+       @echo "Installing Perl scripts: $(datadir)/vi/perl ..."
+       @$(mkdir) $(DESTDIR)$(datadir)/vi/perl && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi/perl
+       @[ ! -f VI.pm ] || \
+           ($(cp) VI.pm $(DESTDIR)$(datadir)/vi/perl && \
+           (cd $(DESTDIR)$(datadir)/vi/perl && $(chmod) $(fmode) VI.pm))
+       @(cd $(visrcdir)/perl_scripts && \
+           $(cp) *.pl $(DESTDIR)$(datadir)/vi/perl && \
+           cd $(DESTDIR)$(datadir)/vi/perl && $(chmod) $(fmode) *.pl)
+       @echo "Installing Tcl scripts: $(datadir)/vi/tcl ..."
+       @$(mkdir) $(DESTDIR)$(datadir)/vi/tcl && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi/tcl
+       @(cd $(visrcdir)/tcl_scripts && \
+           $(cp) *.tcl $(DESTDIR)$(datadir)/vi/tcl && \
+           cd $(DESTDIR)$(datadir)/vi/tcl && $(chmod) $(fmode) *.tcl)
+       @echo "Installing recover script: $(datadir)/vi/recover ..."
+       @($(cp) recover $(DESTDIR)$(datadir)/vi/recover && \
+           $(chmod) $(emode) $(DESTDIR)$(datadir)/vi/recover)
+
+uninstall-local:
+       $(rm) -rf $(DESTDIR)$(datadir)/vi
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo ex | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo view | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo ex.0 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo vi.0 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo view.0 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo ex.1 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo vi.1 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo view.1 | sed '$(transform)'`
diff --git a/dist/nvi/dist/Makefile.in b/dist/nvi/dist/Makefile.in
new file mode 100644 (file)
index 0000000..7bca817
--- /dev/null
@@ -0,0 +1,1797 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+EXTRA_PROGRAMS = vi$(EXEEXT) vi-ipc$(EXEEXT) vi-motif$(EXEEXT) \
+       vi-gtk$(EXEEXT)
+subdir = .
+DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+       $(srcdir)/pathnames.h.in $(srcdir)/port.h.in \
+       $(srcdir)/recover.in $(top_srcdir)/configure INSTALL \
+       acconfig.h compile config.guess config.sub depcomp install-sh \
+       ltconfig ltmain.sh missing mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gtk.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = port.h pathnames.h recover
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am_libvi_la_OBJECTS = api.lo conv.lo cut.lo delete.lo ex.lo \
+       ex_abbrev.lo ex_append.lo ex_args.lo ex_argv.lo ex_at.lo \
+       ex_bang.lo ex_cd.lo ex_cmd.lo ex_cscope.lo ex_delete.lo \
+       ex_display.lo ex_edit.lo ex_equal.lo ex_file.lo ex_filter.lo \
+       ex_global.lo ex_init.lo ex_join.lo ex_map.lo ex_mark.lo \
+       ex_mkexrc.lo ex_move.lo ex_open.lo ex_perl.lo ex_preserve.lo \
+       ex_print.lo ex_put.lo ex_quit.lo ex_read.lo ex_screen.lo \
+       ex_script.lo ex_set.lo ex_shell.lo ex_shift.lo ex_source.lo \
+       ex_stop.lo ex_subst.lo ex_tag.lo ex_tcl.lo ex_txt.lo \
+       ex_undo.lo ex_usage.lo ex_util.lo ex_version.lo ex_visual.lo \
+       ex_write.lo ex_yank.lo ex_z.lo exf.lo getc.lo gs.lo key.lo \
+       db.lo main.lo mark.lo msg.lo options.lo options_f.lo put.lo \
+       recover.lo screen.lo search.lo seq.lo trace.lo util.lo \
+       util2.lo v_at.lo v_ch.lo v_cmd.lo v_delete.lo v_event.lo \
+       v_ex.lo v_increment.lo v_init.lo v_itxt.lo v_left.lo v_mark.lo \
+       v_match.lo v_paragraph.lo v_put.lo v_redraw.lo v_replace.lo \
+       v_right.lo v_screen.lo v_scroll.lo v_search.lo v_section.lo \
+       v_sentence.lo v_status.lo v_txt.lo v_ulcase.lo v_undo.lo \
+       v_util.lo v_word.lo v_xchar.lo v_yank.lo v_z.lo v_zexit.lo \
+       vi.lo vs_line.lo vs_msg.lo vs_refresh.lo vs_relative.lo \
+       vs_smap.lo vs_split.lo
+libvi_la_OBJECTS = $(am_libvi_la_OBJECTS)
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_vi_OBJECTS = vi-cl_bsd.$(OBJEXT) vi-cl_funcs.$(OBJEXT) \
+       vi-cl_main.$(OBJEXT) vi-cl_read.$(OBJEXT) \
+       vi-cl_screen.$(OBJEXT) vi-cl_term.$(OBJEXT) \
+       vi-nothread.$(OBJEXT)
+vi_OBJECTS = $(am_vi_OBJECTS)
+vi_DEPENDENCIES = libvi.la
+vi_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(vi_LDFLAGS) \
+       $(LDFLAGS) -o $@
+am_vi_gtk_OBJECTS = vi_gtk-util2.$(OBJEXT) vi_gtk-ip_run.$(OBJEXT) \
+       vi_gtk-ip_send.$(OBJEXT) vi_gtk-ip_trans.$(OBJEXT) \
+       vi_gtk-ipc_cmd.$(OBJEXT) vi_gtk-ipc_method.$(OBJEXT) \
+       vi_gtk-gtk_main.$(OBJEXT) vi_gtk-gtkvi.$(OBJEXT) \
+       vi_gtk-gtkviscreen.$(OBJEXT) vi_gtk-gtkviwindow.$(OBJEXT)
+vi_gtk_OBJECTS = $(am_vi_gtk_OBJECTS)
+vi_gtk_DEPENDENCIES = @LIBOBJS@
+vi_gtk_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(vi_gtk_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+am_vi_ipc_OBJECTS = ip_funcs.$(OBJEXT) ip_main.$(OBJEXT) \
+       ip_read.$(OBJEXT) ip_screen.$(OBJEXT) ip_send.$(OBJEXT) \
+       ip_term.$(OBJEXT)
+vi_ipc_OBJECTS = $(am_vi_ipc_OBJECTS)
+vi_ipc_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(vi_ipc_LDFLAGS) \
+       $(LDFLAGS) -o $@
+am_vi_motif_OBJECTS = vi_motif-ip_run.$(OBJEXT) \
+       vi_motif-ip_send.$(OBJEXT) vi_motif-ip_trans.$(OBJEXT) \
+       vi_motif-ipc_cmd.$(OBJEXT) vi_motif-ipc_method.$(OBJEXT) \
+       vi_motif-m_main.$(OBJEXT) vi_motif-m_cde.$(OBJEXT) \
+       vi_motif-trace.$(OBJEXT) vi_motif-m_copypaste.$(OBJEXT) \
+       vi_motif-m_func.$(OBJEXT) vi_motif-m_menu.$(OBJEXT) \
+       vi_motif-m_options.$(OBJEXT) vi_motif-m_prompt.$(OBJEXT) \
+       vi_motif-m_ruler.$(OBJEXT) vi_motif-m_search.$(OBJEXT) \
+       vi_motif-m_tags.$(OBJEXT) vi_motif-m_util.$(OBJEXT) \
+       vi_motif-m_vi.$(OBJEXT) vi_motif-xtabbed.$(OBJEXT)
+vi_motif_OBJECTS = $(am_vi_motif_OBJECTS)
+vi_motif_DEPENDENCIES = @LIBOBJS@
+vi_motif_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(vi_motif_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(libvi_la_SOURCES) $(EXTRA_libvi_la_SOURCES) $(vi_SOURCES) \
+       $(vi_gtk_SOURCES) $(vi_ipc_SOURCES) $(vi_motif_SOURCES)
+DIST_SOURCES = $(libvi_la_SOURCES) $(EXTRA_libvi_la_SOURCES) \
+       $(vi_SOURCES) $(vi_gtk_SOURCES) $(vi_ipc_SOURCES) \
+       $(vi_motif_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = $(OPTFLAG)
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURSCPPFLAGS = @CURSCPPFLAGS@
+CURSLDFLAGS = @CURSLDFLAGS@
+CURSLIBS = @CURSLIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+GTKINCS = @GTKINCS@
+GTKLIBS = @GTKLIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_CONFIG = @GTK_CONFIG@
+GTK_LIBS = @GTK_LIBS@
+HAVE_NCURSESW = @HAVE_NCURSESW@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INUSE = @INUSE@
+IPCOBJS = @IPCOBJS@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MOTIFLIBS = @MOTIFLIBS@
+NEED_FPRINTF_PROTO = @NEED_FPRINTF_PROTO@
+OBJEXT = @OBJEXT@
+OPTFLAG = @OPTFLAG@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XINCS = @XINCS@
+XMKMF = @XMKMF@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dl_src = @dl_src@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+int16_decl = @int16_decl@
+int32_decl = @int32_decl@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+no_op_OPTFLAG = @no_op_OPTFLAG@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+perlldflags = @perlldflags@
+perllibs = @perllibs@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+shrpenv = @shrpenv@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+u_char_decl = @u_char_decl@
+u_int16_decl = @u_int16_decl@
+u_int32_decl = @u_int32_decl@
+u_int8_decl = @u_int8_decl@
+u_int_decl = @u_int_decl@
+u_long_decl = @u_long_decl@
+u_short_decl = @u_short_decl@
+vi_cv_path_ar = @vi_cv_path_ar@
+vi_cv_path_chmod = @vi_cv_path_chmod@
+vi_cv_path_cp = @vi_cv_path_cp@
+vi_cv_path_db3 = @vi_cv_path_db3@
+vi_cv_path_fuser = @vi_cv_path_fuser@
+vi_cv_path_ln = @vi_cv_path_ln@
+vi_cv_path_lsof = @vi_cv_path_lsof@
+vi_cv_path_mkdir = @vi_cv_path_mkdir@
+vi_cv_path_perl = @vi_cv_path_perl@
+vi_cv_path_preserve = @vi_cv_path_preserve@
+vi_cv_path_ranlib = @vi_cv_path_ranlib@
+vi_cv_path_rm = @vi_cv_path_rm@
+vi_cv_path_sendmail = @vi_cv_path_sendmail@
+vi_cv_path_shell = @vi_cv_path_shell@
+vi_cv_path_strip = @vi_cv_path_strip@
+vi_cv_perllib = @vi_cv_perllib@
+vi_ipc = @vi_ipc@
+vi_programs = @vi_programs@
+visrcdir = @srcdir@/..
+ACLOCAL_AMFLAGS = -I m4
+lib_LTLIBRARIES = libvi.la
+libvi_la_SOURCES = \
+       $(visrcdir)/common/api.c \
+       $(visrcdir)/common/conv.c \
+       $(visrcdir)/common/conv.h \
+       $(visrcdir)/common/cut.c \
+       $(visrcdir)/common/delete.c \
+       $(visrcdir)/common/args.h \
+       $(visrcdir)/common/common.h \
+       $(visrcdir)/common/cut.h \
+       $(visrcdir)/common/db.h \
+       $(visrcdir)/common/exf.h \
+       $(visrcdir)/common/gs.h \
+       $(visrcdir)/common/key.h \
+       $(visrcdir)/common/log.h \
+       $(visrcdir)/common/mark.h \
+       $(visrcdir)/common/mem.h \
+       $(visrcdir)/common/multibyte.h \
+       $(visrcdir)/common/msg.h \
+       $(visrcdir)/common/options.h \
+       $(visrcdir)/common/options_def.h \
+       $(visrcdir)/common/screen.h \
+       $(visrcdir)/common/seq.h \
+       $(visrcdir)/common/util.h \
+       $(visrcdir)/ex/ex.c \
+       $(visrcdir)/ex/ex_abbrev.c \
+       $(visrcdir)/ex/ex_append.c \
+       $(visrcdir)/ex/ex_args.c \
+       $(visrcdir)/ex/ex_argv.c \
+       $(visrcdir)/ex/ex_at.c \
+       $(visrcdir)/ex/ex_bang.c \
+       $(visrcdir)/ex/ex_cd.c \
+       $(visrcdir)/ex/ex_cmd.c \
+       $(visrcdir)/ex/ex_cscope.c \
+       $(visrcdir)/ex/ex_delete.c \
+       $(visrcdir)/ex/ex_display.c \
+       $(visrcdir)/ex/ex_edit.c \
+       $(visrcdir)/ex/ex_equal.c \
+       $(visrcdir)/ex/ex_file.c \
+       $(visrcdir)/ex/ex_filter.c \
+       $(visrcdir)/ex/ex_global.c \
+       $(visrcdir)/ex/ex_init.c \
+       $(visrcdir)/ex/ex_join.c \
+       $(visrcdir)/ex/ex_map.c \
+       $(visrcdir)/ex/ex_mark.c \
+       $(visrcdir)/ex/ex_mkexrc.c \
+       $(visrcdir)/ex/ex_move.c \
+       $(visrcdir)/ex/ex_open.c \
+       $(visrcdir)/ex/ex_perl.c \
+       $(visrcdir)/ex/ex_preserve.c \
+       $(visrcdir)/ex/ex_print.c \
+       $(visrcdir)/ex/ex_put.c \
+       $(visrcdir)/ex/ex_quit.c \
+       $(visrcdir)/ex/ex_read.c \
+       $(visrcdir)/ex/ex_screen.c \
+       $(visrcdir)/ex/ex_script.c \
+       $(visrcdir)/ex/ex_set.c \
+       $(visrcdir)/ex/ex_shell.c \
+       $(visrcdir)/ex/ex_shift.c \
+       $(visrcdir)/ex/ex_source.c \
+       $(visrcdir)/ex/ex_stop.c \
+       $(visrcdir)/ex/ex_subst.c \
+       $(visrcdir)/ex/ex_tag.c \
+       $(visrcdir)/ex/ex_tcl.c \
+       $(visrcdir)/ex/ex_txt.c \
+       $(visrcdir)/ex/ex_undo.c \
+       $(visrcdir)/ex/ex_usage.c \
+       $(visrcdir)/ex/ex_util.c \
+       $(visrcdir)/ex/ex_version.c \
+       $(visrcdir)/ex/ex_visual.c \
+       $(visrcdir)/ex/ex_write.c \
+       $(visrcdir)/ex/ex_yank.c \
+       $(visrcdir)/ex/ex_z.c \
+       $(visrcdir)/ex/ex.h \
+       $(visrcdir)/ex/ex_def.h \
+       $(visrcdir)/ex/script.h \
+       $(visrcdir)/ex/tag.h \
+       $(visrcdir)/ex/version.h \
+       $(visrcdir)/common/exf.c \
+       $(visrcdir)/vi/getc.c \
+       $(visrcdir)/vi/vi.h \
+       $(visrcdir)/common/gs.c \
+       $(visrcdir)/common/key.c \
+       $(visrcdir)/common/db.c \
+       $(visrcdir)/common/main.c \
+       $(visrcdir)/common/mark.c \
+       $(visrcdir)/common/msg.c \
+       $(visrcdir)/common/options.c \
+       $(visrcdir)/common/options_f.c \
+       $(visrcdir)/common/put.c \
+       $(visrcdir)/common/recover.c \
+       $(visrcdir)/common/screen.c \
+       $(visrcdir)/common/search.c \
+       $(visrcdir)/common/seq.c \
+       $(visrcdir)/common/trace.c \
+       $(visrcdir)/common/util.c \
+       $(visrcdir)/common/util2.c \
+       $(visrcdir)/vi/v_at.c \
+       $(visrcdir)/vi/v_ch.c \
+       $(visrcdir)/vi/v_cmd.c \
+       $(visrcdir)/vi/v_delete.c \
+       $(visrcdir)/vi/v_event.c \
+       $(visrcdir)/vi/v_ex.c \
+       $(visrcdir)/vi/v_increment.c \
+       $(visrcdir)/vi/v_init.c \
+       $(visrcdir)/vi/v_itxt.c \
+       $(visrcdir)/vi/v_left.c \
+       $(visrcdir)/vi/v_mark.c \
+       $(visrcdir)/vi/v_match.c \
+       $(visrcdir)/vi/v_paragraph.c \
+       $(visrcdir)/vi/v_put.c \
+       $(visrcdir)/vi/v_redraw.c \
+       $(visrcdir)/vi/v_replace.c \
+       $(visrcdir)/vi/v_right.c \
+       $(visrcdir)/vi/v_screen.c \
+       $(visrcdir)/vi/v_scroll.c \
+       $(visrcdir)/vi/v_search.c \
+       $(visrcdir)/vi/v_section.c \
+       $(visrcdir)/vi/v_sentence.c \
+       $(visrcdir)/vi/v_status.c \
+       $(visrcdir)/vi/v_txt.c \
+       $(visrcdir)/vi/v_ulcase.c \
+       $(visrcdir)/vi/v_undo.c \
+       $(visrcdir)/vi/v_util.c \
+       $(visrcdir)/vi/v_word.c \
+       $(visrcdir)/vi/v_xchar.c \
+       $(visrcdir)/vi/v_yank.c \
+       $(visrcdir)/vi/v_z.c \
+       $(visrcdir)/vi/v_zexit.c \
+       $(visrcdir)/vi/vi.c \
+       $(visrcdir)/vi/vs_line.c \
+       $(visrcdir)/vi/vs_msg.c \
+       $(visrcdir)/vi/vs_refresh.c \
+       $(visrcdir)/vi/vs_relative.c \
+       $(visrcdir)/vi/vs_smap.c \
+       $(visrcdir)/vi/vs_split.c
+
+EXTRA_libvi_la_SOURCES = \
+       $(visrcdir)/regex/regcomp.c \
+       $(visrcdir)/regex/regerror.c \
+       $(visrcdir)/regex/regexec.c \
+       $(visrcdir)/regex/regfree.c \
+       $(visrcdir)/regex/cclass.h \
+       $(visrcdir)/regex/cname.h \
+       $(visrcdir)/regex/regex.h \
+       $(visrcdir)/regex/regex2.h \
+       $(visrcdir)/regex/utils.h \
+       $(visrcdir)/common/dldb.c \
+       $(visrcdir)/common/log.c \
+       $(visrcdir)/common/log4.c \
+       $(visrcdir)/clib/bsearch.c \
+       $(visrcdir)/clib/env.c \
+       $(visrcdir)/clib/gethostname.c \
+       $(visrcdir)/clib/iswblank.c \
+       $(visrcdir)/clib/memchr.c \
+       $(visrcdir)/clib/memset.c \
+       $(visrcdir)/clib/mkstemp.c \
+       $(visrcdir)/clib/mmap.c \
+       $(visrcdir)/clib/snprintf.c \
+       $(visrcdir)/clib/strdup.c \
+       $(visrcdir)/clib/strpbrk.c \
+       $(visrcdir)/clib/strsep.c \
+       $(visrcdir)/clib/strtol.c \
+       $(visrcdir)/clib/strtoul.c \
+       $(visrcdir)/clib/vsnprintf.c \
+       $(visrcdir)/common/pthread.c \
+       $(visrcdir)/common/vi_auto.c \
+       $(visrcdir)/common/vi_rec.c \
+       $(visrcdir)/perl_api/perl.xs \
+       $(visrcdir)/perl_api/perlsfio.c \
+       $(visrcdir)/tcl_api/tcl.c
+
+# Is this the way to do it ?
+libvi_la_DEPENDENCIES = @LTLIBOBJS@
+libvi_la_LIBADD = @LTLIBOBJS@
+bin_PROGRAMS = @vi_programs@ @vi_ipc@
+vi_SOURCES = \
+       $(visrcdir)/cl/cl.h \
+       $(visrcdir)/cl/cl_bsd.c \
+       $(visrcdir)/cl/cl_funcs.c \
+       $(visrcdir)/cl/cl_main.c \
+       $(visrcdir)/cl/cl_read.c \
+       $(visrcdir)/cl/cl_screen.c \
+       $(visrcdir)/cl/cl_term.c \
+       $(visrcdir)/common/nothread.c
+
+vi_LDADD = libvi.la @perllibs@ @CURSLIBS@
+vi_CPPFLAGS = @CURSCPPFLAGS@ @perlldflags@ $(AM_CPPFLAGS)
+vi_LDFLAGS = @CURSLDFLAGS@ @perlldflags@
+vi_ipc_SOURCES = \
+       $(visrcdir)/ip/ip_funcs.c \
+       $(visrcdir)/ip/ip_main.c \
+       $(visrcdir)/ip/ip_read.c \
+       $(visrcdir)/ip/ip_screen.c \
+       $(visrcdir)/ipc/ip_send.c \
+       $(visrcdir)/ipc/ip.h \
+       $(visrcdir)/ip/ip_term.c 
+
+vi_ipc_LDADD = libvi.la @perllibs@ @IPCOBJS@
+vi_ipc_LDFLAGS = @perlldflags@
+vi_ipc_DEPENDENCIES = @IPCOBJS@
+vi_gtk_SOURCES = \
+       $(visrcdir)/common/util2.c \
+       $(visrcdir)/ipc/ip_run.c \
+       $(visrcdir)/ipc/ip_send.c \
+       $(visrcdir)/ipc/ip_trans.c \
+       $(visrcdir)/ipc/ipc_cmd.c \
+       $(visrcdir)/ipc/ipc_method.c \
+       $(visrcdir)/gtk/gtk_main.c \
+       $(visrcdir)/gtk/gtkvi.c \
+       $(visrcdir)/gtk/gtkviscreen.c \
+       $(visrcdir)/gtk/gtkviwindow.c
+
+vi_gtk_LDADD = @GTKLIBS@ @LIBOBJS@
+vi_gtk_CFLAGS = @GTKINCS@ @XINCS@
+vi_motif_SOURCES = \
+       $(visrcdir)/ipc/ip_run.c \
+       $(visrcdir)/ipc/ip_send.c \
+       $(visrcdir)/ipc/ip_trans.c \
+       $(visrcdir)/ipc/ipc_cmd.c \
+       $(visrcdir)/ipc/ipc_method.c \
+       $(visrcdir)/motif/m_main.c \
+       $(visrcdir)/motif/m_cde.c \
+       $(visrcdir)/common/trace.c \
+       $(visrcdir)/motif_l/m_copypaste.c \
+       $(visrcdir)/motif_l/m_func.c \
+       $(visrcdir)/motif_l/m_menu.c \
+       $(visrcdir)/motif_l/m_options.c \
+       $(visrcdir)/motif_l/m_prompt.c \
+       $(visrcdir)/motif_l/m_ruler.c \
+       $(visrcdir)/motif_l/m_search.c \
+       $(visrcdir)/motif_l/m_tags.c \
+       $(visrcdir)/motif_l/m_util.c \
+       $(visrcdir)/motif_l/m_vi.c \
+       $(visrcdir)/motif_l/xtabbed.c
+
+vi_motif_LDADD = @MOTIFLIBS@ @LIBOBJS@
+vi_motif_CFLAGS = @XINCS@
+VI = -DVI=\"$(bindir)/`echo vi-ipc | sed '$(transform)'`\"
+AM_CPPFLAGS = -D__REGEX_PRIVATE -I. -I$(visrcdir)/include $(VI)
+PERL = @vi_cv_path_perl@
+PERLLIB = @vi_cv_perllib@
+SHRPENV = @shrpenv@
+chmod = @vi_cv_path_chmod@
+cp = @vi_cv_path_cp@
+ln = @vi_cv_path_ln@
+mkdir = @vi_cv_path_mkdir@
+rm = @vi_cv_path_rm@
+strip = @vi_cv_path_strip@
+dmode = 755
+emode = 555
+fmode = 444
+cat = dutch english french german ru_SU.KOI8-R spanish swedish
+all: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+am--refresh:
+       @:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign  --ignore-deps'; \
+             cd $(srcdir) && $(AUTOMAKE) --foreign  --ignore-deps \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  --ignore-deps Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  --ignore-deps Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+       @if test ! -f $@; then \
+         rm -f stamp-h1; \
+         $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+       else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+       @rm -f stamp-h1
+       cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in:  $(am__configure_deps) $(top_srcdir)/acconfig.h
+       cd $(top_srcdir) && $(AUTOHEADER)
+       rm -f stamp-h1
+       touch $@
+
+distclean-hdr:
+       -rm -f config.h stamp-h1
+port.h: $(top_builddir)/config.status $(srcdir)/port.h.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
+pathnames.h: $(top_builddir)/config.status $(srcdir)/pathnames.h.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
+recover: $(top_builddir)/config.status $(srcdir)/recover.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+           $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+         $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+libvi.la: $(libvi_la_OBJECTS) $(libvi_la_DEPENDENCIES) 
+       $(LINK) -rpath $(libdir) $(libvi_la_OBJECTS) $(libvi_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+         rm -f "$(DESTDIR)$(bindir)/$$f"; \
+       done
+
+clean-binPROGRAMS:
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
+       done
+vi$(EXEEXT): $(vi_OBJECTS) $(vi_DEPENDENCIES) 
+       @rm -f vi$(EXEEXT)
+       $(vi_LINK) $(vi_OBJECTS) $(vi_LDADD) $(LIBS)
+vi-gtk$(EXEEXT): $(vi_gtk_OBJECTS) $(vi_gtk_DEPENDENCIES) 
+       @rm -f vi-gtk$(EXEEXT)
+       $(vi_gtk_LINK) $(vi_gtk_OBJECTS) $(vi_gtk_LDADD) $(LIBS)
+vi-ipc$(EXEEXT): $(vi_ipc_OBJECTS) $(vi_ipc_DEPENDENCIES) 
+       @rm -f vi-ipc$(EXEEXT)
+       $(vi_ipc_LINK) $(vi_ipc_OBJECTS) $(vi_ipc_LDADD) $(LIBS)
+vi-motif$(EXEEXT): $(vi_motif_OBJECTS) $(vi_motif_DEPENDENCIES) 
+       @rm -f vi-motif$(EXEEXT)
+       $(vi_motif_LINK) $(vi_motif_OBJECTS) $(vi_motif_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+.c.o:
+       $(COMPILE) -c $<
+
+.c.obj:
+       $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+       $(LTCOMPILE) -c -o $@ $<
+
+api.lo: $(visrcdir)/common/api.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o api.lo `test -f '$(visrcdir)/common/api.c' || echo '$(srcdir)/'`$(visrcdir)/common/api.c
+
+conv.lo: $(visrcdir)/common/conv.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o conv.lo `test -f '$(visrcdir)/common/conv.c' || echo '$(srcdir)/'`$(visrcdir)/common/conv.c
+
+cut.lo: $(visrcdir)/common/cut.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cut.lo `test -f '$(visrcdir)/common/cut.c' || echo '$(srcdir)/'`$(visrcdir)/common/cut.c
+
+delete.lo: $(visrcdir)/common/delete.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete.lo `test -f '$(visrcdir)/common/delete.c' || echo '$(srcdir)/'`$(visrcdir)/common/delete.c
+
+ex.lo: $(visrcdir)/ex/ex.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex.lo `test -f '$(visrcdir)/ex/ex.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex.c
+
+ex_abbrev.lo: $(visrcdir)/ex/ex_abbrev.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_abbrev.lo `test -f '$(visrcdir)/ex/ex_abbrev.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_abbrev.c
+
+ex_append.lo: $(visrcdir)/ex/ex_append.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_append.lo `test -f '$(visrcdir)/ex/ex_append.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_append.c
+
+ex_args.lo: $(visrcdir)/ex/ex_args.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_args.lo `test -f '$(visrcdir)/ex/ex_args.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_args.c
+
+ex_argv.lo: $(visrcdir)/ex/ex_argv.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_argv.lo `test -f '$(visrcdir)/ex/ex_argv.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_argv.c
+
+ex_at.lo: $(visrcdir)/ex/ex_at.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_at.lo `test -f '$(visrcdir)/ex/ex_at.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_at.c
+
+ex_bang.lo: $(visrcdir)/ex/ex_bang.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_bang.lo `test -f '$(visrcdir)/ex/ex_bang.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_bang.c
+
+ex_cd.lo: $(visrcdir)/ex/ex_cd.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_cd.lo `test -f '$(visrcdir)/ex/ex_cd.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_cd.c
+
+ex_cmd.lo: $(visrcdir)/ex/ex_cmd.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_cmd.lo `test -f '$(visrcdir)/ex/ex_cmd.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_cmd.c
+
+ex_cscope.lo: $(visrcdir)/ex/ex_cscope.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_cscope.lo `test -f '$(visrcdir)/ex/ex_cscope.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_cscope.c
+
+ex_delete.lo: $(visrcdir)/ex/ex_delete.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_delete.lo `test -f '$(visrcdir)/ex/ex_delete.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_delete.c
+
+ex_display.lo: $(visrcdir)/ex/ex_display.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_display.lo `test -f '$(visrcdir)/ex/ex_display.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_display.c
+
+ex_edit.lo: $(visrcdir)/ex/ex_edit.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_edit.lo `test -f '$(visrcdir)/ex/ex_edit.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_edit.c
+
+ex_equal.lo: $(visrcdir)/ex/ex_equal.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_equal.lo `test -f '$(visrcdir)/ex/ex_equal.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_equal.c
+
+ex_file.lo: $(visrcdir)/ex/ex_file.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_file.lo `test -f '$(visrcdir)/ex/ex_file.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_file.c
+
+ex_filter.lo: $(visrcdir)/ex/ex_filter.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_filter.lo `test -f '$(visrcdir)/ex/ex_filter.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_filter.c
+
+ex_global.lo: $(visrcdir)/ex/ex_global.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_global.lo `test -f '$(visrcdir)/ex/ex_global.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_global.c
+
+ex_init.lo: $(visrcdir)/ex/ex_init.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_init.lo `test -f '$(visrcdir)/ex/ex_init.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_init.c
+
+ex_join.lo: $(visrcdir)/ex/ex_join.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_join.lo `test -f '$(visrcdir)/ex/ex_join.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_join.c
+
+ex_map.lo: $(visrcdir)/ex/ex_map.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_map.lo `test -f '$(visrcdir)/ex/ex_map.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_map.c
+
+ex_mark.lo: $(visrcdir)/ex/ex_mark.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_mark.lo `test -f '$(visrcdir)/ex/ex_mark.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_mark.c
+
+ex_mkexrc.lo: $(visrcdir)/ex/ex_mkexrc.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_mkexrc.lo `test -f '$(visrcdir)/ex/ex_mkexrc.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_mkexrc.c
+
+ex_move.lo: $(visrcdir)/ex/ex_move.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_move.lo `test -f '$(visrcdir)/ex/ex_move.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_move.c
+
+ex_open.lo: $(visrcdir)/ex/ex_open.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_open.lo `test -f '$(visrcdir)/ex/ex_open.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_open.c
+
+ex_perl.lo: $(visrcdir)/ex/ex_perl.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_perl.lo `test -f '$(visrcdir)/ex/ex_perl.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_perl.c
+
+ex_preserve.lo: $(visrcdir)/ex/ex_preserve.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_preserve.lo `test -f '$(visrcdir)/ex/ex_preserve.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_preserve.c
+
+ex_print.lo: $(visrcdir)/ex/ex_print.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_print.lo `test -f '$(visrcdir)/ex/ex_print.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_print.c
+
+ex_put.lo: $(visrcdir)/ex/ex_put.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_put.lo `test -f '$(visrcdir)/ex/ex_put.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_put.c
+
+ex_quit.lo: $(visrcdir)/ex/ex_quit.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_quit.lo `test -f '$(visrcdir)/ex/ex_quit.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_quit.c
+
+ex_read.lo: $(visrcdir)/ex/ex_read.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_read.lo `test -f '$(visrcdir)/ex/ex_read.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_read.c
+
+ex_screen.lo: $(visrcdir)/ex/ex_screen.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_screen.lo `test -f '$(visrcdir)/ex/ex_screen.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_screen.c
+
+ex_script.lo: $(visrcdir)/ex/ex_script.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_script.lo `test -f '$(visrcdir)/ex/ex_script.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_script.c
+
+ex_set.lo: $(visrcdir)/ex/ex_set.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_set.lo `test -f '$(visrcdir)/ex/ex_set.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_set.c
+
+ex_shell.lo: $(visrcdir)/ex/ex_shell.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_shell.lo `test -f '$(visrcdir)/ex/ex_shell.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_shell.c
+
+ex_shift.lo: $(visrcdir)/ex/ex_shift.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_shift.lo `test -f '$(visrcdir)/ex/ex_shift.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_shift.c
+
+ex_source.lo: $(visrcdir)/ex/ex_source.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_source.lo `test -f '$(visrcdir)/ex/ex_source.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_source.c
+
+ex_stop.lo: $(visrcdir)/ex/ex_stop.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_stop.lo `test -f '$(visrcdir)/ex/ex_stop.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_stop.c
+
+ex_subst.lo: $(visrcdir)/ex/ex_subst.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_subst.lo `test -f '$(visrcdir)/ex/ex_subst.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_subst.c
+
+ex_tag.lo: $(visrcdir)/ex/ex_tag.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_tag.lo `test -f '$(visrcdir)/ex/ex_tag.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_tag.c
+
+ex_tcl.lo: $(visrcdir)/ex/ex_tcl.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_tcl.lo `test -f '$(visrcdir)/ex/ex_tcl.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_tcl.c
+
+ex_txt.lo: $(visrcdir)/ex/ex_txt.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_txt.lo `test -f '$(visrcdir)/ex/ex_txt.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_txt.c
+
+ex_undo.lo: $(visrcdir)/ex/ex_undo.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_undo.lo `test -f '$(visrcdir)/ex/ex_undo.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_undo.c
+
+ex_usage.lo: $(visrcdir)/ex/ex_usage.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_usage.lo `test -f '$(visrcdir)/ex/ex_usage.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_usage.c
+
+ex_util.lo: $(visrcdir)/ex/ex_util.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_util.lo `test -f '$(visrcdir)/ex/ex_util.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_util.c
+
+ex_version.lo: $(visrcdir)/ex/ex_version.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_version.lo `test -f '$(visrcdir)/ex/ex_version.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_version.c
+
+ex_visual.lo: $(visrcdir)/ex/ex_visual.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_visual.lo `test -f '$(visrcdir)/ex/ex_visual.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_visual.c
+
+ex_write.lo: $(visrcdir)/ex/ex_write.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_write.lo `test -f '$(visrcdir)/ex/ex_write.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_write.c
+
+ex_yank.lo: $(visrcdir)/ex/ex_yank.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_yank.lo `test -f '$(visrcdir)/ex/ex_yank.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_yank.c
+
+ex_z.lo: $(visrcdir)/ex/ex_z.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ex_z.lo `test -f '$(visrcdir)/ex/ex_z.c' || echo '$(srcdir)/'`$(visrcdir)/ex/ex_z.c
+
+exf.lo: $(visrcdir)/common/exf.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exf.lo `test -f '$(visrcdir)/common/exf.c' || echo '$(srcdir)/'`$(visrcdir)/common/exf.c
+
+getc.lo: $(visrcdir)/vi/getc.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getc.lo `test -f '$(visrcdir)/vi/getc.c' || echo '$(srcdir)/'`$(visrcdir)/vi/getc.c
+
+gs.lo: $(visrcdir)/common/gs.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gs.lo `test -f '$(visrcdir)/common/gs.c' || echo '$(srcdir)/'`$(visrcdir)/common/gs.c
+
+key.lo: $(visrcdir)/common/key.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o key.lo `test -f '$(visrcdir)/common/key.c' || echo '$(srcdir)/'`$(visrcdir)/common/key.c
+
+db.lo: $(visrcdir)/common/db.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o db.lo `test -f '$(visrcdir)/common/db.c' || echo '$(srcdir)/'`$(visrcdir)/common/db.c
+
+main.lo: $(visrcdir)/common/main.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.lo `test -f '$(visrcdir)/common/main.c' || echo '$(srcdir)/'`$(visrcdir)/common/main.c
+
+mark.lo: $(visrcdir)/common/mark.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mark.lo `test -f '$(visrcdir)/common/mark.c' || echo '$(srcdir)/'`$(visrcdir)/common/mark.c
+
+msg.lo: $(visrcdir)/common/msg.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msg.lo `test -f '$(visrcdir)/common/msg.c' || echo '$(srcdir)/'`$(visrcdir)/common/msg.c
+
+options.lo: $(visrcdir)/common/options.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o options.lo `test -f '$(visrcdir)/common/options.c' || echo '$(srcdir)/'`$(visrcdir)/common/options.c
+
+options_f.lo: $(visrcdir)/common/options_f.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o options_f.lo `test -f '$(visrcdir)/common/options_f.c' || echo '$(srcdir)/'`$(visrcdir)/common/options_f.c
+
+put.lo: $(visrcdir)/common/put.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o put.lo `test -f '$(visrcdir)/common/put.c' || echo '$(srcdir)/'`$(visrcdir)/common/put.c
+
+recover.lo: $(visrcdir)/common/recover.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o recover.lo `test -f '$(visrcdir)/common/recover.c' || echo '$(srcdir)/'`$(visrcdir)/common/recover.c
+
+screen.lo: $(visrcdir)/common/screen.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o screen.lo `test -f '$(visrcdir)/common/screen.c' || echo '$(srcdir)/'`$(visrcdir)/common/screen.c
+
+search.lo: $(visrcdir)/common/search.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o search.lo `test -f '$(visrcdir)/common/search.c' || echo '$(srcdir)/'`$(visrcdir)/common/search.c
+
+seq.lo: $(visrcdir)/common/seq.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o seq.lo `test -f '$(visrcdir)/common/seq.c' || echo '$(srcdir)/'`$(visrcdir)/common/seq.c
+
+trace.lo: $(visrcdir)/common/trace.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o trace.lo `test -f '$(visrcdir)/common/trace.c' || echo '$(srcdir)/'`$(visrcdir)/common/trace.c
+
+util.lo: $(visrcdir)/common/util.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.lo `test -f '$(visrcdir)/common/util.c' || echo '$(srcdir)/'`$(visrcdir)/common/util.c
+
+util2.lo: $(visrcdir)/common/util2.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util2.lo `test -f '$(visrcdir)/common/util2.c' || echo '$(srcdir)/'`$(visrcdir)/common/util2.c
+
+v_at.lo: $(visrcdir)/vi/v_at.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_at.lo `test -f '$(visrcdir)/vi/v_at.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_at.c
+
+v_ch.lo: $(visrcdir)/vi/v_ch.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_ch.lo `test -f '$(visrcdir)/vi/v_ch.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_ch.c
+
+v_cmd.lo: $(visrcdir)/vi/v_cmd.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_cmd.lo `test -f '$(visrcdir)/vi/v_cmd.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_cmd.c
+
+v_delete.lo: $(visrcdir)/vi/v_delete.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_delete.lo `test -f '$(visrcdir)/vi/v_delete.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_delete.c
+
+v_event.lo: $(visrcdir)/vi/v_event.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_event.lo `test -f '$(visrcdir)/vi/v_event.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_event.c
+
+v_ex.lo: $(visrcdir)/vi/v_ex.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_ex.lo `test -f '$(visrcdir)/vi/v_ex.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_ex.c
+
+v_increment.lo: $(visrcdir)/vi/v_increment.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_increment.lo `test -f '$(visrcdir)/vi/v_increment.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_increment.c
+
+v_init.lo: $(visrcdir)/vi/v_init.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_init.lo `test -f '$(visrcdir)/vi/v_init.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_init.c
+
+v_itxt.lo: $(visrcdir)/vi/v_itxt.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_itxt.lo `test -f '$(visrcdir)/vi/v_itxt.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_itxt.c
+
+v_left.lo: $(visrcdir)/vi/v_left.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_left.lo `test -f '$(visrcdir)/vi/v_left.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_left.c
+
+v_mark.lo: $(visrcdir)/vi/v_mark.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_mark.lo `test -f '$(visrcdir)/vi/v_mark.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_mark.c
+
+v_match.lo: $(visrcdir)/vi/v_match.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_match.lo `test -f '$(visrcdir)/vi/v_match.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_match.c
+
+v_paragraph.lo: $(visrcdir)/vi/v_paragraph.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_paragraph.lo `test -f '$(visrcdir)/vi/v_paragraph.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_paragraph.c
+
+v_put.lo: $(visrcdir)/vi/v_put.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_put.lo `test -f '$(visrcdir)/vi/v_put.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_put.c
+
+v_redraw.lo: $(visrcdir)/vi/v_redraw.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_redraw.lo `test -f '$(visrcdir)/vi/v_redraw.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_redraw.c
+
+v_replace.lo: $(visrcdir)/vi/v_replace.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_replace.lo `test -f '$(visrcdir)/vi/v_replace.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_replace.c
+
+v_right.lo: $(visrcdir)/vi/v_right.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_right.lo `test -f '$(visrcdir)/vi/v_right.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_right.c
+
+v_screen.lo: $(visrcdir)/vi/v_screen.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_screen.lo `test -f '$(visrcdir)/vi/v_screen.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_screen.c
+
+v_scroll.lo: $(visrcdir)/vi/v_scroll.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_scroll.lo `test -f '$(visrcdir)/vi/v_scroll.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_scroll.c
+
+v_search.lo: $(visrcdir)/vi/v_search.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_search.lo `test -f '$(visrcdir)/vi/v_search.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_search.c
+
+v_section.lo: $(visrcdir)/vi/v_section.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_section.lo `test -f '$(visrcdir)/vi/v_section.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_section.c
+
+v_sentence.lo: $(visrcdir)/vi/v_sentence.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_sentence.lo `test -f '$(visrcdir)/vi/v_sentence.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_sentence.c
+
+v_status.lo: $(visrcdir)/vi/v_status.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_status.lo `test -f '$(visrcdir)/vi/v_status.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_status.c
+
+v_txt.lo: $(visrcdir)/vi/v_txt.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_txt.lo `test -f '$(visrcdir)/vi/v_txt.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_txt.c
+
+v_ulcase.lo: $(visrcdir)/vi/v_ulcase.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_ulcase.lo `test -f '$(visrcdir)/vi/v_ulcase.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_ulcase.c
+
+v_undo.lo: $(visrcdir)/vi/v_undo.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_undo.lo `test -f '$(visrcdir)/vi/v_undo.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_undo.c
+
+v_util.lo: $(visrcdir)/vi/v_util.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_util.lo `test -f '$(visrcdir)/vi/v_util.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_util.c
+
+v_word.lo: $(visrcdir)/vi/v_word.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_word.lo `test -f '$(visrcdir)/vi/v_word.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_word.c
+
+v_xchar.lo: $(visrcdir)/vi/v_xchar.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_xchar.lo `test -f '$(visrcdir)/vi/v_xchar.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_xchar.c
+
+v_yank.lo: $(visrcdir)/vi/v_yank.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_yank.lo `test -f '$(visrcdir)/vi/v_yank.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_yank.c
+
+v_z.lo: $(visrcdir)/vi/v_z.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_z.lo `test -f '$(visrcdir)/vi/v_z.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_z.c
+
+v_zexit.lo: $(visrcdir)/vi/v_zexit.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o v_zexit.lo `test -f '$(visrcdir)/vi/v_zexit.c' || echo '$(srcdir)/'`$(visrcdir)/vi/v_zexit.c
+
+vi.lo: $(visrcdir)/vi/vi.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi.lo `test -f '$(visrcdir)/vi/vi.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vi.c
+
+vs_line.lo: $(visrcdir)/vi/vs_line.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vs_line.lo `test -f '$(visrcdir)/vi/vs_line.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vs_line.c
+
+vs_msg.lo: $(visrcdir)/vi/vs_msg.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vs_msg.lo `test -f '$(visrcdir)/vi/vs_msg.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vs_msg.c
+
+vs_refresh.lo: $(visrcdir)/vi/vs_refresh.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vs_refresh.lo `test -f '$(visrcdir)/vi/vs_refresh.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vs_refresh.c
+
+vs_relative.lo: $(visrcdir)/vi/vs_relative.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vs_relative.lo `test -f '$(visrcdir)/vi/vs_relative.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vs_relative.c
+
+vs_smap.lo: $(visrcdir)/vi/vs_smap.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vs_smap.lo `test -f '$(visrcdir)/vi/vs_smap.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vs_smap.c
+
+vs_split.lo: $(visrcdir)/vi/vs_split.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vs_split.lo `test -f '$(visrcdir)/vi/vs_split.c' || echo '$(srcdir)/'`$(visrcdir)/vi/vs_split.c
+
+regcomp.lo: $(visrcdir)/regex/regcomp.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regcomp.lo `test -f '$(visrcdir)/regex/regcomp.c' || echo '$(srcdir)/'`$(visrcdir)/regex/regcomp.c
+
+regerror.lo: $(visrcdir)/regex/regerror.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regerror.lo `test -f '$(visrcdir)/regex/regerror.c' || echo '$(srcdir)/'`$(visrcdir)/regex/regerror.c
+
+regexec.lo: $(visrcdir)/regex/regexec.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regexec.lo `test -f '$(visrcdir)/regex/regexec.c' || echo '$(srcdir)/'`$(visrcdir)/regex/regexec.c
+
+regfree.lo: $(visrcdir)/regex/regfree.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regfree.lo `test -f '$(visrcdir)/regex/regfree.c' || echo '$(srcdir)/'`$(visrcdir)/regex/regfree.c
+
+dldb.lo: $(visrcdir)/common/dldb.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dldb.lo `test -f '$(visrcdir)/common/dldb.c' || echo '$(srcdir)/'`$(visrcdir)/common/dldb.c
+
+log.lo: $(visrcdir)/common/log.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log.lo `test -f '$(visrcdir)/common/log.c' || echo '$(srcdir)/'`$(visrcdir)/common/log.c
+
+log4.lo: $(visrcdir)/common/log4.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log4.lo `test -f '$(visrcdir)/common/log4.c' || echo '$(srcdir)/'`$(visrcdir)/common/log4.c
+
+bsearch.lo: $(visrcdir)/clib/bsearch.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bsearch.lo `test -f '$(visrcdir)/clib/bsearch.c' || echo '$(srcdir)/'`$(visrcdir)/clib/bsearch.c
+
+env.lo: $(visrcdir)/clib/env.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o env.lo `test -f '$(visrcdir)/clib/env.c' || echo '$(srcdir)/'`$(visrcdir)/clib/env.c
+
+gethostname.lo: $(visrcdir)/clib/gethostname.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gethostname.lo `test -f '$(visrcdir)/clib/gethostname.c' || echo '$(srcdir)/'`$(visrcdir)/clib/gethostname.c
+
+iswblank.lo: $(visrcdir)/clib/iswblank.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iswblank.lo `test -f '$(visrcdir)/clib/iswblank.c' || echo '$(srcdir)/'`$(visrcdir)/clib/iswblank.c
+
+memchr.lo: $(visrcdir)/clib/memchr.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o memchr.lo `test -f '$(visrcdir)/clib/memchr.c' || echo '$(srcdir)/'`$(visrcdir)/clib/memchr.c
+
+memset.lo: $(visrcdir)/clib/memset.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o memset.lo `test -f '$(visrcdir)/clib/memset.c' || echo '$(srcdir)/'`$(visrcdir)/clib/memset.c
+
+mkstemp.lo: $(visrcdir)/clib/mkstemp.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkstemp.lo `test -f '$(visrcdir)/clib/mkstemp.c' || echo '$(srcdir)/'`$(visrcdir)/clib/mkstemp.c
+
+mmap.lo: $(visrcdir)/clib/mmap.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmap.lo `test -f '$(visrcdir)/clib/mmap.c' || echo '$(srcdir)/'`$(visrcdir)/clib/mmap.c
+
+snprintf.lo: $(visrcdir)/clib/snprintf.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o snprintf.lo `test -f '$(visrcdir)/clib/snprintf.c' || echo '$(srcdir)/'`$(visrcdir)/clib/snprintf.c
+
+strdup.lo: $(visrcdir)/clib/strdup.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strdup.lo `test -f '$(visrcdir)/clib/strdup.c' || echo '$(srcdir)/'`$(visrcdir)/clib/strdup.c
+
+strpbrk.lo: $(visrcdir)/clib/strpbrk.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strpbrk.lo `test -f '$(visrcdir)/clib/strpbrk.c' || echo '$(srcdir)/'`$(visrcdir)/clib/strpbrk.c
+
+strsep.lo: $(visrcdir)/clib/strsep.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strsep.lo `test -f '$(visrcdir)/clib/strsep.c' || echo '$(srcdir)/'`$(visrcdir)/clib/strsep.c
+
+strtol.lo: $(visrcdir)/clib/strtol.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strtol.lo `test -f '$(visrcdir)/clib/strtol.c' || echo '$(srcdir)/'`$(visrcdir)/clib/strtol.c
+
+strtoul.lo: $(visrcdir)/clib/strtoul.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strtoul.lo `test -f '$(visrcdir)/clib/strtoul.c' || echo '$(srcdir)/'`$(visrcdir)/clib/strtoul.c
+
+vsnprintf.lo: $(visrcdir)/clib/vsnprintf.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vsnprintf.lo `test -f '$(visrcdir)/clib/vsnprintf.c' || echo '$(srcdir)/'`$(visrcdir)/clib/vsnprintf.c
+
+pthread.lo: $(visrcdir)/common/pthread.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pthread.lo `test -f '$(visrcdir)/common/pthread.c' || echo '$(srcdir)/'`$(visrcdir)/common/pthread.c
+
+vi_auto.lo: $(visrcdir)/common/vi_auto.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi_auto.lo `test -f '$(visrcdir)/common/vi_auto.c' || echo '$(srcdir)/'`$(visrcdir)/common/vi_auto.c
+
+vi_rec.lo: $(visrcdir)/common/vi_rec.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi_rec.lo `test -f '$(visrcdir)/common/vi_rec.c' || echo '$(srcdir)/'`$(visrcdir)/common/vi_rec.c
+
+perlsfio.lo: $(visrcdir)/perl_api/perlsfio.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o perlsfio.lo `test -f '$(visrcdir)/perl_api/perlsfio.c' || echo '$(srcdir)/'`$(visrcdir)/perl_api/perlsfio.c
+
+tcl.lo: $(visrcdir)/tcl_api/tcl.c
+       $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tcl.lo `test -f '$(visrcdir)/tcl_api/tcl.c' || echo '$(srcdir)/'`$(visrcdir)/tcl_api/tcl.c
+
+vi-cl_bsd.o: $(visrcdir)/cl/cl_bsd.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_bsd.o `test -f '$(visrcdir)/cl/cl_bsd.c' || echo '$(srcdir)/'`$(visrcdir)/cl/cl_bsd.c
+
+vi-cl_bsd.obj: $(visrcdir)/cl/cl_bsd.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_bsd.obj `if test -f '$(visrcdir)/cl/cl_bsd.c'; then $(CYGPATH_W) '$(visrcdir)/cl/cl_bsd.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/cl/cl_bsd.c'; fi`
+
+vi-cl_funcs.o: $(visrcdir)/cl/cl_funcs.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_funcs.o `test -f '$(visrcdir)/cl/cl_funcs.c' || echo '$(srcdir)/'`$(visrcdir)/cl/cl_funcs.c
+
+vi-cl_funcs.obj: $(visrcdir)/cl/cl_funcs.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_funcs.obj `if test -f '$(visrcdir)/cl/cl_funcs.c'; then $(CYGPATH_W) '$(visrcdir)/cl/cl_funcs.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/cl/cl_funcs.c'; fi`
+
+vi-cl_main.o: $(visrcdir)/cl/cl_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_main.o `test -f '$(visrcdir)/cl/cl_main.c' || echo '$(srcdir)/'`$(visrcdir)/cl/cl_main.c
+
+vi-cl_main.obj: $(visrcdir)/cl/cl_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_main.obj `if test -f '$(visrcdir)/cl/cl_main.c'; then $(CYGPATH_W) '$(visrcdir)/cl/cl_main.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/cl/cl_main.c'; fi`
+
+vi-cl_read.o: $(visrcdir)/cl/cl_read.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_read.o `test -f '$(visrcdir)/cl/cl_read.c' || echo '$(srcdir)/'`$(visrcdir)/cl/cl_read.c
+
+vi-cl_read.obj: $(visrcdir)/cl/cl_read.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_read.obj `if test -f '$(visrcdir)/cl/cl_read.c'; then $(CYGPATH_W) '$(visrcdir)/cl/cl_read.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/cl/cl_read.c'; fi`
+
+vi-cl_screen.o: $(visrcdir)/cl/cl_screen.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_screen.o `test -f '$(visrcdir)/cl/cl_screen.c' || echo '$(srcdir)/'`$(visrcdir)/cl/cl_screen.c
+
+vi-cl_screen.obj: $(visrcdir)/cl/cl_screen.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_screen.obj `if test -f '$(visrcdir)/cl/cl_screen.c'; then $(CYGPATH_W) '$(visrcdir)/cl/cl_screen.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/cl/cl_screen.c'; fi`
+
+vi-cl_term.o: $(visrcdir)/cl/cl_term.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_term.o `test -f '$(visrcdir)/cl/cl_term.c' || echo '$(srcdir)/'`$(visrcdir)/cl/cl_term.c
+
+vi-cl_term.obj: $(visrcdir)/cl/cl_term.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-cl_term.obj `if test -f '$(visrcdir)/cl/cl_term.c'; then $(CYGPATH_W) '$(visrcdir)/cl/cl_term.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/cl/cl_term.c'; fi`
+
+vi-nothread.o: $(visrcdir)/common/nothread.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-nothread.o `test -f '$(visrcdir)/common/nothread.c' || echo '$(srcdir)/'`$(visrcdir)/common/nothread.c
+
+vi-nothread.obj: $(visrcdir)/common/nothread.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vi_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vi-nothread.obj `if test -f '$(visrcdir)/common/nothread.c'; then $(CYGPATH_W) '$(visrcdir)/common/nothread.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/common/nothread.c'; fi`
+
+vi_gtk-util2.o: $(visrcdir)/common/util2.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-util2.o `test -f '$(visrcdir)/common/util2.c' || echo '$(srcdir)/'`$(visrcdir)/common/util2.c
+
+vi_gtk-util2.obj: $(visrcdir)/common/util2.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-util2.obj `if test -f '$(visrcdir)/common/util2.c'; then $(CYGPATH_W) '$(visrcdir)/common/util2.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/common/util2.c'; fi`
+
+vi_gtk-ip_run.o: $(visrcdir)/ipc/ip_run.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ip_run.o `test -f '$(visrcdir)/ipc/ip_run.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_run.c
+
+vi_gtk-ip_run.obj: $(visrcdir)/ipc/ip_run.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ip_run.obj `if test -f '$(visrcdir)/ipc/ip_run.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_run.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_run.c'; fi`
+
+vi_gtk-ip_send.o: $(visrcdir)/ipc/ip_send.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ip_send.o `test -f '$(visrcdir)/ipc/ip_send.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_send.c
+
+vi_gtk-ip_send.obj: $(visrcdir)/ipc/ip_send.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ip_send.obj `if test -f '$(visrcdir)/ipc/ip_send.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_send.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_send.c'; fi`
+
+vi_gtk-ip_trans.o: $(visrcdir)/ipc/ip_trans.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ip_trans.o `test -f '$(visrcdir)/ipc/ip_trans.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_trans.c
+
+vi_gtk-ip_trans.obj: $(visrcdir)/ipc/ip_trans.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ip_trans.obj `if test -f '$(visrcdir)/ipc/ip_trans.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_trans.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_trans.c'; fi`
+
+vi_gtk-ipc_cmd.o: $(visrcdir)/ipc/ipc_cmd.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ipc_cmd.o `test -f '$(visrcdir)/ipc/ipc_cmd.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ipc_cmd.c
+
+vi_gtk-ipc_cmd.obj: $(visrcdir)/ipc/ipc_cmd.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ipc_cmd.obj `if test -f '$(visrcdir)/ipc/ipc_cmd.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ipc_cmd.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ipc_cmd.c'; fi`
+
+vi_gtk-ipc_method.o: $(visrcdir)/ipc/ipc_method.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ipc_method.o `test -f '$(visrcdir)/ipc/ipc_method.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ipc_method.c
+
+vi_gtk-ipc_method.obj: $(visrcdir)/ipc/ipc_method.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-ipc_method.obj `if test -f '$(visrcdir)/ipc/ipc_method.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ipc_method.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ipc_method.c'; fi`
+
+vi_gtk-gtk_main.o: $(visrcdir)/gtk/gtk_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtk_main.o `test -f '$(visrcdir)/gtk/gtk_main.c' || echo '$(srcdir)/'`$(visrcdir)/gtk/gtk_main.c
+
+vi_gtk-gtk_main.obj: $(visrcdir)/gtk/gtk_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtk_main.obj `if test -f '$(visrcdir)/gtk/gtk_main.c'; then $(CYGPATH_W) '$(visrcdir)/gtk/gtk_main.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/gtk/gtk_main.c'; fi`
+
+vi_gtk-gtkvi.o: $(visrcdir)/gtk/gtkvi.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtkvi.o `test -f '$(visrcdir)/gtk/gtkvi.c' || echo '$(srcdir)/'`$(visrcdir)/gtk/gtkvi.c
+
+vi_gtk-gtkvi.obj: $(visrcdir)/gtk/gtkvi.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtkvi.obj `if test -f '$(visrcdir)/gtk/gtkvi.c'; then $(CYGPATH_W) '$(visrcdir)/gtk/gtkvi.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/gtk/gtkvi.c'; fi`
+
+vi_gtk-gtkviscreen.o: $(visrcdir)/gtk/gtkviscreen.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtkviscreen.o `test -f '$(visrcdir)/gtk/gtkviscreen.c' || echo '$(srcdir)/'`$(visrcdir)/gtk/gtkviscreen.c
+
+vi_gtk-gtkviscreen.obj: $(visrcdir)/gtk/gtkviscreen.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtkviscreen.obj `if test -f '$(visrcdir)/gtk/gtkviscreen.c'; then $(CYGPATH_W) '$(visrcdir)/gtk/gtkviscreen.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/gtk/gtkviscreen.c'; fi`
+
+vi_gtk-gtkviwindow.o: $(visrcdir)/gtk/gtkviwindow.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtkviwindow.o `test -f '$(visrcdir)/gtk/gtkviwindow.c' || echo '$(srcdir)/'`$(visrcdir)/gtk/gtkviwindow.c
+
+vi_gtk-gtkviwindow.obj: $(visrcdir)/gtk/gtkviwindow.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_gtk_CFLAGS) $(CFLAGS) -c -o vi_gtk-gtkviwindow.obj `if test -f '$(visrcdir)/gtk/gtkviwindow.c'; then $(CYGPATH_W) '$(visrcdir)/gtk/gtkviwindow.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/gtk/gtkviwindow.c'; fi`
+
+ip_funcs.o: $(visrcdir)/ip/ip_funcs.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_funcs.o `test -f '$(visrcdir)/ip/ip_funcs.c' || echo '$(srcdir)/'`$(visrcdir)/ip/ip_funcs.c
+
+ip_funcs.obj: $(visrcdir)/ip/ip_funcs.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_funcs.obj `if test -f '$(visrcdir)/ip/ip_funcs.c'; then $(CYGPATH_W) '$(visrcdir)/ip/ip_funcs.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ip/ip_funcs.c'; fi`
+
+ip_main.o: $(visrcdir)/ip/ip_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_main.o `test -f '$(visrcdir)/ip/ip_main.c' || echo '$(srcdir)/'`$(visrcdir)/ip/ip_main.c
+
+ip_main.obj: $(visrcdir)/ip/ip_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_main.obj `if test -f '$(visrcdir)/ip/ip_main.c'; then $(CYGPATH_W) '$(visrcdir)/ip/ip_main.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ip/ip_main.c'; fi`
+
+ip_read.o: $(visrcdir)/ip/ip_read.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_read.o `test -f '$(visrcdir)/ip/ip_read.c' || echo '$(srcdir)/'`$(visrcdir)/ip/ip_read.c
+
+ip_read.obj: $(visrcdir)/ip/ip_read.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_read.obj `if test -f '$(visrcdir)/ip/ip_read.c'; then $(CYGPATH_W) '$(visrcdir)/ip/ip_read.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ip/ip_read.c'; fi`
+
+ip_screen.o: $(visrcdir)/ip/ip_screen.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_screen.o `test -f '$(visrcdir)/ip/ip_screen.c' || echo '$(srcdir)/'`$(visrcdir)/ip/ip_screen.c
+
+ip_screen.obj: $(visrcdir)/ip/ip_screen.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_screen.obj `if test -f '$(visrcdir)/ip/ip_screen.c'; then $(CYGPATH_W) '$(visrcdir)/ip/ip_screen.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ip/ip_screen.c'; fi`
+
+ip_send.o: $(visrcdir)/ipc/ip_send.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_send.o `test -f '$(visrcdir)/ipc/ip_send.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_send.c
+
+ip_send.obj: $(visrcdir)/ipc/ip_send.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_send.obj `if test -f '$(visrcdir)/ipc/ip_send.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_send.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_send.c'; fi`
+
+ip_term.o: $(visrcdir)/ip/ip_term.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_term.o `test -f '$(visrcdir)/ip/ip_term.c' || echo '$(srcdir)/'`$(visrcdir)/ip/ip_term.c
+
+ip_term.obj: $(visrcdir)/ip/ip_term.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ip_term.obj `if test -f '$(visrcdir)/ip/ip_term.c'; then $(CYGPATH_W) '$(visrcdir)/ip/ip_term.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ip/ip_term.c'; fi`
+
+vi_motif-ip_run.o: $(visrcdir)/ipc/ip_run.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ip_run.o `test -f '$(visrcdir)/ipc/ip_run.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_run.c
+
+vi_motif-ip_run.obj: $(visrcdir)/ipc/ip_run.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ip_run.obj `if test -f '$(visrcdir)/ipc/ip_run.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_run.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_run.c'; fi`
+
+vi_motif-ip_send.o: $(visrcdir)/ipc/ip_send.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ip_send.o `test -f '$(visrcdir)/ipc/ip_send.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_send.c
+
+vi_motif-ip_send.obj: $(visrcdir)/ipc/ip_send.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ip_send.obj `if test -f '$(visrcdir)/ipc/ip_send.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_send.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_send.c'; fi`
+
+vi_motif-ip_trans.o: $(visrcdir)/ipc/ip_trans.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ip_trans.o `test -f '$(visrcdir)/ipc/ip_trans.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ip_trans.c
+
+vi_motif-ip_trans.obj: $(visrcdir)/ipc/ip_trans.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ip_trans.obj `if test -f '$(visrcdir)/ipc/ip_trans.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ip_trans.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ip_trans.c'; fi`
+
+vi_motif-ipc_cmd.o: $(visrcdir)/ipc/ipc_cmd.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ipc_cmd.o `test -f '$(visrcdir)/ipc/ipc_cmd.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ipc_cmd.c
+
+vi_motif-ipc_cmd.obj: $(visrcdir)/ipc/ipc_cmd.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ipc_cmd.obj `if test -f '$(visrcdir)/ipc/ipc_cmd.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ipc_cmd.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ipc_cmd.c'; fi`
+
+vi_motif-ipc_method.o: $(visrcdir)/ipc/ipc_method.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ipc_method.o `test -f '$(visrcdir)/ipc/ipc_method.c' || echo '$(srcdir)/'`$(visrcdir)/ipc/ipc_method.c
+
+vi_motif-ipc_method.obj: $(visrcdir)/ipc/ipc_method.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-ipc_method.obj `if test -f '$(visrcdir)/ipc/ipc_method.c'; then $(CYGPATH_W) '$(visrcdir)/ipc/ipc_method.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/ipc/ipc_method.c'; fi`
+
+vi_motif-m_main.o: $(visrcdir)/motif/m_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_main.o `test -f '$(visrcdir)/motif/m_main.c' || echo '$(srcdir)/'`$(visrcdir)/motif/m_main.c
+
+vi_motif-m_main.obj: $(visrcdir)/motif/m_main.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_main.obj `if test -f '$(visrcdir)/motif/m_main.c'; then $(CYGPATH_W) '$(visrcdir)/motif/m_main.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif/m_main.c'; fi`
+
+vi_motif-m_cde.o: $(visrcdir)/motif/m_cde.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_cde.o `test -f '$(visrcdir)/motif/m_cde.c' || echo '$(srcdir)/'`$(visrcdir)/motif/m_cde.c
+
+vi_motif-m_cde.obj: $(visrcdir)/motif/m_cde.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_cde.obj `if test -f '$(visrcdir)/motif/m_cde.c'; then $(CYGPATH_W) '$(visrcdir)/motif/m_cde.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif/m_cde.c'; fi`
+
+vi_motif-trace.o: $(visrcdir)/common/trace.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-trace.o `test -f '$(visrcdir)/common/trace.c' || echo '$(srcdir)/'`$(visrcdir)/common/trace.c
+
+vi_motif-trace.obj: $(visrcdir)/common/trace.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-trace.obj `if test -f '$(visrcdir)/common/trace.c'; then $(CYGPATH_W) '$(visrcdir)/common/trace.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/common/trace.c'; fi`
+
+vi_motif-m_copypaste.o: $(visrcdir)/motif_l/m_copypaste.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_copypaste.o `test -f '$(visrcdir)/motif_l/m_copypaste.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_copypaste.c
+
+vi_motif-m_copypaste.obj: $(visrcdir)/motif_l/m_copypaste.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_copypaste.obj `if test -f '$(visrcdir)/motif_l/m_copypaste.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_copypaste.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_copypaste.c'; fi`
+
+vi_motif-m_func.o: $(visrcdir)/motif_l/m_func.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_func.o `test -f '$(visrcdir)/motif_l/m_func.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_func.c
+
+vi_motif-m_func.obj: $(visrcdir)/motif_l/m_func.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_func.obj `if test -f '$(visrcdir)/motif_l/m_func.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_func.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_func.c'; fi`
+
+vi_motif-m_menu.o: $(visrcdir)/motif_l/m_menu.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_menu.o `test -f '$(visrcdir)/motif_l/m_menu.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_menu.c
+
+vi_motif-m_menu.obj: $(visrcdir)/motif_l/m_menu.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_menu.obj `if test -f '$(visrcdir)/motif_l/m_menu.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_menu.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_menu.c'; fi`
+
+vi_motif-m_options.o: $(visrcdir)/motif_l/m_options.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_options.o `test -f '$(visrcdir)/motif_l/m_options.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_options.c
+
+vi_motif-m_options.obj: $(visrcdir)/motif_l/m_options.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_options.obj `if test -f '$(visrcdir)/motif_l/m_options.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_options.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_options.c'; fi`
+
+vi_motif-m_prompt.o: $(visrcdir)/motif_l/m_prompt.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_prompt.o `test -f '$(visrcdir)/motif_l/m_prompt.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_prompt.c
+
+vi_motif-m_prompt.obj: $(visrcdir)/motif_l/m_prompt.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_prompt.obj `if test -f '$(visrcdir)/motif_l/m_prompt.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_prompt.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_prompt.c'; fi`
+
+vi_motif-m_ruler.o: $(visrcdir)/motif_l/m_ruler.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_ruler.o `test -f '$(visrcdir)/motif_l/m_ruler.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_ruler.c
+
+vi_motif-m_ruler.obj: $(visrcdir)/motif_l/m_ruler.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_ruler.obj `if test -f '$(visrcdir)/motif_l/m_ruler.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_ruler.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_ruler.c'; fi`
+
+vi_motif-m_search.o: $(visrcdir)/motif_l/m_search.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_search.o `test -f '$(visrcdir)/motif_l/m_search.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_search.c
+
+vi_motif-m_search.obj: $(visrcdir)/motif_l/m_search.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_search.obj `if test -f '$(visrcdir)/motif_l/m_search.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_search.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_search.c'; fi`
+
+vi_motif-m_tags.o: $(visrcdir)/motif_l/m_tags.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_tags.o `test -f '$(visrcdir)/motif_l/m_tags.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_tags.c
+
+vi_motif-m_tags.obj: $(visrcdir)/motif_l/m_tags.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_tags.obj `if test -f '$(visrcdir)/motif_l/m_tags.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_tags.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_tags.c'; fi`
+
+vi_motif-m_util.o: $(visrcdir)/motif_l/m_util.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_util.o `test -f '$(visrcdir)/motif_l/m_util.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_util.c
+
+vi_motif-m_util.obj: $(visrcdir)/motif_l/m_util.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_util.obj `if test -f '$(visrcdir)/motif_l/m_util.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_util.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_util.c'; fi`
+
+vi_motif-m_vi.o: $(visrcdir)/motif_l/m_vi.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_vi.o `test -f '$(visrcdir)/motif_l/m_vi.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/m_vi.c
+
+vi_motif-m_vi.obj: $(visrcdir)/motif_l/m_vi.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-m_vi.obj `if test -f '$(visrcdir)/motif_l/m_vi.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/m_vi.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/m_vi.c'; fi`
+
+vi_motif-xtabbed.o: $(visrcdir)/motif_l/xtabbed.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-xtabbed.o `test -f '$(visrcdir)/motif_l/xtabbed.c' || echo '$(srcdir)/'`$(visrcdir)/motif_l/xtabbed.c
+
+vi_motif-xtabbed.obj: $(visrcdir)/motif_l/xtabbed.c
+       $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vi_motif_CFLAGS) $(CFLAGS) -c -o vi_motif-xtabbed.obj `if test -f '$(visrcdir)/motif_l/xtabbed.c'; then $(CYGPATH_W) '$(visrcdir)/motif_l/xtabbed.c'; else $(CYGPATH_W) '$(srcdir)/$(visrcdir)/motif_l/xtabbed.c'; fi`
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       test -d $(distdir) || mkdir $(distdir)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+       $(am__remove_distdir)
+
+dist-tarZ: distdir
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__remove_distdir)
+
+dist-shar: distdir
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+dist dist-all: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/_build
+       mkdir $(distdir)/_inst
+       chmod a-w $(distdir)
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && cd $(distdir)/_build \
+         && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+       $(am__remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+       @cd $(distuninstallcheck_dir) \
+       && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) config.h
+install-binPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+       clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS install-exec-local \
+       install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
+       uninstall-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+       clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+       clean-libtool ctags dist dist-all dist-bzip2 dist-gzip \
+       dist-shar dist-tarZ dist-zip distcheck distclean \
+       distclean-compile distclean-generic distclean-hdr \
+       distclean-libtool distclean-tags distcleancheck distdir \
+       distuninstallcheck dvi dvi-am html html-am info info-am \
+       install install-am install-binPROGRAMS install-data \
+       install-data-am install-data-local install-dvi install-dvi-am \
+       install-exec install-exec-am install-exec-local install-html \
+       install-html-am install-info install-info-am \
+       install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags uninstall uninstall-am uninstall-binPROGRAMS \
+       uninstall-libLTLIBRARIES uninstall-local
+
+
+perl.c: $(visrcdir)/perl_api/perl.xs $(visrcdir)/perl_api/typemap
+       echo "#define _PATH_PERLSCRIPTS \"$(datadir)/vi/perl\"" > $@
+       $(PERL) -e 'unless ($$] >= 5.005) {' \
+               -e   'for (qw(incgv sv_undef errgv na)) {' \
+               -e     'print "#define PL_$$_ $$_\n" }} ' >> $@
+       $(PERL) $(PERLLIB)/ExtUtils/xsubpp -typemap \
+           $(PERLLIB)/ExtUtils/typemap $(visrcdir)/perl_api/perl.xs >> $@
+       ($(PERL) -ne 'print "sub $$1 {\$$curscr->$$1(\@_)}\n"' \
+                 -e   'if /newXS\("VI::([^\":]*)"/;' $@ ; echo "1;") > VI.pm
+perlxsi.c:
+       perl -MExtUtils::Embed -e xsinit -- -std VI
+
+install-exec-local:
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo ex | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo view | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(ln) \
+               `echo vi | sed '$(transform)'` `echo ex | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(ln) \
+               `echo vi | sed '$(transform)'` `echo view | sed '$(transform)'`
+
+install-data-local: install_common
+       @[ -d $(DESTDIR)$(mandir) ] || \
+           ($(mkdir) $(DESTDIR)$(mandir) && \
+            $(chmod) $(dmode) $(DESTDIR)$(mandir))
+       @[ -d $(DESTDIR)$(mandir)/cat1 ] || \
+           ($(mkdir) $(DESTDIR)$(mandir)/cat1 && \
+            $(chmod) $(dmode) $(DESTDIR)$(mandir)/cat1)
+       @echo "Installing man pages: $(DESTDIR)$(mandir) ..."
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo vi.0 | sed '$(transform)'`
+       @$(cp) $(visrcdir)/docs/vi.man/vi.0 \
+           $(DESTDIR)$(mandir)/cat1/`echo vi.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(chmod) $(fmode) `echo vi.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo ex.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo view.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && $(ln) \
+           `echo vi.0 | sed '$(transform)'` `echo ex.0 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/cat1 && $(ln) \
+           `echo vi.0 | sed '$(transform)'` `echo view.0 | sed '$(transform)'`
+       @[ -d $(DESTDIR)$(mandir)/man1 ] || \
+           ($(mkdir) $(DESTDIR)$(mandir)/man1 && \
+            $(chmod) $(dmode) $(DESTDIR)$(mandir)/man1)
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo vi.1 | sed '$(transform)'`
+       @$(cp) $(visrcdir)/docs/vi.man/vi.1 \
+           $(DESTDIR)$(mandir)/man1/`echo vi.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(chmod) $(fmode) `echo vi.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo ex.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo view.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && $(ln) \
+           `echo vi.1 | sed '$(transform)'` `echo ex.1 | sed '$(transform)'`
+       @cd $(DESTDIR)$(mandir)/man1 && $(ln) \
+           `echo vi.1 | sed '$(transform)'` `echo view.1 | sed '$(transform)'`
+install_common:
+       @[ -f $(chmod) ] || (echo 'chmod not found.'; exit 1)
+       @[ -f $(cp) ] || (echo 'cp not found.'; exit 1)
+       @[ -f $(ln) ] || (echo 'ln not found.'; exit 1)
+       @[ -f $(mkdir) ] || (echo 'mkdir not found.'; exit 1)
+       @[ -f $(rm) ] || (echo 'rm not found.'; exit 1)
+       @[ -d $(DESTDIR)$(prefix) ] || \
+           ($(mkdir) $(DESTDIR)$(prefix) && \
+               $(chmod) $(dmode) $(DESTDIR)$(prefix))
+       @[ -d $(DESTDIR)$(exec_prefix) ] || \
+           ($(mkdir) $(DESTDIR)$(exec_prefix) && \
+               $(chmod) $(dmode) $(DESTDIR)$(exec_prefix))
+       @[ -d $(DESTDIR)$(datadir) ] || \
+           ($(mkdir) $(DESTDIR)$(datadir) && \
+               $(chmod) $(dmode) $(DESTDIR)$(datadir))
+       @$(rm) -rf $(DESTDIR)$(datadir)/vi
+       @$(mkdir) $(DESTDIR)$(datadir)/vi && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi
+       @echo "Installing message catalogs: $(datadir)/vi/catalog ..."
+       @$(mkdir) $(DESTDIR)$(datadir)/vi/catalog && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi/catalog
+       @(cd $(visrcdir)/catalog && \
+           $(cp) $(cat) $(DESTDIR)$(datadir)/vi/catalog && \
+           cd $(DESTDIR)$(datadir)/vi/catalog && $(chmod) $(fmode) *)
+       @echo "Installing Perl scripts: $(datadir)/vi/perl ..."
+       @$(mkdir) $(DESTDIR)$(datadir)/vi/perl && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi/perl
+       @[ ! -f VI.pm ] || \
+           ($(cp) VI.pm $(DESTDIR)$(datadir)/vi/perl && \
+           (cd $(DESTDIR)$(datadir)/vi/perl && $(chmod) $(fmode) VI.pm))
+       @(cd $(visrcdir)/perl_scripts && \
+           $(cp) *.pl $(DESTDIR)$(datadir)/vi/perl && \
+           cd $(DESTDIR)$(datadir)/vi/perl && $(chmod) $(fmode) *.pl)
+       @echo "Installing Tcl scripts: $(datadir)/vi/tcl ..."
+       @$(mkdir) $(DESTDIR)$(datadir)/vi/tcl && \
+           $(chmod) $(dmode) $(DESTDIR)$(datadir)/vi/tcl
+       @(cd $(visrcdir)/tcl_scripts && \
+           $(cp) *.tcl $(DESTDIR)$(datadir)/vi/tcl && \
+           cd $(DESTDIR)$(datadir)/vi/tcl && $(chmod) $(fmode) *.tcl)
+       @echo "Installing recover script: $(datadir)/vi/recover ..."
+       @($(cp) recover $(DESTDIR)$(datadir)/vi/recover && \
+           $(chmod) $(emode) $(DESTDIR)$(datadir)/vi/recover)
+
+uninstall-local:
+       $(rm) -rf $(DESTDIR)$(datadir)/vi
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo ex | sed '$(transform)'`
+       cd $(DESTDIR)$(bindir) && $(rm) -f `echo view | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo ex.0 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo vi.0 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/cat1 && \
+           $(rm) -f `echo view.0 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo ex.1 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo vi.1 | sed '$(transform)'`
+       cd $(DESTDIR)$(mandir)/man1 && \
+           $(rm) -f `echo view.1 | sed '$(transform)'`
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/dist/nvi/dist/acconfig.h b/dist/nvi/dist/acconfig.h
new file mode 100644 (file)
index 0000000..83ba4f1
--- /dev/null
@@ -0,0 +1,126 @@
+/*     $NetBSD: acconfig.h,v 1.1.1.2 2008/05/18 14:29:55 aymeric Exp $ */
+
+/* Id: acconfig.h,v 8.34 2002/01/19 23:01:35 skimo Exp (Berkeley) Date: 2002/01/19 23:01:35 */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef ssize_t
+
+/* Define if you want a debugging version. */
+#undef DEBUG
+
+/* Define if you have a System V-style (broken) gettimeofday. */
+#undef HAVE_BROKEN_GETTIMEOFDAY
+
+/* Define if you have a Ultrix-style (broken) vdisable. */
+#undef HAVE_BROKEN_VDISABLE
+
+/* Define if you have a BSD version of curses. */
+#undef HAVE_BSD_CURSES
+
+/* Define if you have wide ncurses(3). */
+#undef HAVE_NCURSESW
+
+/* Define if you have the curses(3) waddnwstr function. */
+#undef HAVE_CURSES_ADDNWSTR
+
+/* Define if you have the curses(3) waddnstr function. */
+#undef HAVE_CURSES_WADDNSTR
+
+/* Define if you have the curses(3) beep function. */
+#undef HAVE_CURSES_BEEP
+
+/* Define if you have the curses(3) flash function. */
+#undef HAVE_CURSES_FLASH
+
+/* Define if you have the curses(3) idlok function. */
+#undef HAVE_CURSES_IDLOK
+
+/* Define if you have the curses(3) keypad function. */
+#undef HAVE_CURSES_KEYPAD
+
+/* Define if you have the curses(3) newterm function. */
+#undef HAVE_CURSES_NEWTERM
+
+/* Define if you have the curses(3) setupterm function. */
+#undef HAVE_CURSES_SETUPTERM
+
+/* Define if you have the curses(3) tigetstr/tigetnum functions. */
+#undef HAVE_CURSES_TIGETSTR
+
+/* Define if you have the DB __hash_open call in the C library. */
+#undef HAVE_DB_HASH_OPEN
+
+/* Define if you have the chsize(2) system call. */
+#undef HAVE_FTRUNCATE_CHSIZE
+
+/* Define if you have the ftruncate(2) system call. */
+#undef HAVE_FTRUNCATE_FTRUNCATE
+
+/* Define if you have gcc. */
+#undef HAVE_GCC
+
+/* Define if you have fcntl(2) style locking. */
+#undef HAVE_LOCK_FCNTL
+
+/* Define if you have flock(2) style locking. */
+#undef HAVE_LOCK_FLOCK
+
+/* Define is appropriate pango is available */
+#undef HAVE_PANGO
+
+/* Define if you want to compile in the Perl interpreter. */
+#undef HAVE_PERL_INTERP
+
+/* Define if using pthread. */
+#undef HAVE_PTHREAD
+
+/* Define if you have the Berkeley style revoke(2) system call. */
+#undef HAVE_REVOKE
+
+/* Define if you have the Berkeley style strsep(3) function. */
+#undef HAVE_STRSEP
+
+/* Define if you have <sys/mman.h> */
+#undef HAVE_SYS_MMAN_H
+
+/* Define if you have <sys/select.h> */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the System V style pty calls. */
+#undef HAVE_SYS5_PTY
+
+/* Define if you want to compile in the Tcl interpreter. */
+#undef HAVE_TCL_INTERP
+
+/* Define is appropriate zvt is available */
+#undef HAVE_ZVT
+
+/* Define if your sprintf returns a pointer, not a length. */
+#undef SPRINTF_RET_CHARPNT
+
+/* Define when using db1 */
+#undef USE_DB1
+
+/* Define when using db4 logging */
+#undef USE_DB4_LOGGING
+
+/* Define when dynamically loading DB 3 */
+#undef USE_DYNAMIC_LOADING
+
+/* Define when iconv can be used */
+#undef USE_ICONV
+
+/* Define when perl's setenv should be used */
+#undef USE_PERL_SETENV
+
+/* Define when using S-Lang */
+#undef USE_SLANG_CURSES
+
+/* Define when using wide characters */
+#undef USE_WIDECHAR
+
+/* Define if you have <ncurses.h> */
+#undef HAVE_NCURSES_H
+
+/* Define when fprintf prototype not in an obvious place */
+#undef NEED_FPRINTF_PROTO
diff --git a/dist/nvi/dist/aclocal.m4 b/dist/nvi/dist/aclocal.m4
new file mode 100644 (file)
index 0000000..6b8a4a1
--- /dev/null
@@ -0,0 +1,7440 @@
+# generated automatically by aclocal 1.10 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_if(m4_PACKAGE_VERSION, [2.61],,
+[m4_fatal([this file was generated for autoconf 2.61.
+You have another version of autoconf.  If you want to use that,
+you should regenerate the build system entirely.], [63])])
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+
+# serial 51 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+         [],
+         [m4_define([AC_PROVIDE_IFELSE],
+                [m4_ifdef([AC_PROVIDE_$1],
+                          [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+  AC_PROVIDE_IFELSE([AC_PROG_CXX],
+    [AC_LIBTOOL_CXX],
+    [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+  ])])
+dnl And a similar setup for Fortran 77 support
+  AC_PROVIDE_IFELSE([AC_PROG_F77],
+    [AC_LIBTOOL_F77],
+    [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+  AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+    [AC_LIBTOOL_GCJ],
+    [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+      [AC_LIBTOOL_GCJ],
+      [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+       [AC_LIBTOOL_GCJ],
+      [ifdef([AC_PROG_GCJ],
+            [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([A][M_PROG_GCJ],
+            [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([LT_AC_PROG_GCJ],
+            [define([LT_AC_PROG_GCJ],
+               defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    AC_PATH_MAGIC
+  fi
+  ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+       [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+    [AC_HELP_STRING([--with-pic],
+       [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+AC_DEFUN([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+AC_DEFUN([_LT_COMPILER_BOILERPLATE],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+AC_DEFUN([_LT_LINKER_BOILERPLATE],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_LINKER_BOILERPLATE
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+            [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+        [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+[$]*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    IFS="$lt_save_ifs"
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "[$]0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+       [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *32-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_i386_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_x86_64_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)    LD="${LD-ld} -64" ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+  ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#              [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+  ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$5], , :, [$5])
+else
+    ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                          [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$4], , :, [$4])
+else
+    ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[       ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+              = "XX$teststring") >/dev/null 2>&1 &&
+             new_result=`expr "X$teststring" : ".*" 2>&1` &&
+             lt_cv_sys_max_cmd_len=$new_result &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on massive
+      # amounts of additional arguments before passing them to the linker.
+      # It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# ------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ---------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}]
+EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# ----------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+   ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+   ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+         [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+           [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen="dlopen"],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+   test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+   test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_AC_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+   darwin*)
+       if test -n "$STRIP" ; then
+         striplib="$STRIP -x"
+         old_striplib="$STRIP -S"
+         AC_MSG_RESULT([yes])
+       else
+  AC_MSG_RESULT([no])
+fi
+       ;;
+   *)
+  AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+m4_if($1,[],[
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`echo $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+  m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) 
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[         ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_ARG_WITH([tags],
+    [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+        [include additional configurations @<:@automatic@:>@])],
+    [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+  if test ! -f "${ofile}"; then
+    AC_MSG_WARN([output file `$ofile' does not exist])
+  fi
+
+  if test -z "$LTCC"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+    if test -z "$LTCC"; then
+      AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+    else
+      AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+    fi
+  fi
+  if test -z "$LTCFLAGS"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+  fi
+
+  # Extract list of available tagged configurations in $ofile.
+  # Note that this assumes the entire list is on one line.
+  available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+  lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+  for tagname in $tagnames; do
+    IFS="$lt_save_ifs"
+    # Check whether tagname contains only valid characters
+    case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+    "") ;;
+    *)  AC_MSG_ERROR([invalid tag name: $tagname])
+       ;;
+    esac
+
+    if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+    then
+      AC_MSG_ERROR([tag name \"$tagname\" already exists])
+    fi
+
+    # Update the list of available tags.
+    if test -n "$tagname"; then
+      echo appending configuration tag \"$tagname\" to $ofile
+
+      case $tagname in
+      CXX)
+       if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+           ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+           (test "X$CXX" != "Xg++"))) ; then
+         AC_LIBTOOL_LANG_CXX_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      F77)
+       if test -n "$F77" && test "X$F77" != "Xno"; then
+         AC_LIBTOOL_LANG_F77_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      GCJ)
+       if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+         AC_LIBTOOL_LANG_GCJ_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      RC)
+       AC_LIBTOOL_LANG_RC_CONFIG
+       ;;
+
+      *)
+       AC_MSG_ERROR([Unsupported tag name: $tagname])
+       ;;
+      esac
+
+      # Append the new tag name to the list of available tags.
+      if test -n "$tagname" ; then
+      available_tags="$available_tags $tagname"
+    fi
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+  else
+    rm -f "${ofile}T"
+    AC_MSG_ERROR([unable to update list of available tagged configurations.])
+  fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 DLLs
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+    [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+       [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+# set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+    [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+       [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+    [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+   [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognize shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="ifelse([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognize a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+    [AC_HELP_STRING([--with-gnu-ld],
+       [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+nto-qnx*)
+  lt_cv_deplibs_check_method=unknown
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# it is assumed to be `libltdl'.  LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!).  If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, lt_dlinit,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    LTDLINCL=
+  fi
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ------------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+    [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+      [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+        [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+          [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# -------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF
+
+# Report which library types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+    ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+  lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+  $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+  lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+  $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+  # Set up default GNU C++ configuration
+
+  AC_PROG_LD
+
+  # Check if GNU C++ uses GNU ld as the underlying linker, since the
+  # archiving commands below assume that GNU ld is being used.
+  if test "$with_gnu_ld" = yes; then
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+    #     investigate it a little bit more. (MM)
+    wlarc='${wl}'
+
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+       grep 'no-whole-archive' > /dev/null; then
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    with_gnu_ld=no
+    wlarc=
+
+    # A generic and very simple default shared library creation
+    # command for GNU C++ for the case where it uses the native
+    # linker, instead of GNU ld.  If possible, this setting should
+    # overridden to take advantage of the native linker features on
+    # the platform it is being used on.
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+  fi
+
+  # Commands to make compiler produce verbose output that lists
+  # what "hidden" libraries, object files and flags are used when
+  # linking a shared library.
+  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+  GXX=no
+  with_gnu_ld=no
+  wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+  aix3*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         case $ld_flag in
+         *-brtl*)
+           aix_use_runtimelinking=yes
+           break
+           ;;
+         esac
+       done
+       ;;
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    _LT_AC_TAGVAR(archive_cmds, $1)=''
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+    if test "$GXX" = yes; then
+      case $host_os in aix4.[[012]]|aix4.[[012]].*)
+      # We only want to do this on AIX 4.2 and lower, the check
+      # below for broken collect2 doesn't work under 4.3+
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         :
+       else
+         # We have old collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+       fi
+       ;;
+      esac
+      shared_flag='-shared'
+      if test "$aix_use_runtimelinking" = yes; then
+       shared_flag="$shared_flag "'${wl}-G'
+      fi
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+       shared_flag='-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall does not export symbols beginning with
+    # underscore (_), so it is better to generate a list of symbols to export.
+    _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+      # Determine the default libpath from the value encoded in an empty executable.
+      _LT_AC_SYS_LIBPATH_AIX
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+     else
+      if test "$host_cpu" = ia64; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+      else
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+       # Exported symbols can be pulled into shared objects from archives
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+       _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+       # This is similar to how AIX traditionally builds its shared libraries.
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+      fi
+    fi
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+    ;;
+
+  chorus*)
+    case $cc_basename in
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+    # as there is no search path for DLLs.
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+    _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+    _LT_AC_TAGVAR(always_export_symbols, $1)=no
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+    if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      # If the export-symbols file already is a .def file (1st line
+      # is EXPORTS), use it as is; otherwise, prepend...
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname.def;
+      else
+       echo EXPORTS > $output_objdir/$soname.def;
+       cat $export_symbols >> $output_objdir/$soname.def;
+      fi~
+      $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+  ;;
+      darwin* | rhapsody*)
+        case $host_os in
+        rhapsody* | darwin1.[[012]])
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[[012]])
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+        esac
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+    if test "$GXX" = yes ; then
+      lt_int_apple_cc_single_mod=no
+      output_verbose_link_cmd='echo'
+      if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+       lt_int_apple_cc_single_mod=yes
+      fi
+      if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      else
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+        fi
+        _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+            _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          else
+            _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          fi
+            _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+          _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+          ;;
+      esac
+      fi
+        ;;
+
+  dgux*)
+    case $cc_basename in
+      ec++*)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      ghcx*)
+       # Green Hills C++ Compiler
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  freebsd[[12]]*)
+    # C++ shared libraries reported to be fairly broken before switch to ELF
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  freebsd-elf*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    ;;
+  freebsd* | dragonfly*)
+    # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+    # conventions
+    _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+    ;;
+  gnu*)
+    ;;
+  hpux9*)
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                               # but as the default
+                               # location of the library.
+
+    case $cc_basename in
+    CC*)
+      # FIXME: insert proper C++ library support
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    aCC*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      #
+      # There doesn't appear to be a way to prevent this compiler from
+      # explicitly linking system object files so we need to strip them
+      # from the output so that they don't get included in the library
+      # dependencies.
+      output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+      ;;
+    *)
+      if test "$GXX" = yes; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+        # FIXME: insert proper C++ library support
+        _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+    ;;
+  hpux10*|hpux11*)
+    if test $with_gnu_ld = no; then
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+      case $host_cpu in
+      hppa*64*|ia64*) ;;
+      *)
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        ;;
+      esac
+    fi
+    case $host_cpu in
+    hppa*64*|ia64*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+    *)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                             # but as the default
+                                             # location of the library.
+      ;;
+    esac
+
+    case $cc_basename in
+      CC*)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      aCC*)
+       case $host_cpu in
+       hppa*64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       esac
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test $with_gnu_ld = no; then
+           case $host_cpu in
+           hppa*64*)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           ia64*)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           *)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           esac
+         fi
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  interix[[3-9]]*)
+    _LT_AC_TAGVAR(hardcode_direct, $1)=no
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+    # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+    # Instead, shared libraries are loaded at an image base (0x10000000 by
+    # default) and relocated if they conflict, which is a slow very memory
+    # consuming and fragmenting process.  To avoid this, we pick a random,
+    # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+    # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    ;;
+  irix5* | irix6*)
+    case $cc_basename in
+      CC*)
+       # SGI C++
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       # Archives containing C++ object files must be created using
+       # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test "$with_gnu_ld" = no; then
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+         else
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+         fi
+       fi
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+       ;;
+    esac
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    ;;
+  linux* | k*bsd*-gnu)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+       ;;
+      icpc*)
+       # Intel C++
+       with_gnu_ld=yes
+       # version 8.0 and above of icpc choke on multiply defined symbols
+       # if we add $predep_objects and $postdep_objects, however 7.1 and
+       # earlier do not add the objects themselves.
+       case `$CC -V 2>&1` in
+       *"Version 7."*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       *)  # Version 8.0 or newer
+         tmp_idyn=
+         case $host_cpu in
+           ia64*) tmp_idyn=' -i_dynamic';;
+         esac
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       esac
+       _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+       ;;
+      pgCC*)
+        # Portland Group C++ compiler
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+        ;;
+      cxx*)
+       # Compaq C++
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+       runpath_var=LD_RUN_PATH
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C++ 5.9
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+
+         # Not sure whether something based on
+         # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+         # would be better.
+         output_verbose_link_cmd='echo'
+
+         # Archives containing C++ object files must be created using
+         # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+         # necessary to make sure instantiated templates are included
+         # in the archive.
+         _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+         ;;
+       esac
+       ;;
+    esac
+    ;;
+  lynxos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  m88k*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  mvs*)
+    case $cc_basename in
+      cxx*)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    fi
+    # Workaround some broken pre-1.5 toolchains
+    output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+    ;;
+  openbsd2*)
+    # C++ shared libraries are fairly broken
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  openbsd*)
+    if test -f /usr/libexec/ld.so; then
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      fi
+      output_verbose_link_cmd='echo'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+    ;;
+  osf3*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      cxx*)
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  osf4* | osf5*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Archives containing C++ object files must be created using
+       # the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      cxx*)
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+         echo "-hidden">> $lib.exp~
+         $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp  `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+         $rm $lib.exp'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  psos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  sunos4*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.x
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      lcc*)
+       # Lucid
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  solaris*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.2, 5.x and Centerline C++
+        _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
+       _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       case $host_os in
+         solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+         *)
+           # The compiler driver will combine and reorder linker options,
+           # but understands `-z linker_flag'.
+           # Supported since Solaris 2.6 (maybe 2.5.1?)
+           _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+           ;;
+       esac
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+       output_verbose_link_cmd='echo'
+
+       # Archives containing C++ object files must be created using
+       # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+       ;;
+      gcx*)
+       # Green Hills C++ Compiler
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+       # The C++ compiler must be used to create the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+       ;;
+      *)
+       # GNU C++ compiler with Solaris linker
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+         if $CC --version | grep -v '^2\.7' > /dev/null; then
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         else
+           # g++ 2.7 appears to require `-G' NOT `-shared' on this
+           # platform.
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         fi
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+         case $host_os in
+         solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+         *)
+           _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+           ;;
+         esac
+       fi
+       ;;
+    esac
+    ;;
+  sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+    _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  sysv5* | sco3.2v5* | sco5v6*)
+    # Note: We can NOT use -z defs as we might desire, because we do not
+    # link with -lc, and that would cause any symbols used from libc to
+    # always be unresolved, which means just about no library would
+    # ever link correctly.  If we're not using GNU ld we use -z text
+    # though, which does catch some bad symbols but isn't as heavy-handed
+    # as -z defs.
+    # For security reasons, it is highly recommended that you always
+    # use absolute paths for naming shared libraries, and exclude the
+    # DT_RUNPATH tag from executables and libraries.  But doing so
+    # requires that you compile everything twice, which is a pain.
+    # So that behaviour is only enabled if SCOABSPATH is set to a
+    # non-empty value in the environment.  Most likely only useful for
+    # creating official distributions of packages.
+    # This is a hack until libtool officially supports absolute path
+    # names for shared libraries.
+    _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+    _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  tandem*)
+    case $cc_basename in
+      NCC*)
+       # NonStop-UX NCC 3.20
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  vxworks*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  *)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  # The `*' in the case matches for architectures that use `case' in
+  # $output_verbose_cmd can trigger glob expansion during the loop
+  # eval without this substitution.
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+  for p in `eval $output_verbose_link_cmd`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" \
+         || test $p = "-R"; then
+        prev=$p
+        continue
+       else
+        prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        case $p in
+        -L* | -R*)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+            _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+          else
+            _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+          _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+        else
+          _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+        fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+          _LT_AC_TAGVAR(predep_objects, $1)="$p"
+        else
+          _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+        fi
+       else
+        if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+          _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+        else
+          _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_AC_TAGVAR(predep_objects,$1)=
+  _LT_AC_TAGVAR(postdep_objects,$1)=
+  _LT_AC_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+    #
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="\
+      program t
+      end
+"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# -------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars.  Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    _LT_AC_TAGVAR(compiler, $1) \
+    _LT_AC_TAGVAR(CC, $1) \
+    _LT_AC_TAGVAR(LD, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+    _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+    _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+    _LT_AC_TAGVAR(old_archive_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+    _LT_AC_TAGVAR(predep_objects, $1) \
+    _LT_AC_TAGVAR(postdep_objects, $1) \
+    _LT_AC_TAGVAR(predeps, $1) \
+    _LT_AC_TAGVAR(postdeps, $1) \
+    _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+    _LT_AC_TAGVAR(archive_cmds, $1) \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(postinstall_cmds, $1) \
+    _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+    _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+    _LT_AC_TAGVAR(no_undefined_flag, $1) \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+    _LT_AC_TAGVAR(hardcode_automatic, $1) \
+    _LT_AC_TAGVAR(module_cmds, $1) \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+    _LT_AC_TAGVAR(fix_srcfile_path, $1) \
+    _LT_AC_TAGVAR(exclude_expsyms, $1) \
+    _LT_AC_TAGVAR(include_expsyms, $1); do
+
+    case $var in
+    _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(module_cmds, $1) | \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\[$]0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+    ;;
+  esac
+
+ifelse([$1], [],
+  [cfgfile="${ofile}T"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  $rm -f "$cfgfile"
+  AC_MSG_NOTICE([creating $ofile])],
+  [cfgfile="$ofile"])
+
+  cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" || \
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+])
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([LT_AC_PROG_SED])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+linux* | k*bsd*-gnu)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDGIRSTW]]'
+    lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+    lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[     ]]\($symcode$symcode*\)[[       ]][[    ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if grep ' nm_test_var$' "$nlist" >/dev/null; then
+       if grep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_save_LIBS="$LIBS"
+         lt_save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+         if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS="$lt_save_LIBS"
+         CFLAGS="$lt_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix4* | aix5*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       else
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+       darwin*)
+         # PIC is the default on this platform
+         # Common symbols not allowed in MH_DYLIB files
+         case $cc_basename in
+           xlc*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           ;;
+         esac
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           if test "$host_cpu" != ia64; then
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+           fi
+           ;;
+         aCC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         icpc* | ecpc*)
+           # Intel C++
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         pgCC*)
+           # Portland Group C++ compiler.
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+             _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+             _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd*)
+       ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+       ;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+    _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+    [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix4* | aix5*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+],[
+  runpath_var=
+  _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+  _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_AC_TAGVAR(archive_cmds, $1)=
+  _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+  _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+  _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+  _LT_AC_TAGVAR(module_cmds, $1)=
+  _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(always_export_symbols, $1)=no
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_AC_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  _LT_CC_BASENAME([$compiler])
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=no
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    interix[[3-9]]*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           _LT_AC_TAGVAR(ld_shlibs, $1)=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+       else
+         _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_AC_TAGVAR(archive_cmds, $1)=''
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[[012]]|aix4.[[012]].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        _LT_AC_SYS_LIBPATH_AIX
+        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      # see comment about different semantics on the GNU ld section
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    bsdi[[45]]*)
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[[012]])
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[[012]])
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    freebsd1*)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+         _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+         ;;
+       *)
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+         _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+         _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       else
+         case $host_os in
+          openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+            _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+            ;;
+          *)
+            _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+        ;;
+       motorola)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_AC_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+       pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+        then
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
+  ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL],   [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED],  [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC],  [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD],        [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM],        [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+  test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+  AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+
+# Cheap backport of AS_EXECUTABLE_P and required macros
+# from Autoconf 2.59; we should not use $as_executable_p directly.
+
+# _AS_TEST_PREPARE
+# ----------------
+m4_ifndef([_AS_TEST_PREPARE],
+[m4_defun([_AS_TEST_PREPARE],
+[if test -x / >/dev/null 2>&1; then
+  as_executable_p='test -x'
+else
+  as_executable_p='test -f'
+fi
+])])# _AS_TEST_PREPARE
+
+# AS_EXECUTABLE_P
+# ---------------
+# Check whether a file is executable.
+m4_ifndef([AS_EXECUTABLE_P],
+[m4_defun([AS_EXECUTABLE_P],
+[AS_REQUIRE([_AS_TEST_PREPARE])dnl
+$as_executable_p $1[]dnl
+])])# AS_EXECUTABLE_P
+
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])
+
+# Copyright (C) 2002, 2003, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.10], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10])dnl
+_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
+    dirpart=`AS_DIRNAME("$mf")`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`AS_DIRNAME(["$file"])`
+    AS_MKDIR_P([$dirpart/$fdir])
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+                            [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                  [_AM_DEPENDENCIES(OBJC)],
+                  [define([AC_PROG_OBJC],
+                          defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $1 | $1:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.                 -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/gtk.m4])
diff --git a/dist/nvi/dist/compile b/dist/nvi/dist/compile
new file mode 100644 (file)
index 0000000..9bb997a
--- /dev/null
@@ -0,0 +1,99 @@
+#! /bin/sh
+
+# Wrapper for compilers which do not understand `-c -o'.
+
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Usage:
+# compile PROGRAM [ARGS]...
+# `-o FOO.o' is removed from the args passed to the actual compile.
+
+prog=$1
+shift
+
+ofile=
+cfile=
+args=
+while test $# -gt 0; do
+   case "$1" in
+    -o)
+       # configure might choose to run compile as `compile cc -o foo foo.c'.
+       # So we do something ugly here.
+       ofile=$2
+       shift
+       case "$ofile" in
+       *.o | *.obj)
+          ;;
+       *)
+          args="$args -o $ofile"
+          ofile=
+          ;;
+       esac
+       ;;
+    *.c)
+       cfile=$1
+       args="$args $1"
+       ;;
+    *)
+       args="$args $1"
+       ;;
+   esac
+   shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+   # If no `-o' option was seen then we might have been invoked from a
+   # pattern rule where we don't need one.  That is ok -- this is a
+   # normal compilation that the losing compiler can handle.  If no
+   # `.c' file was seen then we are probably linking.  That is also
+   # ok.
+   exec "$prog" $args
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d
+while true; do
+   if mkdir $lockdir > /dev/null 2>&1; then
+      break
+   fi
+   sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir $lockdir; exit 1" 1 2 15
+
+# Run the compile.
+"$prog" $args
+status=$?
+
+if test -f "$cofile"; then
+   mv "$cofile" "$ofile"
+fi
+
+rmdir $lockdir
+exit $status
diff --git a/dist/nvi/dist/config.guess b/dist/nvi/dist/config.guess
new file mode 100644 (file)
index 0000000..951383e
--- /dev/null
@@ -0,0 +1,1516 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2007-05-17'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[45])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep __LP64__ >/dev/null
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:[3456]*)
+       case ${UNAME_MACHINE} in
+           x86) 
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           EM64T | authenticamd)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips64
+       #undef mips64el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mips64el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips64
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa:Linux:*:*)
+       echo xtensa-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit ;;
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^LIBC/{
+               s: ::g
+               p
+           }'`"
+       test x"${LIBC}" != x && {
+               echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+               exit
+       }
+       test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+       echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/dist/nvi/dist/config.h.in b/dist/nvi/dist/config.h.in
new file mode 100644 (file)
index 0000000..c1bda3e
--- /dev/null
@@ -0,0 +1,283 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+/* Id: acconfig.h,v 8.34 2002/01/19 23:01:35 skimo Exp (Berkeley) Date: 2002/01/19 23:01:35 */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef ssize_t
+
+/* Define if you want a debugging version. */
+#undef DEBUG
+
+/* Define if you have a System V-style (broken) gettimeofday. */
+#undef HAVE_BROKEN_GETTIMEOFDAY
+
+/* Define if you have a Ultrix-style (broken) vdisable. */
+#undef HAVE_BROKEN_VDISABLE
+
+/* Define if you have a BSD version of curses. */
+#undef HAVE_BSD_CURSES
+
+/* Define if you have wide ncurses(3). */
+#undef HAVE_NCURSESW
+
+/* Define if you have the curses(3) waddnwstr function. */
+#undef HAVE_CURSES_ADDNWSTR
+
+/* Define if you have the curses(3) waddnstr function. */
+#undef HAVE_CURSES_WADDNSTR
+
+/* Define if you have the curses(3) beep function. */
+#undef HAVE_CURSES_BEEP
+
+/* Define if you have the curses(3) flash function. */
+#undef HAVE_CURSES_FLASH
+
+/* Define if you have the curses(3) idlok function. */
+#undef HAVE_CURSES_IDLOK
+
+/* Define if you have the curses(3) keypad function. */
+#undef HAVE_CURSES_KEYPAD
+
+/* Define if you have the curses(3) newterm function. */
+#undef HAVE_CURSES_NEWTERM
+
+/* Define if you have the curses(3) setupterm function. */
+#undef HAVE_CURSES_SETUPTERM
+
+/* Define if you have the curses(3) tigetstr/tigetnum functions. */
+#undef HAVE_CURSES_TIGETSTR
+
+/* Define if you have the DB __hash_open call in the C library. */
+#undef HAVE_DB_HASH_OPEN
+
+/* Define if you have the chsize(2) system call. */
+#undef HAVE_FTRUNCATE_CHSIZE
+
+/* Define if you have the ftruncate(2) system call. */
+#undef HAVE_FTRUNCATE_FTRUNCATE
+
+/* Define if you have gcc. */
+#undef HAVE_GCC
+
+/* Define if you have fcntl(2) style locking. */
+#undef HAVE_LOCK_FCNTL
+
+/* Define if you have flock(2) style locking. */
+#undef HAVE_LOCK_FLOCK
+
+/* Define is appropriate pango is available */
+#undef HAVE_PANGO
+
+/* Define if you want to compile in the Perl interpreter. */
+#undef HAVE_PERL_INTERP
+
+/* Define if using pthread. */
+#undef HAVE_PTHREAD
+
+/* Define if you have the Berkeley style revoke(2) system call. */
+#undef HAVE_REVOKE
+
+/* Define if you have the Berkeley style strsep(3) function. */
+#undef HAVE_STRSEP
+
+/* Define if you have <sys/mman.h> */
+#undef HAVE_SYS_MMAN_H
+
+/* Define if you have <sys/select.h> */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the System V style pty calls. */
+#undef HAVE_SYS5_PTY
+
+/* Define if you want to compile in the Tcl interpreter. */
+#undef HAVE_TCL_INTERP
+
+/* Define is appropriate zvt is available */
+#undef HAVE_ZVT
+
+/* Define if your sprintf returns a pointer, not a length. */
+#undef SPRINTF_RET_CHARPNT
+
+/* Define when using db1 */
+#undef USE_DB1
+
+/* Define when using db4 logging */
+#undef USE_DB4_LOGGING
+
+/* Define when dynamically loading DB 3 */
+#undef USE_DYNAMIC_LOADING
+
+/* Define when iconv can be used */
+#undef USE_ICONV
+
+/* Define when perl's setenv should be used */
+#undef USE_PERL_SETENV
+
+/* Define when using S-Lang */
+#undef USE_SLANG_CURSES
+
+/* Define when using wide characters */
+#undef USE_WIDECHAR
+
+/* Define if you have <ncurses.h> */
+#undef HAVE_NCURSES_H
+
+/* Define when fprintf prototype not in an obvious place */
+#undef NEED_FPRINTF_PROTO
+
+/* Define to 1 if you have the `bsearch' function. */
+#undef HAVE_BSEARCH
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `iswblank' function. */
+#undef HAVE_ISWBLANK
+
+/* Define to 1 if you have the `memchr' function. */
+#undef HAVE_MEMCHR
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the <ncursesw/ncurses.h> header file. */
+#undef HAVE_NCURSESW_NCURSES_H
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+#undef HAVE_NCURSES_H
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strpbrk' function. */
+#undef HAVE_STRPBRK
+
+/* Define to 1 if you have the `strsep' function. */
+#undef HAVE_STRSEP
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if your `struct stat' has `st_blksize'. Deprecated, use
+   `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */
+#undef HAVE_ST_BLKSIZE
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/dist/nvi/dist/config.sub b/dist/nvi/dist/config.sub
new file mode 100644 (file)
index 0000000..c060f44
--- /dev/null
@@ -0,0 +1,1626 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2007-04-29'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | mcore | mep \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64vr | mips64vrel \
+       | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | mt \
+       | msp430 \
+       | nios | nios2 \
+       | ns16k | ns32k \
+       | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nios-* | nios2-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16c)
+               basic_machine=cr16c-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+               os=-elf
+               ;;
+        spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+        mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/dist/nvi/dist/configure b/dist/nvi/dist/configure
new file mode 100644 (file)
index 0000000..b23e167
--- /dev/null
@@ -0,0 +1,30513 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&    (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+        /*)
+          for as_base in sh bash ksh sh5; do
+            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+          done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+        # Try only shells that exist, to save several forks.
+        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+               { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+              as_have_required=yes
+              if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+       case $1 in
+        -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    IFS="$lt_save_ifs"
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "$0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="../common/main.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+am__isrc
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+SED
+GREP
+EGREP
+LN_S
+ECHO
+AR
+RANLIB
+CPP
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+CXXCPP
+F77
+FFLAGS
+ac_ct_F77
+LIBTOOL
+OPTFLAG
+no_op_OPTFLAG
+vi_cv_path_shell
+vi_cv_path_sendmail
+vi_cv_path_perl
+vi_cv_path_preserve
+vi_cv_path_fuser
+vi_cv_path_lsof
+INUSE
+vi_cv_path_ar
+vi_cv_path_chmod
+vi_cv_path_cp
+vi_cv_path_ln
+vi_cv_path_mkdir
+vi_cv_path_rm
+vi_cv_path_ranlib
+vi_cv_path_strip
+XMKMF
+XINCS
+LIBOBJS
+vi_programs
+vi_ipc
+GTKLIBS
+GTKINCS
+PKG_CONFIG
+GTK_CONFIG
+GTK_CFLAGS
+GTK_LIBS
+MOTIFLIBS
+IPCOBJS
+shrpenv
+perlldflags
+perllibs
+vi_cv_perllib
+CURSLIBS
+CURSCPPFLAGS
+CURSLDFLAGS
+HAVE_NCURSESW
+u_char_decl
+u_short_decl
+u_int_decl
+u_long_decl
+u_int8_decl
+u_int16_decl
+int16_decl
+u_int32_decl
+int32_decl
+NEED_FPRINTF_PROTO
+dl_src
+vi_cv_path_db3
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+CXX
+CXXFLAGS
+CCC
+CXXCPP
+F77
+FFLAGS
+XMKMF'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+X features:
+  --x-includes=DIR    X include files are in DIR
+  --x-libraries=DIR   X library files are in DIR
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-debug          Build a debugging version.
+  --disable-runpath       Don't record path of libraries in binary.
+  --enable-trace          Build a tracing version.
+  --enable-widechar       Build a wide char aware vi.
+  --enable-gtk            Build a Gtk front-end for vi.
+  --disable-gtktest       Do not try to compile and run a test GTK program
+  --enable-motif          Build a Motif front-end for vi.
+  --enable-threads        Turn on thread support.
+  --enable-perlinterp     Include a Perl interpreter in vi.
+  --enable-tclinterp      Include a Tk/Tcl interpreter in vi.
+  --enable-dynamic-loading Load DB 3 dynamically.
+  --enable-db4-logging    Enable experimental/broken db4 logging.
+  --disable-re            DON'T use the nvi-provided RE routines.
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-tags[=TAGS]      include additional configurations [automatic]
+  --with-x                use the X Window System
+  --with-gtk-prefix=PFX   Prefix where GTK is installed (optional)
+  --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)
+  --with-curses=DIR       Path to curses installation.
+  --with-db=bundled|system Which db to use.
+  --with-db-prefix=PFX    Path to db installation.
+  --with-db-build=prefix  Path to db build.
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CXXCPP      C++ preprocessor
+  F77         Fortran 77 compiler command
+  FFLAGS      Fortran 77 compiler flags
+  XMKMF       Path to xmkmf, Makefile generator for X Window System
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+       "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_aux_dir=
+for ac_dir in . "$srcdir"/.; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+am__api_version='1.10'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in mkdir gmkdir; do
+        for ac_exec_ext in '' $ac_executable_extensions; do
+          { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+            'mkdir (GNU coreutils) '* | \
+            'mkdir (coreutils) '* | \
+            'mkdir (fileutils) '4.1*)
+              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+              break 3;;
+          esac
+        done
+       done
+done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  SET_MAKE=
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=vi
+ VERSION=1.81.6
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+# Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC"   am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; }
+if test "${lt_cv_path_SED+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+
+{ echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6; }
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+  { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; }
+if test "${lt_cv_path_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6; }
+NM="$lt_cv_path_NM"
+
+{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5
+echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+nto-qnx*)
+  lt_cv_deplibs_check_method=unknown
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 4459 "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.o` in
+    *32-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_i386_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_x86_64_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  lt_cv_cc_needs_belf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       lt_cv_cc_needs_belf=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)    LD="${LD-ld} -64" ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CXXFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+        CXXFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+if test -z "$CXXCPP"; then
+  if test "${ac_cv_prog_CXXCPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$F77"; then
+  ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+  { echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$F77" && break
+  done
+fi
+if test -z "$F77"; then
+  ac_ct_F77=$F77
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_F77"; then
+  ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_F77="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_F77" && break
+done
+
+  if test "x$ac_ct_F77" = x; then
+    F77=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    F77=$ac_ct_F77
+  fi
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file.  (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+      program main
+#ifndef __GNUC__
+       choke me
+#endif
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_f77_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_f77_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_prog_f77_g=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
+if test "$ac_test_FFLAGS" = set; then
+  FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-g -O2"
+  else
+    FFLAGS="-g"
+  fi
+else
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-O2"
+  else
+    FFLAGS=
+  fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[        ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+              = "XX$teststring") >/dev/null 2>&1 &&
+             new_result=`expr "X$teststring" : ".*" 2>&1` &&
+             lt_cv_sys_max_cmd_len=$new_result &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on massive
+      # amounts of additional arguments before passing them to the linker.
+      # It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6; }
+fi
+
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+linux* | k*bsd*-gnu)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDGIRSTW]'
+    lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+    lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[      ]\($symcode$symcode*\)[         ][      ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if grep ' nm_test_var$' "$nlist" >/dev/null; then
+       if grep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_save_LIBS="$LIBS"
+         lt_save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+         if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS="$lt_save_LIBS"
+         CFLAGS="$lt_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6; }
+else
+  { echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6; }
+if test "${lt_cv_objdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=no
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7196: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7200: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      else
+       lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         lt_prog_compiler_pic='-qnocommon'
+         lt_prog_compiler_wl='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-KPIC'
+       lt_prog_compiler_static='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-fpic'
+       lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic='-Kconform_pic'
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7486: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7490: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works=yes
+       fi
+     else
+       lt_prog_compiler_static_works=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; }
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7590: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:7594: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  enable_shared_with_static_runtimes=no
+  archive_cmds=
+  archive_expsym_cmds=
+  old_archive_From_new_cmds=
+  old_archive_from_expsyms_cmds=
+  export_dynamic_flag_spec=
+  whole_archive_flag_spec=
+  thread_safe_flag_spec=
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_direct=no
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  link_all_deplibs=unknown
+  hardcode_automatic=no
+  module_cmds=
+  module_expsym_cmds=
+  always_export_symbols=no
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      ld_shlibs=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       ld_shlibs=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           ld_shlibs=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L=yes
+         hardcode_libdir_flag_spec='-L$libdir'
+         hardcode_libdir_separator=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+       archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag="-z nodefs"
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag=' ${wl}-bernotok'
+         allow_undefined_flag=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         whole_archive_flag_spec='$convenience'
+         archive_cmds_need_lc=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs=no
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_From_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      archive_cmds_need_lc=no
+      hardcode_direct=no
+      hardcode_automatic=yes
+      hardcode_shlibpath_var=unsupported
+      whole_archive_flag_spec=''
+      link_all_deplibs=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      module_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+
+       hardcode_direct=yes
+       export_dynamic_flag_spec='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_libdir_flag_spec_ld='+b $libdir'
+         hardcode_direct=no
+         hardcode_shlibpath_var=no
+         ;;
+       *)
+         hardcode_direct=yes
+         export_dynamic_flag_spec='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_ld='-rpath $libdir'
+      fi
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct=yes
+       hardcode_shlibpath_var=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec='-R$libdir'
+            ;;
+          *)
+            archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds='$CC -r -o $output$reload_objs'
+         hardcode_direct=no
+        ;;
+       motorola)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl
+       pic_flag=$lt_prog_compiler_pic
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag
+        allow_undefined_flag=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc=no
+        else
+         archive_cmds_need_lc=yes
+        fi
+        allow_undefined_flag=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`echo $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var" || \
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+   darwin*)
+       if test -n "$STRIP" ; then
+         striplib="$STRIP -x"
+         old_striplib="$STRIP -S"
+         { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+       ;;
+   *)
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+    ;;
+  esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+   ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+   ;;
+
+  *)
+    { echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+  lt_cv_dlopen="shl_load"
+else
+  { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dld_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+  { echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+if test $ac_cv_func_dlopen = yes; then
+  lt_cv_dlopen="dlopen"
+else
+  { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_svld_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dld_dld_link=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 9939 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 10039 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+# Report which library types will actually be built
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+    ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler \
+    CC \
+    LD \
+    lt_prog_compiler_wl \
+    lt_prog_compiler_pic \
+    lt_prog_compiler_static \
+    lt_prog_compiler_no_builtin_flag \
+    export_dynamic_flag_spec \
+    thread_safe_flag_spec \
+    whole_archive_flag_spec \
+    enable_shared_with_static_runtimes \
+    old_archive_cmds \
+    old_archive_from_new_cmds \
+    predep_objects \
+    postdep_objects \
+    predeps \
+    postdeps \
+    compiler_lib_search_path \
+    archive_cmds \
+    archive_expsym_cmds \
+    postinstall_cmds \
+    postuninstall_cmds \
+    old_archive_from_expsyms_cmds \
+    allow_undefined_flag \
+    no_undefined_flag \
+    export_symbols_cmds \
+    hardcode_libdir_flag_spec \
+    hardcode_libdir_flag_spec_ld \
+    hardcode_libdir_separator \
+    hardcode_automatic \
+    module_cmds \
+    module_expsym_cmds \
+    lt_cv_prog_compiler_c_o \
+    fix_srcfile_path \
+    exclude_expsyms \
+    include_expsyms; do
+
+    case $var in
+    old_archive_cmds | \
+    old_archive_from_new_cmds | \
+    archive_cmds | \
+    archive_expsym_cmds | \
+    module_cmds | \
+    module_expsym_cmds | \
+    old_archive_from_expsyms_cmds | \
+    export_symbols_cmds | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="${ofile}T"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  $rm -f "$cfgfile"
+  { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+  cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" || \
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags was given.
+if test "${with_tags+set}" = set; then
+  withval=$with_tags; tagnames="$withval"
+fi
+
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+  if test ! -f "${ofile}"; then
+    { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+  fi
+
+  if test -z "$LTCC"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+    if test -z "$LTCC"; then
+      { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+    else
+      { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+    fi
+  fi
+  if test -z "$LTCFLAGS"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+  fi
+
+  # Extract list of available tagged configurations in $ofile.
+  # Note that this assumes the entire list is on one line.
+  available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+  lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+  for tagname in $tagnames; do
+    IFS="$lt_save_ifs"
+    # Check whether tagname contains only valid characters
+    case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+    "") ;;
+    *)  { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+   { (exit 1); exit 1; }; }
+       ;;
+    esac
+
+    if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+    then
+      { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+    # Update the list of available tags.
+    if test -n "$tagname"; then
+      echo appending configuration tag \"$tagname\" to $ofile
+
+      case $tagname in
+      CXX)
+       if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+           ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+           (test "X$CXX" != "Xg++"))) ; then
+         ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+  lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+  $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+  lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+  $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+  lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+  lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+  # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+  { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+  # Check if GNU C++ uses GNU ld as the underlying linker, since the
+  # archiving commands below assume that GNU ld is being used.
+  if test "$with_gnu_ld" = yes; then
+    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+    hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+    #     investigate it a little bit more. (MM)
+    wlarc='${wl}'
+
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+       grep 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec_CXX=
+    fi
+  else
+    with_gnu_ld=no
+    wlarc=
+
+    # A generic and very simple default shared library creation
+    # command for GNU C++ for the case where it uses the native
+    # linker, instead of GNU ld.  If possible, this setting should
+    # overridden to take advantage of the native linker features on
+    # the platform it is being used on.
+    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+  fi
+
+  # Commands to make compiler produce verbose output that lists
+  # what "hidden" libraries, object files and flags are used when
+  # linking a shared library.
+  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+  GXX=no
+  with_gnu_ld=no
+  wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+ld_shlibs_CXX=yes
+case $host_os in
+  aix3*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         case $ld_flag in
+         *-brtl*)
+           aix_use_runtimelinking=yes
+           break
+           ;;
+         esac
+       done
+       ;;
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    archive_cmds_CXX=''
+    hardcode_direct_CXX=yes
+    hardcode_libdir_separator_CXX=':'
+    link_all_deplibs_CXX=yes
+
+    if test "$GXX" = yes; then
+      case $host_os in aix4.[012]|aix4.[012].*)
+      # We only want to do this on AIX 4.2 and lower, the check
+      # below for broken collect2 doesn't work under 4.3+
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         :
+       else
+         # We have old collect2
+         hardcode_direct_CXX=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L_CXX=yes
+         hardcode_libdir_flag_spec_CXX='-L$libdir'
+         hardcode_libdir_separator_CXX=
+       fi
+       ;;
+      esac
+      shared_flag='-shared'
+      if test "$aix_use_runtimelinking" = yes; then
+       shared_flag="$shared_flag "'${wl}-G'
+      fi
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+       shared_flag='-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall does not export symbols beginning with
+    # underscore (_), so it is better to generate a list of symbols to export.
+    always_export_symbols_CXX=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      allow_undefined_flag_CXX='-berok'
+      # Determine the default libpath from the value encoded in an empty executable.
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+      hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+      archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+     else
+      if test "$host_cpu" = ia64; then
+       hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+       allow_undefined_flag_CXX="-z nodefs"
+       archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+      else
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       no_undefined_flag_CXX=' ${wl}-bernotok'
+       allow_undefined_flag_CXX=' ${wl}-berok'
+       # Exported symbols can be pulled into shared objects from archives
+       whole_archive_flag_spec_CXX='$convenience'
+       archive_cmds_need_lc_CXX=yes
+       # This is similar to how AIX traditionally builds its shared libraries.
+       archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+      fi
+    fi
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag_CXX=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs_CXX=no
+    fi
+    ;;
+
+  chorus*)
+    case $cc_basename in
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+    # as there is no search path for DLLs.
+    hardcode_libdir_flag_spec_CXX='-L$libdir'
+    allow_undefined_flag_CXX=unsupported
+    always_export_symbols_CXX=no
+    enable_shared_with_static_runtimes_CXX=yes
+
+    if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+      archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      # If the export-symbols file already is a .def file (1st line
+      # is EXPORTS), use it as is; otherwise, prepend...
+      archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname.def;
+      else
+       echo EXPORTS > $output_objdir/$soname.def;
+       cat $export_symbols >> $output_objdir/$soname.def;
+      fi~
+      $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+    else
+      ld_shlibs_CXX=no
+    fi
+  ;;
+      darwin* | rhapsody*)
+        case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+        esac
+      archive_cmds_need_lc_CXX=no
+      hardcode_direct_CXX=no
+      hardcode_automatic_CXX=yes
+      hardcode_shlibpath_var_CXX=unsupported
+      whole_archive_flag_spec_CXX=''
+      link_all_deplibs_CXX=yes
+
+    if test "$GXX" = yes ; then
+      lt_int_apple_cc_single_mod=no
+      output_verbose_link_cmd='echo'
+      if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+       lt_int_apple_cc_single_mod=yes
+      fi
+      if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+       archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      else
+          archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+        fi
+        module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+            archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          else
+            archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          fi
+            module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+          archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+          module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs_CXX=no
+          ;;
+      esac
+      fi
+        ;;
+
+  dgux*)
+    case $cc_basename in
+      ec++*)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      ghcx*)
+       # Green Hills C++ Compiler
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  freebsd[12]*)
+    # C++ shared libraries reported to be fairly broken before switch to ELF
+    ld_shlibs_CXX=no
+    ;;
+  freebsd-elf*)
+    archive_cmds_need_lc_CXX=no
+    ;;
+  freebsd* | dragonfly*)
+    # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+    # conventions
+    ld_shlibs_CXX=yes
+    ;;
+  gnu*)
+    ;;
+  hpux9*)
+    hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator_CXX=:
+    export_dynamic_flag_spec_CXX='${wl}-E'
+    hardcode_direct_CXX=yes
+    hardcode_minus_L_CXX=yes # Not in the search PATH,
+                               # but as the default
+                               # location of the library.
+
+    case $cc_basename in
+    CC*)
+      # FIXME: insert proper C++ library support
+      ld_shlibs_CXX=no
+      ;;
+    aCC*)
+      archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      #
+      # There doesn't appear to be a way to prevent this compiler from
+      # explicitly linking system object files so we need to strip them
+      # from the output so that they don't get included in the library
+      # dependencies.
+      output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+      ;;
+    *)
+      if test "$GXX" = yes; then
+        archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+      fi
+      ;;
+    esac
+    ;;
+  hpux10*|hpux11*)
+    if test $with_gnu_ld = no; then
+      hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_CXX=:
+
+      case $host_cpu in
+      hppa*64*|ia64*) ;;
+      *)
+       export_dynamic_flag_spec_CXX='${wl}-E'
+        ;;
+      esac
+    fi
+    case $host_cpu in
+    hppa*64*|ia64*)
+      hardcode_direct_CXX=no
+      hardcode_shlibpath_var_CXX=no
+      ;;
+    *)
+      hardcode_direct_CXX=yes
+      hardcode_minus_L_CXX=yes # Not in the search PATH,
+                                             # but as the default
+                                             # location of the library.
+      ;;
+    esac
+
+    case $cc_basename in
+      CC*)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      aCC*)
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       *)
+         archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       esac
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test $with_gnu_ld = no; then
+           case $host_cpu in
+           hppa*64*)
+             archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           ia64*)
+             archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           *)
+             archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           esac
+         fi
+       else
+         # FIXME: insert proper C++ library support
+         ld_shlibs_CXX=no
+       fi
+       ;;
+    esac
+    ;;
+  interix[3-9]*)
+    hardcode_direct_CXX=no
+    hardcode_shlibpath_var_CXX=no
+    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+    export_dynamic_flag_spec_CXX='${wl}-E'
+    # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+    # Instead, shared libraries are loaded at an image base (0x10000000 by
+    # default) and relocated if they conflict, which is a slow very memory
+    # consuming and fragmenting process.  To avoid this, we pick a random,
+    # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+    # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+    archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    ;;
+  irix5* | irix6*)
+    case $cc_basename in
+      CC*)
+       # SGI C++
+       archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       # Archives containing C++ object files must be created using
+       # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test "$with_gnu_ld" = no; then
+           archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+         else
+           archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+         fi
+       fi
+       link_all_deplibs_CXX=yes
+       ;;
+    esac
+    hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator_CXX=:
+    ;;
+  linux* | k*bsd*-gnu)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+       archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+       hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+       export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+       ;;
+      icpc*)
+       # Intel C++
+       with_gnu_ld=yes
+       # version 8.0 and above of icpc choke on multiply defined symbols
+       # if we add $predep_objects and $postdep_objects, however 7.1 and
+       # earlier do not add the objects themselves.
+       case `$CC -V 2>&1` in
+       *"Version 7."*)
+         archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       *)  # Version 8.0 or newer
+         tmp_idyn=
+         case $host_cpu in
+           ia64*) tmp_idyn=' -i_dynamic';;
+         esac
+         archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       esac
+       archive_cmds_need_lc_CXX=no
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+       export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+       whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+       ;;
+      pgCC*)
+        # Portland Group C++ compiler
+       archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+       export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+       whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+        ;;
+      cxx*)
+       # Compaq C++
+       archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+       runpath_var=LD_RUN_PATH
+       hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C++ 5.9
+         no_undefined_flag_CXX=' -zdefs'
+         archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+         hardcode_libdir_flag_spec_CXX='-R$libdir'
+         whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+
+         # Not sure whether something based on
+         # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+         # would be better.
+         output_verbose_link_cmd='echo'
+
+         # Archives containing C++ object files must be created using
+         # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+         # necessary to make sure instantiated templates are included
+         # in the archive.
+         old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+         ;;
+       esac
+       ;;
+    esac
+    ;;
+  lynxos*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  m88k*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  mvs*)
+    case $cc_basename in
+      cxx*)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds_CXX='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+      wlarc=
+      hardcode_libdir_flag_spec_CXX='-R$libdir'
+      hardcode_direct_CXX=yes
+      hardcode_shlibpath_var_CXX=no
+    fi
+    # Workaround some broken pre-1.5 toolchains
+    output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+    ;;
+  openbsd2*)
+    # C++ shared libraries are fairly broken
+    ld_shlibs_CXX=no
+    ;;
+  openbsd*)
+    if test -f /usr/libexec/ld.so; then
+      hardcode_direct_CXX=yes
+      hardcode_shlibpath_var_CXX=no
+      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+      if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+       archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+       export_dynamic_flag_spec_CXX='${wl}-E'
+       whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      fi
+      output_verbose_link_cmd='echo'
+    else
+      ld_shlibs_CXX=no
+    fi
+    ;;
+  osf3*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      cxx*)
+       allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+         archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+         hardcode_libdir_separator_CXX=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         ld_shlibs_CXX=no
+       fi
+       ;;
+    esac
+    ;;
+  osf4* | osf5*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Archives containing C++ object files must be created using
+       # the KAI C++ compiler.
+       old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      cxx*)
+       allow_undefined_flag_CXX=' -expect_unresolved \*'
+       archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+         echo "-hidden">> $lib.exp~
+         $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp  `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+         $rm $lib.exp'
+
+       hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+        archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+         hardcode_libdir_separator_CXX=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         ld_shlibs_CXX=no
+       fi
+       ;;
+    esac
+    ;;
+  psos*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  sunos4*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.x
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      lcc*)
+       # Lucid
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  solaris*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.2, 5.x and Centerline C++
+        archive_cmds_need_lc_CXX=yes
+       no_undefined_flag_CXX=' -zdefs'
+       archive_cmds_CXX='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+       hardcode_libdir_flag_spec_CXX='-R$libdir'
+       hardcode_shlibpath_var_CXX=no
+       case $host_os in
+         solaris2.[0-5] | solaris2.[0-5].*) ;;
+         *)
+           # The compiler driver will combine and reorder linker options,
+           # but understands `-z linker_flag'.
+           # Supported since Solaris 2.6 (maybe 2.5.1?)
+           whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+           ;;
+       esac
+       link_all_deplibs_CXX=yes
+
+       output_verbose_link_cmd='echo'
+
+       # Archives containing C++ object files must be created using
+       # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+       ;;
+      gcx*)
+       # Green Hills C++ Compiler
+       archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+       # The C++ compiler must be used to create the archive.
+       old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+       ;;
+      *)
+       # GNU C++ compiler with Solaris linker
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+         if $CC --version | grep -v '^2\.7' > /dev/null; then
+           archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         else
+           # g++ 2.7 appears to require `-G' NOT `-shared' on this
+           # platform.
+           archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         fi
+
+         hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+         case $host_os in
+         solaris2.[0-5] | solaris2.[0-5].*) ;;
+         *)
+           whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+           ;;
+         esac
+       fi
+       ;;
+    esac
+    ;;
+  sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+    no_undefined_flag_CXX='${wl}-z,text'
+    archive_cmds_need_lc_CXX=no
+    hardcode_shlibpath_var_CXX=no
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  sysv5* | sco3.2v5* | sco5v6*)
+    # Note: We can NOT use -z defs as we might desire, because we do not
+    # link with -lc, and that would cause any symbols used from libc to
+    # always be unresolved, which means just about no library would
+    # ever link correctly.  If we're not using GNU ld we use -z text
+    # though, which does catch some bad symbols but isn't as heavy-handed
+    # as -z defs.
+    # For security reasons, it is highly recommended that you always
+    # use absolute paths for naming shared libraries, and exclude the
+    # DT_RUNPATH tag from executables and libraries.  But doing so
+    # requires that you compile everything twice, which is a pain.
+    # So that behaviour is only enabled if SCOABSPATH is set to a
+    # non-empty value in the environment.  Most likely only useful for
+    # creating official distributions of packages.
+    # This is a hack until libtool officially supports absolute path
+    # names for shared libraries.
+    no_undefined_flag_CXX='${wl}-z,text'
+    allow_undefined_flag_CXX='${wl}-z,nodefs'
+    archive_cmds_need_lc_CXX=no
+    hardcode_shlibpath_var_CXX=no
+    hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+    hardcode_libdir_separator_CXX=':'
+    link_all_deplibs_CXX=yes
+    export_dynamic_flag_spec_CXX='${wl}-Bexport'
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  tandem*)
+    case $cc_basename in
+      NCC*)
+       # NonStop-UX NCC 3.20
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  vxworks*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  *)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+esac
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  # The `*' in the case matches for architectures that use `case' in
+  # $output_verbose_cmd can trigger glob expansion during the loop
+  # eval without this substitution.
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+  for p in `eval $output_verbose_link_cmd`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" \
+         || test $p = "-R"; then
+        prev=$p
+        continue
+       else
+        prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        case $p in
+        -L* | -R*)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$compiler_lib_search_path_CXX"; then
+            compiler_lib_search_path_CXX="${prev}${p}"
+          else
+            compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$postdeps_CXX"; then
+          postdeps_CXX="${prev}${p}"
+        else
+          postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+        fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$predep_objects_CXX"; then
+          predep_objects_CXX="$p"
+        else
+          predep_objects_CXX="$predep_objects_CXX $p"
+        fi
+       else
+        if test -z "$postdep_objects_CXX"; then
+          postdep_objects_CXX="$p"
+        else
+          postdep_objects_CXX="$postdep_objects_CXX $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix[3-9]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  predep_objects_CXX=
+  postdep_objects_CXX=
+  postdeps_CXX=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+    #
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+    if test "$solaris_use_stlport4" != yes; then
+      postdeps_CXX='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      postdeps_CXX='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    lt_prog_compiler_wl_CXX='-Wl,'
+    lt_prog_compiler_static_CXX='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_CXX='-Bstatic'
+      fi
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_CXX='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      lt_prog_compiler_pic_CXX=
+      ;;
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic_CXX=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       ;;
+      *)
+       lt_prog_compiler_pic_CXX='-fPIC'
+       ;;
+      esac
+      ;;
+    *)
+      lt_prog_compiler_pic_CXX='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix4* | aix5*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         lt_prog_compiler_static_CXX='-Bstatic'
+       else
+         lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+       darwin*)
+         # PIC is the default on this platform
+         # Common symbols not allowed in MH_DYLIB files
+         case $cc_basename in
+           xlc*)
+           lt_prog_compiler_pic_CXX='-qnocommon'
+           lt_prog_compiler_wl_CXX='-Wl,'
+           ;;
+         esac
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           lt_prog_compiler_pic_CXX='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           lt_prog_compiler_pic_CXX='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+           if test "$host_cpu" != ia64; then
+             lt_prog_compiler_pic_CXX='+Z'
+           fi
+           ;;
+         aCC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             lt_prog_compiler_pic_CXX='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_static_CXX='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           lt_prog_compiler_wl_CXX='--backend -Wl,'
+           lt_prog_compiler_pic_CXX='-fPIC'
+           ;;
+         icpc* | ecpc*)
+           # Intel C++
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_pic_CXX='-KPIC'
+           lt_prog_compiler_static_CXX='-static'
+           ;;
+         pgCC*)
+           # Portland Group C++ compiler.
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_pic_CXX='-fpic'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           lt_prog_compiler_pic_CXX=
+           lt_prog_compiler_static_CXX='-non_shared'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             lt_prog_compiler_pic_CXX='-KPIC'
+             lt_prog_compiler_static_CXX='-Bstatic'
+             lt_prog_compiler_wl_CXX='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           lt_prog_compiler_pic_CXX='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd*)
+       ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           lt_prog_compiler_wl_CXX='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           lt_prog_compiler_pic_CXX='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           lt_prog_compiler_wl_CXX='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           lt_prog_compiler_pic_CXX=
+           lt_prog_compiler_static_CXX='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           lt_prog_compiler_pic_CXX='-KPIC'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           lt_prog_compiler_wl_CXX='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           lt_prog_compiler_pic_CXX='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           lt_prog_compiler_pic_CXX='-pic'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           lt_prog_compiler_pic_CXX='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           lt_prog_compiler_pic_CXX='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_pic_CXX='-KPIC'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       lt_prog_compiler_can_build_shared_CXX=no
+       ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works_CXX=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:12459: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:12463: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works_CXX=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+    case $lt_prog_compiler_pic_CXX in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+     esac
+else
+    lt_prog_compiler_pic_CXX=
+     lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_CXX=
+    ;;
+  *)
+    lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works_CXX=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works_CXX=yes
+       fi
+     else
+       lt_prog_compiler_static_works_CXX=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
+    :
+else
+    lt_prog_compiler_static_CXX=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o_CXX=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:12563: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:12567: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_CXX=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix4* | aix5*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+    else
+      export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    export_symbols_cmds_CXX="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_CXX=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_CXX in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl_CXX
+       pic_flag=$lt_prog_compiler_pic_CXX
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+        allow_undefined_flag_CXX=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc_CXX=no
+        else
+         archive_cmds_need_lc_CXX=yes
+        fi
+        allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+   test -n "$runpath_var_CXX" || \
+   test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct_CXX" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+     test "$hardcode_minus_L_CXX" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_CXX=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_CXX=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_CXX=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_CXX \
+    CC_CXX \
+    LD_CXX \
+    lt_prog_compiler_wl_CXX \
+    lt_prog_compiler_pic_CXX \
+    lt_prog_compiler_static_CXX \
+    lt_prog_compiler_no_builtin_flag_CXX \
+    export_dynamic_flag_spec_CXX \
+    thread_safe_flag_spec_CXX \
+    whole_archive_flag_spec_CXX \
+    enable_shared_with_static_runtimes_CXX \
+    old_archive_cmds_CXX \
+    old_archive_from_new_cmds_CXX \
+    predep_objects_CXX \
+    postdep_objects_CXX \
+    predeps_CXX \
+    postdeps_CXX \
+    compiler_lib_search_path_CXX \
+    archive_cmds_CXX \
+    archive_expsym_cmds_CXX \
+    postinstall_cmds_CXX \
+    postuninstall_cmds_CXX \
+    old_archive_from_expsyms_cmds_CXX \
+    allow_undefined_flag_CXX \
+    no_undefined_flag_CXX \
+    export_symbols_cmds_CXX \
+    hardcode_libdir_flag_spec_CXX \
+    hardcode_libdir_flag_spec_ld_CXX \
+    hardcode_libdir_separator_CXX \
+    hardcode_automatic_CXX \
+    module_cmds_CXX \
+    module_expsym_cmds_CXX \
+    lt_cv_prog_compiler_c_o_CXX \
+    fix_srcfile_path_CXX \
+    exclude_expsyms_CXX \
+    include_expsyms_CXX; do
+
+    case $var in
+    old_archive_cmds_CXX | \
+    old_archive_from_new_cmds_CXX | \
+    archive_cmds_CXX | \
+    archive_expsym_cmds_CXX | \
+    module_cmds_CXX | \
+    module_expsym_cmds_CXX | \
+    old_archive_from_expsyms_cmds_CXX | \
+    export_symbols_cmds_CXX | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_CXX
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+       else
+         tagname=""
+       fi
+       ;;
+
+      F77)
+       if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="\
+      program t
+      end
+"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl_F77='-Wl,'
+    lt_prog_compiler_static_F77='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_F77='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_F77='-fno-common'
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared_F77=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic_F77=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_F77='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      lt_prog_compiler_pic_F77='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_F77='-Bstatic'
+      else
+       lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         lt_prog_compiler_pic_F77='-qnocommon'
+         lt_prog_compiler_wl_F77='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_F77='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static_F77='-non_shared'
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       lt_prog_compiler_wl_F77='-Wl,'
+       lt_prog_compiler_pic_F77='-KPIC'
+       lt_prog_compiler_static_F77='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl_F77='-Wl,'
+       lt_prog_compiler_pic_F77='-fpic'
+       lt_prog_compiler_static_F77='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl_F77='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static_F77='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic_F77='-KPIC'
+         lt_prog_compiler_static_F77='-Bstatic'
+         lt_prog_compiler_wl_F77='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic_F77='-KPIC'
+         lt_prog_compiler_static_F77='-Bstatic'
+         lt_prog_compiler_wl_F77=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static_F77='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static_F77='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       lt_prog_compiler_wl_F77='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl_F77='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl_F77='-Qoption ld '
+      lt_prog_compiler_pic_F77='-PIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic_F77='-Kconform_pic'
+       lt_prog_compiler_static_F77='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      lt_prog_compiler_can_build_shared_F77=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic_F77='-pic'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared_F77=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works_F77=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_F77"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:14125: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:14129: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works_F77=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+    case $lt_prog_compiler_pic_F77 in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+     esac
+else
+    lt_prog_compiler_pic_F77=
+     lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_F77=
+    ;;
+  *)
+    lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works_F77=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works_F77=yes
+       fi
+     else
+       lt_prog_compiler_static_works_F77=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_static_works_F77" = xyes; then
+    :
+else
+    lt_prog_compiler_static_F77=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o_F77=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:14229: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:14233: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_F77=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  runpath_var=
+  allow_undefined_flag_F77=
+  enable_shared_with_static_runtimes_F77=no
+  archive_cmds_F77=
+  archive_expsym_cmds_F77=
+  old_archive_From_new_cmds_F77=
+  old_archive_from_expsyms_cmds_F77=
+  export_dynamic_flag_spec_F77=
+  whole_archive_flag_spec_F77=
+  thread_safe_flag_spec_F77=
+  hardcode_libdir_flag_spec_F77=
+  hardcode_libdir_flag_spec_ld_F77=
+  hardcode_libdir_separator_F77=
+  hardcode_direct_F77=no
+  hardcode_minus_L_F77=no
+  hardcode_shlibpath_var_F77=unsupported
+  link_all_deplibs_F77=unknown
+  hardcode_automatic_F77=no
+  module_cmds_F77=
+  module_expsym_cmds_F77=
+  always_export_symbols_F77=no
+  export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms_F77=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs_F77=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec_F77=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs_F77=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_minus_L_F77=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      ld_shlibs_F77=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag_F77=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      allow_undefined_flag_F77=unsupported
+      always_export_symbols_F77=no
+      enable_shared_with_static_runtimes_F77=yes
+      export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct_F77=no
+      hardcode_shlibpath_var_F77=no
+      hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec_F77='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       ld_shlibs_F77=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs_F77=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           ld_shlibs_F77=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs_F77" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec_F77=
+      export_dynamic_flag_spec_F77=
+      whole_archive_flag_spec_F77=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag_F77=unsupported
+      always_export_symbols_F77=yes
+      archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L_F77=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct_F77=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds_F77=''
+      hardcode_direct_F77=yes
+      hardcode_libdir_separator_F77=':'
+      link_all_deplibs_F77=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct_F77=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L_F77=yes
+         hardcode_libdir_flag_spec_F77='-L$libdir'
+         hardcode_libdir_separator_F77=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols_F77=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag_F77='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+       archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag_F77="-z nodefs"
+         archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag_F77=' ${wl}-bernotok'
+         allow_undefined_flag_F77=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         whole_archive_flag_spec_F77='$convenience'
+         archive_cmds_need_lc_F77=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_minus_L_F77=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs_F77=no
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec_F77=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec_F77=' '
+      allow_undefined_flag_F77=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_From_new_cmds_F77='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes_F77=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      archive_cmds_need_lc_F77=no
+      hardcode_direct_F77=no
+      hardcode_automatic_F77=yes
+      hardcode_shlibpath_var_F77=unsupported
+      whole_archive_flag_spec_F77=''
+      link_all_deplibs_F77=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs_F77=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs_F77=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_F77=yes
+      hardcode_minus_L_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      hardcode_direct_F77=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L_F77=yes
+      export_dynamic_flag_spec_F77='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_F77=:
+
+       hardcode_direct_F77=yes
+       export_dynamic_flag_spec_F77='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L_F77=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_F77=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+         hardcode_direct_F77=no
+         hardcode_shlibpath_var_F77=no
+         ;;
+       *)
+         hardcode_direct_F77=yes
+         export_dynamic_flag_spec_F77='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L_F77=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+      fi
+      hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      link_all_deplibs_F77=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    newsos6)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_F77=yes
+      hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct_F77=yes
+       hardcode_shlibpath_var_F77=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec_F77='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec_F77='-R$libdir'
+            ;;
+          *)
+            archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_minus_L_F77=yes
+      allow_undefined_flag_F77=unsupported
+      archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag_F77=' -expect_unresolved \*'
+       archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag_F77=' -expect_unresolved \*'
+       archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec_F77='-rpath $libdir'
+      fi
+      hardcode_libdir_separator_F77=:
+      ;;
+
+    solaris*)
+      no_undefined_flag_F77=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_shlibpath_var_F77=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs_F77=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_direct_F77=yes
+      hardcode_minus_L_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_F77=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds_F77='$CC -r -o $output$reload_objs'
+         hardcode_direct_F77=no
+        ;;
+       motorola)
+         archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var_F77=no
+      export_dynamic_flag_spec_F77='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var_F77=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs_F77=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_F77='${wl}-z,text'
+      archive_cmds_need_lc_F77=no
+      hardcode_shlibpath_var_F77=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag_F77='${wl}-z,text'
+      allow_undefined_flag_F77='${wl}-z,nodefs'
+      archive_cmds_need_lc_F77=no
+      hardcode_shlibpath_var_F77=no
+      hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator_F77=':'
+      link_all_deplibs_F77=yes
+      export_dynamic_flag_spec_F77='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    *)
+      ld_shlibs_F77=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6; }
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_F77=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_F77 in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl_F77
+       pic_flag=$lt_prog_compiler_pic_F77
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+        allow_undefined_flag_F77=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc_F77=no
+        else
+         archive_cmds_need_lc_F77=yes
+        fi
+        allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+   test -n "$runpath_var_F77" || \
+   test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct_F77" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+     test "$hardcode_minus_L_F77" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_F77=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_F77=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_F77=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6; }
+
+if test "$hardcode_action_F77" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_F77 \
+    CC_F77 \
+    LD_F77 \
+    lt_prog_compiler_wl_F77 \
+    lt_prog_compiler_pic_F77 \
+    lt_prog_compiler_static_F77 \
+    lt_prog_compiler_no_builtin_flag_F77 \
+    export_dynamic_flag_spec_F77 \
+    thread_safe_flag_spec_F77 \
+    whole_archive_flag_spec_F77 \
+    enable_shared_with_static_runtimes_F77 \
+    old_archive_cmds_F77 \
+    old_archive_from_new_cmds_F77 \
+    predep_objects_F77 \
+    postdep_objects_F77 \
+    predeps_F77 \
+    postdeps_F77 \
+    compiler_lib_search_path_F77 \
+    archive_cmds_F77 \
+    archive_expsym_cmds_F77 \
+    postinstall_cmds_F77 \
+    postuninstall_cmds_F77 \
+    old_archive_from_expsyms_cmds_F77 \
+    allow_undefined_flag_F77 \
+    no_undefined_flag_F77 \
+    export_symbols_cmds_F77 \
+    hardcode_libdir_flag_spec_F77 \
+    hardcode_libdir_flag_spec_ld_F77 \
+    hardcode_libdir_separator_F77 \
+    hardcode_automatic_F77 \
+    module_cmds_F77 \
+    module_expsym_cmds_F77 \
+    lt_cv_prog_compiler_c_o_F77 \
+    fix_srcfile_path_F77 \
+    exclude_expsyms_F77 \
+    include_expsyms_F77; do
+
+    case $var in
+    old_archive_cmds_F77 | \
+    old_archive_from_new_cmds_F77 | \
+    archive_cmds_F77 | \
+    archive_expsym_cmds_F77 | \
+    module_cmds_F77 | \
+    module_expsym_cmds_F77 | \
+    old_archive_from_expsyms_cmds_F77 | \
+    export_symbols_cmds_F77 | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_F77
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_F77
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+       else
+         tagname=""
+       fi
+       ;;
+
+      GCJ)
+       if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+old_archive_cmds_GCJ=$old_archive_cmds
+
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+  lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:16416: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:16420: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl_GCJ='-Wl,'
+    lt_prog_compiler_static_GCJ='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_GCJ='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_GCJ='-fno-common'
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared_GCJ=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic_GCJ=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_GCJ='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      lt_prog_compiler_pic_GCJ='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_GCJ='-Bstatic'
+      else
+       lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         lt_prog_compiler_pic_GCJ='-qnocommon'
+         lt_prog_compiler_wl_GCJ='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_GCJ='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static_GCJ='-non_shared'
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       lt_prog_compiler_wl_GCJ='-Wl,'
+       lt_prog_compiler_pic_GCJ='-KPIC'
+       lt_prog_compiler_static_GCJ='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl_GCJ='-Wl,'
+       lt_prog_compiler_pic_GCJ='-fpic'
+       lt_prog_compiler_static_GCJ='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl_GCJ='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static_GCJ='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic_GCJ='-KPIC'
+         lt_prog_compiler_static_GCJ='-Bstatic'
+         lt_prog_compiler_wl_GCJ='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic_GCJ='-KPIC'
+         lt_prog_compiler_static_GCJ='-Bstatic'
+         lt_prog_compiler_wl_GCJ=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static_GCJ='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static_GCJ='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       lt_prog_compiler_wl_GCJ='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl_GCJ='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl_GCJ='-Qoption ld '
+      lt_prog_compiler_pic_GCJ='-PIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic_GCJ='-Kconform_pic'
+       lt_prog_compiler_static_GCJ='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      lt_prog_compiler_can_build_shared_GCJ=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic_GCJ='-pic'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared_GCJ=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works_GCJ=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:16706: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:16710: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works_GCJ=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+    case $lt_prog_compiler_pic_GCJ in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+     esac
+else
+    lt_prog_compiler_pic_GCJ=
+     lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_GCJ=
+    ;;
+  *)
+    lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works_GCJ=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works_GCJ=yes
+       fi
+     else
+       lt_prog_compiler_static_works_GCJ=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
+    :
+else
+    lt_prog_compiler_static_GCJ=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o_GCJ=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:16810: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:16814: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_GCJ=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  runpath_var=
+  allow_undefined_flag_GCJ=
+  enable_shared_with_static_runtimes_GCJ=no
+  archive_cmds_GCJ=
+  archive_expsym_cmds_GCJ=
+  old_archive_From_new_cmds_GCJ=
+  old_archive_from_expsyms_cmds_GCJ=
+  export_dynamic_flag_spec_GCJ=
+  whole_archive_flag_spec_GCJ=
+  thread_safe_flag_spec_GCJ=
+  hardcode_libdir_flag_spec_GCJ=
+  hardcode_libdir_flag_spec_ld_GCJ=
+  hardcode_libdir_separator_GCJ=
+  hardcode_direct_GCJ=no
+  hardcode_minus_L_GCJ=no
+  hardcode_shlibpath_var_GCJ=unsupported
+  link_all_deplibs_GCJ=unknown
+  hardcode_automatic_GCJ=no
+  module_cmds_GCJ=
+  module_expsym_cmds_GCJ=
+  always_export_symbols_GCJ=no
+  export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms_GCJ=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs_GCJ=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec_GCJ=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs_GCJ=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_minus_L_GCJ=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      ld_shlibs_GCJ=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag_GCJ=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      allow_undefined_flag_GCJ=unsupported
+      always_export_symbols_GCJ=no
+      enable_shared_with_static_runtimes_GCJ=yes
+      export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct_GCJ=no
+      hardcode_shlibpath_var_GCJ=no
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec_GCJ='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       ld_shlibs_GCJ=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs_GCJ=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           ld_shlibs_GCJ=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs_GCJ" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec_GCJ=
+      export_dynamic_flag_spec_GCJ=
+      whole_archive_flag_spec_GCJ=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag_GCJ=unsupported
+      always_export_symbols_GCJ=yes
+      archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L_GCJ=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct_GCJ=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds_GCJ=''
+      hardcode_direct_GCJ=yes
+      hardcode_libdir_separator_GCJ=':'
+      link_all_deplibs_GCJ=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct_GCJ=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L_GCJ=yes
+         hardcode_libdir_flag_spec_GCJ='-L$libdir'
+         hardcode_libdir_separator_GCJ=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols_GCJ=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag_GCJ='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+       archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag_GCJ="-z nodefs"
+         archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag_GCJ=' ${wl}-bernotok'
+         allow_undefined_flag_GCJ=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         whole_archive_flag_spec_GCJ='$convenience'
+         archive_cmds_need_lc_GCJ=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_minus_L_GCJ=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs_GCJ=no
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec_GCJ=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec_GCJ=' '
+      allow_undefined_flag_GCJ=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_From_new_cmds_GCJ='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes_GCJ=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      archive_cmds_need_lc_GCJ=no
+      hardcode_direct_GCJ=no
+      hardcode_automatic_GCJ=yes
+      hardcode_shlibpath_var_GCJ=unsupported
+      whole_archive_flag_spec_GCJ=''
+      link_all_deplibs_GCJ=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs_GCJ=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs_GCJ=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_GCJ=yes
+      hardcode_minus_L_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      hardcode_direct_GCJ=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L_GCJ=yes
+      export_dynamic_flag_spec_GCJ='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_GCJ=:
+
+       hardcode_direct_GCJ=yes
+       export_dynamic_flag_spec_GCJ='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L_GCJ=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_GCJ=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+         hardcode_direct_GCJ=no
+         hardcode_shlibpath_var_GCJ=no
+         ;;
+       *)
+         hardcode_direct_GCJ=yes
+         export_dynamic_flag_spec_GCJ='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L_GCJ=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+      fi
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      link_all_deplibs_GCJ=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    newsos6)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_GCJ=yes
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct_GCJ=yes
+       hardcode_shlibpath_var_GCJ=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec_GCJ='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec_GCJ='-R$libdir'
+            ;;
+          *)
+            archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_minus_L_GCJ=yes
+      allow_undefined_flag_GCJ=unsupported
+      archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag_GCJ=' -expect_unresolved \*'
+       archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag_GCJ=' -expect_unresolved \*'
+       archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+      fi
+      hardcode_libdir_separator_GCJ=:
+      ;;
+
+    solaris*)
+      no_undefined_flag_GCJ=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_shlibpath_var_GCJ=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs_GCJ=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_minus_L_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_GCJ=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+         hardcode_direct_GCJ=no
+        ;;
+       motorola)
+         archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var_GCJ=no
+      export_dynamic_flag_spec_GCJ='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var_GCJ=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs_GCJ=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_GCJ='${wl}-z,text'
+      archive_cmds_need_lc_GCJ=no
+      hardcode_shlibpath_var_GCJ=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag_GCJ='${wl}-z,text'
+      allow_undefined_flag_GCJ='${wl}-z,nodefs'
+      archive_cmds_need_lc_GCJ=no
+      hardcode_shlibpath_var_GCJ=no
+      hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator_GCJ=':'
+      link_all_deplibs_GCJ=yes
+      export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    *)
+      ld_shlibs_GCJ=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6; }
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_GCJ=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_GCJ in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl_GCJ
+       pic_flag=$lt_prog_compiler_pic_GCJ
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+        allow_undefined_flag_GCJ=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc_GCJ=no
+        else
+         archive_cmds_need_lc_GCJ=yes
+        fi
+        allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+   test -n "$runpath_var_GCJ" || \
+   test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct_GCJ" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+     test "$hardcode_minus_L_GCJ" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_GCJ=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_GCJ=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_GCJ=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6; }
+
+if test "$hardcode_action_GCJ" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_GCJ \
+    CC_GCJ \
+    LD_GCJ \
+    lt_prog_compiler_wl_GCJ \
+    lt_prog_compiler_pic_GCJ \
+    lt_prog_compiler_static_GCJ \
+    lt_prog_compiler_no_builtin_flag_GCJ \
+    export_dynamic_flag_spec_GCJ \
+    thread_safe_flag_spec_GCJ \
+    whole_archive_flag_spec_GCJ \
+    enable_shared_with_static_runtimes_GCJ \
+    old_archive_cmds_GCJ \
+    old_archive_from_new_cmds_GCJ \
+    predep_objects_GCJ \
+    postdep_objects_GCJ \
+    predeps_GCJ \
+    postdeps_GCJ \
+    compiler_lib_search_path_GCJ \
+    archive_cmds_GCJ \
+    archive_expsym_cmds_GCJ \
+    postinstall_cmds_GCJ \
+    postuninstall_cmds_GCJ \
+    old_archive_from_expsyms_cmds_GCJ \
+    allow_undefined_flag_GCJ \
+    no_undefined_flag_GCJ \
+    export_symbols_cmds_GCJ \
+    hardcode_libdir_flag_spec_GCJ \
+    hardcode_libdir_flag_spec_ld_GCJ \
+    hardcode_libdir_separator_GCJ \
+    hardcode_automatic_GCJ \
+    module_cmds_GCJ \
+    module_expsym_cmds_GCJ \
+    lt_cv_prog_compiler_c_o_GCJ \
+    fix_srcfile_path_GCJ \
+    exclude_expsyms_GCJ \
+    include_expsyms_GCJ; do
+
+    case $var in
+    old_archive_cmds_GCJ | \
+    old_archive_from_new_cmds_GCJ | \
+    archive_cmds_GCJ | \
+    archive_expsym_cmds_GCJ | \
+    module_cmds_GCJ | \
+    module_expsym_cmds_GCJ | \
+    old_archive_from_expsyms_cmds_GCJ | \
+    export_symbols_cmds_GCJ | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_GCJ
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+       else
+         tagname=""
+       fi
+       ;;
+
+      RC)
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_RC \
+    CC_RC \
+    LD_RC \
+    lt_prog_compiler_wl_RC \
+    lt_prog_compiler_pic_RC \
+    lt_prog_compiler_static_RC \
+    lt_prog_compiler_no_builtin_flag_RC \
+    export_dynamic_flag_spec_RC \
+    thread_safe_flag_spec_RC \
+    whole_archive_flag_spec_RC \
+    enable_shared_with_static_runtimes_RC \
+    old_archive_cmds_RC \
+    old_archive_from_new_cmds_RC \
+    predep_objects_RC \
+    postdep_objects_RC \
+    predeps_RC \
+    postdeps_RC \
+    compiler_lib_search_path_RC \
+    archive_cmds_RC \
+    archive_expsym_cmds_RC \
+    postinstall_cmds_RC \
+    postuninstall_cmds_RC \
+    old_archive_from_expsyms_cmds_RC \
+    allow_undefined_flag_RC \
+    no_undefined_flag_RC \
+    export_symbols_cmds_RC \
+    hardcode_libdir_flag_spec_RC \
+    hardcode_libdir_flag_spec_ld_RC \
+    hardcode_libdir_separator_RC \
+    hardcode_automatic_RC \
+    module_cmds_RC \
+    module_expsym_cmds_RC \
+    lt_cv_prog_compiler_c_o_RC \
+    fix_srcfile_path_RC \
+    exclude_expsyms_RC \
+    include_expsyms_RC; do
+
+    case $var in
+    old_archive_cmds_RC | \
+    old_archive_from_new_cmds_RC | \
+    archive_cmds_RC | \
+    archive_expsym_cmds_RC | \
+    module_cmds_RC | \
+    module_expsym_cmds_RC | \
+    old_archive_from_expsyms_cmds_RC | \
+    export_symbols_cmds_RC | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_RC
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_RC
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+       ;;
+
+      *)
+       { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+   { (exit 1); exit 1; }; }
+       ;;
+      esac
+
+      # Append the new tag name to the list of available tags.
+      if test -n "$tagname" ; then
+      available_tags="$available_tags $tagname"
+    fi
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+  else
+    rm -f "${ofile}T"
+    { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking if --enable-debug option specified" >&5
+echo $ECHO_N "checking if --enable-debug option specified... $ECHO_C" >&6; }
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then
+  enableval=$enable_debug; vi_cv_debug=$enableval
+else
+  vi_cv_debug="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_debug" >&5
+echo "${ECHO_T}$vi_cv_debug" >&6; }
+if test "$vi_cv_debug" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define DEBUG 1
+_ACEOF
+
+       OPTFLAG=${OPTFLAG-"-g"}
+       no_op_OPTFLAG=${no_op_OPTFLAG-"-g"}
+fi
+
+
+
+case "$host_os" in
+aix3.2.5)  OPTFLAG=${OPTFLAG-"-O"};;
+aix4.1*)   CFLAGS=${CFLAGS-"-qstrict"}
+          OPTFLAG=${OPTFLAG-"-O3"};;
+aux*)     CPPFLAGS=${CPPFLAGS-"-ZP -D_BSD_SOURCE -D_SYSV_SOURCE -D_AUX_SOURCE"}
+          LDFLAGS=${LDFLAGS-"-ZP"}
+          OPTFLAG=${OPTFLAG-"-O"};;
+bsd4.4)    OPTFLAG=${OPTFLAG-"-O2"};;
+bsdi*)    CC=${CC-"shlicc"}
+          OPTFLAG=${OPTFLAG-"-O2"};;
+irix6*)           OPTFLAG=${OPTFLAG-"-O2"};;
+irix*)    OPTFLAG=${OPTFLAG-"-O2"};;
+lynxos*)   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC"   am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+          { echo "$as_me:$LINENO: checking for GNU C (gcc) version 2.x" >&5
+echo $ECHO_N "checking for GNU C (gcc) version 2.x... $ECHO_C" >&6; }
+          ac_cv_gcc_vers=`${CC-cc} -v 2>&1 | \
+               grep "gcc version " | sed 's/.*version //'`
+          ac_cv_gcc_major=`echo "$ac_cv_gcc_vers" | sed 's/\..*//'`
+          if test "$ac_cv_gcc_major" = "2" ; then
+               { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+          else
+               { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+               { echo "$as_me:$LINENO: WARNING: Nvi requires gcc 2.x to build on LynxOS." >&5
+echo "$as_me: WARNING: Nvi requires gcc 2.x to build on LynxOS." >&2;}
+               { { echo "$as_me:$LINENO: error: See build/README.LynxOS for more information." >&5
+echo "$as_me: error: See build/README.LynxOS for more information." >&2;}
+   { (exit 1); exit 1; }; }
+          fi;;
+nextstep3) CPPFLAGS=${CPPFLAGS-"-w -pipe -posix"}
+          LDFLAGS=${LDFLAGS-"-posix"}
+          OPTFLAG=${OPTFLAG-"-O2"};;
+osf*)     CFLAGS=${CFLAGS-"-Olimit 1000"};;
+solaris*)  no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+sunos*)           no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+esac
+
+
+OPTFLAG=${OPTFLAG-"-O"}
+
+
+CC=${CC-cc}
+CFLAGS=${CFLAGS-""}
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC"   am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+if test "$GCC" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_GCC 1
+_ACEOF
+
+fi
+
+
+no_op_OPTFLAG=${no_op_OPTFLAG-"$OPTFLAG"}
+
+case "$host_os" in
+bsdi2.1)   LIBS=${LIBS-"-lipc"};;
+dgux*)    LIBS=${LIBS-"-ldgc"};;
+irix6*)           LIBS=${LIBS-"-lbsd"};;
+irix*)    LIBS=${LIBS-"-lc_s -lbsd"};;
+isc*)     LIBS=${LIBS-"-lcposix -linet"};;
+netbsd1*)  LIBS=${LIBS-"-lcrypt"};;
+ptx*)     LIBS=${LIBS-"-lseq -linet -lsocket"};;
+sco3.2*)   LIBS=${LIBS-"-lsocket"};;
+sinix*)           LIBS=${LIBS-"-lelf -lc"};;
+solaris*)  LIBS=${LIBS-"-lsocket -lnsl -ldl"};;
+wgs*)     LIBS=${LIBS-"-lnsl"};;
+esac
+
+case "$host_os" in
+aux*)     LIBOBJS="getopt.o strpbrk.o $LIBOBJS";;
+esac
+
+case "$host_os" in
+ultrix*)   cat >>confdefs.h <<\_ACEOF
+#define HAVE_BROKEN_VDISABLE 1
+_ACEOF
+;;
+esac
+
+{ echo "$as_me:$LINENO: checking whether recording of pathnames of libraries is enabled" >&5
+echo $ECHO_N "checking whether recording of pathnames of libraries is enabled... $ECHO_C" >&6; }
+# Check whether --enable-runpath was given.
+if test "${enable_runpath+set}" = set; then
+  enableval=$enable_runpath; vi_cv_runpath="$enableval"
+else
+  vi_cv_runpath="yes"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_runpath" >&5
+echo "${ECHO_T}$vi_cv_runpath" >&6; }
+
+if test "X$vi_cv_runpath" = "Xyes"; then
+       LRscript='s/^\(.*\)/-R\1 -L\1 /'
+else
+       LRscript='s/^\(.*\)/-L\1 /'
+fi
+
+{ echo "$as_me:$LINENO: checking if --enable-trace option specified" >&5
+echo $ECHO_N "checking if --enable-trace option specified... $ECHO_C" >&6; }
+# Check whether --enable-trace was given.
+if test "${enable_trace+set}" = set; then
+  enableval=$enable_trace; vi_cv_trace="yes"
+else
+  vi_cv_trace="no"
+fi
+
+if test "$vi_cv_trace" = yes; then
+       CPPFLAGS="-DTRACE $CPPFLAGS"
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_trace" >&5
+echo "${ECHO_T}$vi_cv_trace" >&6; }
+
+CPPFLAGS="$ADDCPPFLAGS $CPPFLAGS"
+
+LDFLAGS="$ADDLDFLAGS $LDFLAGS"
+
+LIBS="$ADDLIBS $LIBS"
+
+PATH="$PATH:/usr/bin:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib:/usr/ucblib"
+
+# Extract the first word of "sh", so it can be a program name with args.
+set dummy sh; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_shell+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_shell in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_shell="$vi_cv_path_shell" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_shell="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_shell" && ac_cv_path_vi_cv_path_shell="no"
+  ;;
+esac
+fi
+vi_cv_path_shell=$ac_cv_path_vi_cv_path_shell
+if test -n "$vi_cv_path_shell"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_shell" >&5
+echo "${ECHO_T}$vi_cv_path_shell" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+if test "$vi_cv_path_shell" = no; then
+       { { echo "$as_me:$LINENO: error: No shell utility found." >&5
+echo "$as_me: error: No shell utility found." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# Extract the first word of "sendmail", so it can be a program name with args.
+set dummy sendmail; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_sendmail+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_sendmail in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_sendmail="$vi_cv_path_sendmail" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_sendmail="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_sendmail" && ac_cv_path_vi_cv_path_sendmail="no"
+  ;;
+esac
+fi
+vi_cv_path_sendmail=$ac_cv_path_vi_cv_path_sendmail
+if test -n "$vi_cv_path_sendmail"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_sendmail" >&5
+echo "${ECHO_T}$vi_cv_path_sendmail" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+if test "$vi_cv_path_sendmail" = no; then
+       { echo "$as_me:$LINENO: WARNING: No sendmail utility found;" >&5
+echo "$as_me: WARNING: No sendmail utility found;" >&2;}
+       { echo "$as_me:$LINENO: WARNING:     users will not be told of saved files." >&5
+echo "$as_me: WARNING:     users will not be told of saved files." >&2;}
+fi
+
+
+for ac_prog in perl5 perl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_perl+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_perl in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_perl="$vi_cv_path_perl" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_perl="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+vi_cv_path_perl=$ac_cv_path_vi_cv_path_perl
+if test -n "$vi_cv_path_perl"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_perl" >&5
+echo "${ECHO_T}$vi_cv_path_perl" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$vi_cv_path_perl" && break
+done
+test -n "$vi_cv_path_perl" || vi_cv_path_perl="no"
+
+
+
+{ echo "$as_me:$LINENO: checking for preserve directory" >&5
+echo $ECHO_N "checking for preserve directory... $ECHO_C" >&6; }
+if test "${vi_cv_path_preserve+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       dirlist="/var/preserve /var/tmp /usr/tmp"
+       vi_cv_path_preserve=no
+       for i in $dirlist; do
+               if test -d $i/vi.recover; then
+                       vi_cv_path_preserve=$i/vi.recover
+                       break;
+               fi
+       done
+       if test "$vi_cv_path_preserve" = no; then
+               for i in $dirlist; do
+                       if test -d $i -a -w $i; then
+                               vi_cv_path_preserve=$i/vi.recover
+                               break;
+                       fi
+               done
+
+       fi
+fi
+
+if test "$vi_cv_path_preserve" = no; then
+       { { echo "$as_me:$LINENO: error: No writeable preserve directory found." >&5
+echo "$as_me: error: No writeable preserve directory found." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_path_preserve" >&5
+echo "${ECHO_T}$vi_cv_path_preserve" >&6; }
+# Extract the first word of "fuser", so it can be a program name with args.
+set dummy fuser; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_fuser+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_fuser in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_fuser="$vi_cv_path_fuser" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_fuser="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_fuser" && ac_cv_path_vi_cv_path_fuser="no"
+  ;;
+esac
+fi
+vi_cv_path_fuser=$ac_cv_path_vi_cv_path_fuser
+if test -n "$vi_cv_path_fuser"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_fuser" >&5
+echo "${ECHO_T}$vi_cv_path_fuser" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "lsof", so it can be a program name with args.
+set dummy lsof; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_lsof+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_lsof in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_lsof="$vi_cv_path_lsof" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_lsof="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_lsof" && ac_cv_path_vi_cv_path_lsof="no"
+  ;;
+esac
+fi
+vi_cv_path_lsof=$ac_cv_path_vi_cv_path_lsof
+if test -n "$vi_cv_path_lsof"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_lsof" >&5
+echo "${ECHO_T}$vi_cv_path_lsof" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+INUSE=""
+if test "$vi_cv_path_lsof" != no; then
+       INUSE='test `lsof -t $i`'
+fi
+if test "$vi_cv_path_fuser" != no; then
+       INUSE='fuser -s $i'
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+# Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_ar+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_ar in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_ar="$vi_cv_path_ar" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_ar="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_ar" && ac_cv_path_vi_cv_path_ar="missing_ar"
+  ;;
+esac
+fi
+vi_cv_path_ar=$ac_cv_path_vi_cv_path_ar
+if test -n "$vi_cv_path_ar"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_ar" >&5
+echo "${ECHO_T}$vi_cv_path_ar" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "chmod", so it can be a program name with args.
+set dummy chmod; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_chmod+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_chmod in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_chmod="$vi_cv_path_chmod" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_chmod="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_chmod" && ac_cv_path_vi_cv_path_chmod="missing_chmod"
+  ;;
+esac
+fi
+vi_cv_path_chmod=$ac_cv_path_vi_cv_path_chmod
+if test -n "$vi_cv_path_chmod"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_chmod" >&5
+echo "${ECHO_T}$vi_cv_path_chmod" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "cp", so it can be a program name with args.
+set dummy cp; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_cp+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_cp in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_cp="$vi_cv_path_cp" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_cp="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_cp" && ac_cv_path_vi_cv_path_cp="missing_cp"
+  ;;
+esac
+fi
+vi_cv_path_cp=$ac_cv_path_vi_cv_path_cp
+if test -n "$vi_cv_path_cp"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_cp" >&5
+echo "${ECHO_T}$vi_cv_path_cp" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "ln", so it can be a program name with args.
+set dummy ln; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_ln+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_ln in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_ln="$vi_cv_path_ln" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_ln="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_ln" && ac_cv_path_vi_cv_path_ln="missing_ln"
+  ;;
+esac
+fi
+vi_cv_path_ln=$ac_cv_path_vi_cv_path_ln
+if test -n "$vi_cv_path_ln"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_ln" >&5
+echo "${ECHO_T}$vi_cv_path_ln" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "mkdir", so it can be a program name with args.
+set dummy mkdir; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_mkdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_mkdir in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_mkdir="$vi_cv_path_mkdir" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_mkdir="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_mkdir" && ac_cv_path_vi_cv_path_mkdir="missing_mkdir"
+  ;;
+esac
+fi
+vi_cv_path_mkdir=$ac_cv_path_vi_cv_path_mkdir
+if test -n "$vi_cv_path_mkdir"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_mkdir" >&5
+echo "${ECHO_T}$vi_cv_path_mkdir" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_rm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_rm in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_rm="$vi_cv_path_rm" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_rm="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_rm" && ac_cv_path_vi_cv_path_rm="missing_rm"
+  ;;
+esac
+fi
+vi_cv_path_rm=$ac_cv_path_vi_cv_path_rm
+if test -n "$vi_cv_path_rm"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_rm" >&5
+echo "${ECHO_T}$vi_cv_path_rm" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_ranlib+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_ranlib in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_ranlib="$vi_cv_path_ranlib" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_ranlib="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_ranlib" && ac_cv_path_vi_cv_path_ranlib="missing_ranlib"
+  ;;
+esac
+fi
+vi_cv_path_ranlib=$ac_cv_path_vi_cv_path_ranlib
+if test -n "$vi_cv_path_ranlib"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_ranlib" >&5
+echo "${ECHO_T}$vi_cv_path_ranlib" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_strip+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_strip in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_strip="$vi_cv_path_strip" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_strip="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_strip" && ac_cv_path_vi_cv_path_strip="missing_strip"
+  ;;
+esac
+fi
+vi_cv_path_strip=$ac_cv_path_vi_cv_path_strip
+if test -n "$vi_cv_path_strip"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_strip" >&5
+echo "${ECHO_T}$vi_cv_path_strip" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for X" >&5
+echo $ECHO_N "checking for X... $ECHO_C" >&6; }
+
+
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then
+  withval=$with_x;
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+  # The user explicitly disabled X.
+  have_x=disabled
+else
+  case $x_includes,$x_libraries in #(
+    *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5
+echo "$as_me: error: Cannot use X directory names containing '" >&2;}
+   { (exit 1); exit 1; }; };; #(
+    *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=no ac_x_libraries=no
+rm -f -r conftest.dir
+if mkdir conftest.dir; then
+  cd conftest.dir
+  cat >Imakefile <<'_ACEOF'
+incroot:
+       @echo incroot='${INCROOT}'
+usrlibdir:
+       @echo usrlibdir='${USRLIBDIR}'
+libdir:
+       @echo libdir='${LIBDIR}'
+_ACEOF
+  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
+    # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+    for ac_var in incroot usrlibdir libdir; do
+      eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+    done
+    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+    for ac_extension in a so sl; do
+      if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+        test -f "$ac_im_libdir/libX11.$ac_extension"; then
+       ac_im_usrlibdir=$ac_im_libdir; break
+      fi
+    done
+    # Screen out bogus values from the imake configuration.  They are
+    # bogus both because they are the default anyway, and because
+    # using them would break gcc on systems where it needs fixed includes.
+    case $ac_im_incroot in
+       /usr/include) ac_x_includes= ;;
+       *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
+    esac
+    case $ac_im_usrlibdir in
+       /usr/lib | /lib) ;;
+       *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
+    esac
+  fi
+  cd ..
+  rm -f -r conftest.dir
+fi
+
+# Standard set of common directories for X headers.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ac_x_header_dirs='
+/usr/X11/include
+/usr/X11R6/include
+/usr/X11R5/include
+/usr/X11R4/include
+
+/usr/include/X11
+/usr/include/X11R6
+/usr/include/X11R5
+/usr/include/X11R4
+
+/usr/local/X11/include
+/usr/local/X11R6/include
+/usr/local/X11R5/include
+/usr/local/X11R4/include
+
+/usr/local/include/X11
+/usr/local/include/X11R6
+/usr/local/include/X11R5
+/usr/local/include/X11R4
+
+/usr/X386/include
+/usr/x386/include
+/usr/XFree86/include/X11
+
+/usr/include
+/usr/local/include
+/usr/unsupported/include
+/usr/athena/include
+/usr/local/x11r5/include
+/usr/lpp/Xamples/include
+
+/usr/openwin/include
+/usr/openwin/share/include'
+
+if test "$ac_x_includes" = no; then
+  # Guess where to find include files, by looking for Xlib.h.
+  # First, try using that file with no special directory specified.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  for ac_dir in $ac_x_header_dirs; do
+  if test -r "$ac_dir/X11/Xlib.h"; then
+    ac_x_includes=$ac_dir
+    break
+  fi
+done
+fi
+
+rm -f conftest.err conftest.$ac_ext
+fi # $ac_x_includes = no
+
+if test "$ac_x_libraries" = no; then
+  # Check for the libraries.
+  # See if we find them without any special options.
+  # Don't add to $LIBS permanently.
+  ac_save_LIBS=$LIBS
+  LIBS="-lX11 $LIBS"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+int
+main ()
+{
+XrmInitialize ()
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  LIBS=$ac_save_LIBS
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       LIBS=$ac_save_LIBS
+for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+do
+  # Don't even attempt the hair of trying to link an X program!
+  for ac_extension in a so sl; do
+    if test -r "$ac_dir/libX11.$ac_extension"; then
+      ac_x_libraries=$ac_dir
+      break 2
+    fi
+  done
+done
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi # $ac_x_libraries = no
+
+case $ac_x_includes,$ac_x_libraries in #(
+  no,* | *,no | *\'*)
+    # Didn't find X, or a directory has "'" in its name.
+    ac_cv_have_x="have_x=no";; #(
+  *)
+    # Record where we found X for the cache.
+    ac_cv_have_x="have_x=yes\
+       ac_x_includes='$ac_x_includes'\
+       ac_x_libraries='$ac_x_libraries'"
+esac
+fi
+;; #(
+    *) have_x=yes;;
+  esac
+  eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+  { echo "$as_me:$LINENO: result: $have_x" >&5
+echo "${ECHO_T}$have_x" >&6; }
+  no_x=yes
+else
+  # If each of the values was on the command line, it overrides each guess.
+  test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+  test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+  # Update the cache value to reflect the command line values.
+  ac_cv_have_x="have_x=yes\
+       ac_x_includes='$x_includes'\
+       ac_x_libraries='$x_libraries'"
+  { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5
+echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; }
+fi
+
+
+if test "$no_x" != yes; then
+       if test "X$x_libraries" != "X"; then
+               XLIBS="`echo $x_libraries | sed "$LRscript"` $XLIBS"
+       fi
+       XLIBS="$XLIBS -lX11"
+       if test "X$x_includes" != "X"; then
+               XINCS="-I$x_includes"
+       fi
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking if --enable-widechar option specified" >&5
+echo $ECHO_N "checking if --enable-widechar option specified... $ECHO_C" >&6; }
+# Check whether --enable-widechar was given.
+if test "${enable_widechar+set}" = set; then
+  enableval=$enable_widechar; vi_cv_widechar=$enableval
+else
+  vi_cv_widechar="no"
+fi
+
+if test "$vi_cv_widechar" = "yes"; then
+       cat >>confdefs.h <<\_ACEOF
+#define USE_WIDECHAR 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_widechar" >&5
+echo "${ECHO_T}$vi_cv_widechar" >&6; }
+
+if test "${ac_cv_header_langinfo_h+set}" = set; then
+  { echo "$as_me:$LINENO: checking for langinfo.h" >&5
+echo $ECHO_N "checking for langinfo.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_langinfo_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_langinfo_h" >&5
+echo "${ECHO_T}$ac_cv_header_langinfo_h" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking langinfo.h usability" >&5
+echo $ECHO_N "checking langinfo.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <langinfo.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking langinfo.h presence" >&5
+echo $ECHO_N "checking langinfo.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <langinfo.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: langinfo.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: langinfo.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: langinfo.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: langinfo.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: langinfo.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: langinfo.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: langinfo.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: langinfo.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: langinfo.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: langinfo.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: langinfo.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: langinfo.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: langinfo.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: langinfo.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: langinfo.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: langinfo.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for langinfo.h" >&5
+echo $ECHO_N "checking for langinfo.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_langinfo_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_langinfo_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_langinfo_h" >&5
+echo "${ECHO_T}$ac_cv_header_langinfo_h" >&6; }
+
+fi
+if test $ac_cv_header_langinfo_h = yes; then
+
+       if test "${ac_cv_header_iconv_h+set}" = set; then
+  { echo "$as_me:$LINENO: checking for iconv.h" >&5
+echo $ECHO_N "checking for iconv.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_iconv_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_iconv_h" >&5
+echo "${ECHO_T}$ac_cv_header_iconv_h" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking iconv.h usability" >&5
+echo $ECHO_N "checking iconv.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <iconv.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking iconv.h presence" >&5
+echo $ECHO_N "checking iconv.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <iconv.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: iconv.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: iconv.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: iconv.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: iconv.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: iconv.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: iconv.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: iconv.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: iconv.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: iconv.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: iconv.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: iconv.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: iconv.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: iconv.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: iconv.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: iconv.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: iconv.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for iconv.h" >&5
+echo $ECHO_N "checking for iconv.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_iconv_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_iconv_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_iconv_h" >&5
+echo "${ECHO_T}$ac_cv_header_iconv_h" >&6; }
+
+fi
+if test $ac_cv_header_iconv_h = yes; then
+
+               cat >>confdefs.h <<\_ACEOF
+#define USE_ICONV 1
+_ACEOF
+
+
+for ac_func in iswblank
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+
+
+fi
+
+
+
+fi
+
+
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking if --enable-gtk option specified" >&5
+echo $ECHO_N "checking if --enable-gtk option specified... $ECHO_C" >&6; }
+# Check whether --enable-gtk was given.
+if test "${enable_gtk+set}" = set; then
+  enableval=$enable_gtk; vi_cv_gtk=$enableval
+else
+  vi_cv_gtk="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_gtk" >&5
+echo "${ECHO_T}$vi_cv_gtk" >&6; }
+if test "$vi_cv_gtk" = "yes"; then
+       #
+       # Find pkg-config
+       #
+       # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
+echo "${ECHO_T}$PKG_CONFIG" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+       if test x$PKG_CONFIG = xno ; then
+           if test "$vi_cv_widechar" = "yes"; then
+               { { echo "$as_me:$LINENO: error: *** pkg-config not found. See http://pkgconfig.sourceforge.net" >&5
+echo "$as_me: error: *** pkg-config not found. See http://pkgconfig.sourceforge.net" >&2;}
+   { (exit 1); exit 1; }; }
+           fi
+
+       else
+           if ! $PKG_CONFIG --atleast-pkgconfig-version 0.5 ; then
+               if test "$vi_cv_widechar" = "yes"; then
+                   { { echo "$as_me:$LINENO: error: *** pkg-config too old; version 0.5 or better required." >&5
+echo "$as_me: error: *** pkg-config too old; version 0.5 or better required." >&2;}
+   { (exit 1); exit 1; }; }
+               fi
+               PKG_CONFIG=no
+           fi
+
+       fi
+       if test x$PKG_CONFIG = xno ; then
+           PKG_CONFIG=/bin/false
+       fi
+
+       vi_programs="$vi_programs vi-gtk"
+       vi_ipc=vi-ipc
+       { echo "$as_me:$LINENO: checking for gtk+" >&5
+echo $ECHO_N "checking for gtk+... $ECHO_C" >&6; }
+       if $PKG_CONFIG gtk+-2.0 ; then
+             GTKINCS=`$PKG_CONFIG --cflags gtk+-2.0`
+             GTKLIBS=`$PKG_CONFIG --libs gtk+-2.0`
+
+             { echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6; }
+             cat >>confdefs.h <<\_ACEOF
+#define HAVE_PANGO 1
+_ACEOF
+
+       else
+           if test "$vi_cv_widechar" = "yes"; then
+               { { echo "$as_me:$LINENO: error:
+*** gtk+-2.0 is required. The latest version of gtk
+*** is always available from ftp://ftp.gtk.org/.
+               " >&5
+echo "$as_me: error:
+*** gtk+-2.0 is required. The latest version of gtk
+*** is always available from ftp://ftp.gtk.org/.
+               " >&2;}
+   { (exit 1); exit 1; }; }
+           else
+
+# Check whether --with-gtk-prefix was given.
+if test "${with_gtk_prefix+set}" = set; then
+  withval=$with_gtk_prefix; gtk_config_prefix="$withval"
+else
+  gtk_config_prefix=""
+fi
+
+
+# Check whether --with-gtk-exec-prefix was given.
+if test "${with_gtk_exec_prefix+set}" = set; then
+  withval=$with_gtk_exec_prefix; gtk_config_exec_prefix="$withval"
+else
+  gtk_config_exec_prefix=""
+fi
+
+# Check whether --enable-gtktest was given.
+if test "${enable_gtktest+set}" = set; then
+  enableval=$enable_gtktest;
+else
+  enable_gtktest=yes
+fi
+
+
+  for module in .
+  do
+      case "$module" in
+         gthread)
+             gtk_config_args="$gtk_config_args gthread"
+         ;;
+      esac
+  done
+
+  if test x$gtk_config_exec_prefix != x ; then
+     gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+     fi
+  fi
+  if test x$gtk_config_prefix != x ; then
+     gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+     fi
+  fi
+
+  # Extract the first word of "gtk-config", so it can be a program name with args.
+set dummy gtk-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_GTK_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $GTK_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_GTK_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_GTK_CONFIG" && ac_cv_path_GTK_CONFIG="no"
+  ;;
+esac
+fi
+GTK_CONFIG=$ac_cv_path_GTK_CONFIG
+if test -n "$GTK_CONFIG"; then
+  { echo "$as_me:$LINENO: result: $GTK_CONFIG" >&5
+echo "${ECHO_T}$GTK_CONFIG" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  min_gtk_version=1.2.0
+  { echo "$as_me:$LINENO: checking for GTK - version >= $min_gtk_version" >&5
+echo $ECHO_N "checking for GTK - version >= $min_gtk_version... $ECHO_C" >&6; }
+  no_gtk=""
+  if test "$GTK_CONFIG" = "no" ; then
+    no_gtk=yes
+  else
+    GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+    GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+    gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+    gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+    gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+    if test "x$enable_gtktest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GTK_CFLAGS"
+      LIBS="$GTK_LIBS $LIBS"
+      rm -f conf.gtktest
+      if test "$cross_compiling" = yes; then
+  echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtktest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtk_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtk_version");
+     exit(1);
+   }
+
+  if ((gtk_major_version != $gtk_config_major_version) ||
+      (gtk_minor_version != $gtk_config_minor_version) ||
+      (gtk_micro_version != $gtk_config_micro_version))
+    {
+      printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n",
+             $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+             gtk_major_version, gtk_minor_version, gtk_micro_version);
+      printf ("*** was found! If gtk-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+      printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    }
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+  else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+          (gtk_minor_version != GTK_MINOR_VERSION) ||
+           (gtk_micro_version != GTK_MICRO_VERSION))
+    {
+      printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+            GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+            gtk_major_version, gtk_minor_version, gtk_micro_version);
+    }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+  else
+    {
+      if ((gtk_major_version > major) ||
+        ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+        ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+               gtk_major_version, gtk_minor_version, gtk_micro_version);
+        printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+              major, minor, micro);
+        printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+no_gtk=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtk" = x ; then
+     { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+     :
+  else
+     { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+     if test "$GTK_CONFIG" = "no" ; then
+       echo "*** The gtk-config script installed by GTK could not be found"
+       echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTK_CONFIG environment variable to the"
+       echo "*** full path to gtk-config."
+     else
+       if test -f conf.gtktest ; then
+        :
+       else
+          echo "*** Could not run GTK test program, checking why..."
+          CFLAGS="$CFLAGS $GTK_CFLAGS"
+          LIBS="$LIBS $GTK_LIBS"
+          cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+   echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK or finding the wrong"
+          echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+         echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+          echo "***"
+          echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+          echo "*** came with the system with the command"
+          echo "***"
+          echo "***    rpm --erase --nodeps gtk gtk-devel"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+        echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+          echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtk-config script: $GTK_CONFIG"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTK_CFLAGS=""
+     GTK_LIBS=""
+     :
+  fi
+
+
+  rm -f conf.gtktest
+
+               GTKINCS="$GTK_CFLAGS"
+               GTKLIBS="$GTK_LIBS $LIBS"
+           fi
+       fi
+
+       SAVELIBS="$LIBS"
+       LIBS="-lutil $GTKLIBS"
+       { echo "$as_me:$LINENO: checking for zvt_get_ptys in -lnvizvt" >&5
+echo $ECHO_N "checking for zvt_get_ptys in -lnvizvt... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nvizvt_zvt_get_ptys+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnvizvt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char zvt_get_ptys ();
+int
+main ()
+{
+return zvt_get_ptys ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_nvizvt_zvt_get_ptys=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_nvizvt_zvt_get_ptys=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nvizvt_zvt_get_ptys" >&5
+echo "${ECHO_T}$ac_cv_lib_nvizvt_zvt_get_ptys" >&6; }
+if test $ac_cv_lib_nvizvt_zvt_get_ptys = yes; then
+  vi_cv_zvt="yes"
+else
+  vi_cv_zvt="no"
+fi
+
+       if test "$vi_cv_zvt" = "yes"; then
+               GTKLIBS="-lnvizvt $LIBS"
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_ZVT 1
+_ACEOF
+
+       fi
+       LIBS="$SAVELIBS"
+#      AC_PATH_PROG(vi_cv_gnome_config, gnome-config, no)
+#      if test "$vi_cv_gnome_config" != "no"; then
+#              ZVTLIBS=`$vi_cv_gnome_config zvt --libs`
+#              GTKLIBS="$ZVTLIBS $GTKLIBS"
+#      fi
+fi
+
+
+{ echo "$as_me:$LINENO: checking if --enable-motif option specified" >&5
+echo $ECHO_N "checking if --enable-motif option specified... $ECHO_C" >&6; }
+# Check whether --enable-motif was given.
+if test "${enable_motif+set}" = set; then
+  enableval=$enable_motif; vi_cv_motif=$enableval
+else
+  vi_cv_motif="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_motif" >&5
+echo "${ECHO_T}$vi_cv_motif" >&6; }
+if test "$vi_cv_motif" = "yes"; then
+       vi_programs="$vi_programs vi-motif"
+       vi_ipc=vi-ipc
+
+
+       case "$host_os" in
+       bsdi*)  CC=cc;;
+       esac
+
+
+       MOTIFLIBS="-lXm -lXt"
+       { echo "$as_me:$LINENO: checking for main in -lSM" >&5
+echo $ECHO_N "checking for main in -lSM... $ECHO_C" >&6; }
+if test "${ac_cv_lib_SM_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSM "$XLIBS" $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_SM_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_SM_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_SM_main" >&5
+echo "${ECHO_T}$ac_cv_lib_SM_main" >&6; }
+if test $ac_cv_lib_SM_main = yes; then
+  vi_cv_smlib="yes"
+else
+  vi_cv_smlib="no"
+fi
+
+       if test "$vi_cv_smlib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lSM"
+       fi
+       { echo "$as_me:$LINENO: checking for main in -lICE" >&5
+echo $ECHO_N "checking for main in -lICE... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ICE_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lICE "$XLIBS" $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_ICE_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_ICE_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_main" >&5
+echo "${ECHO_T}$ac_cv_lib_ICE_main" >&6; }
+if test $ac_cv_lib_ICE_main = yes; then
+  vi_cv_icelib="yes"
+else
+  vi_cv_icelib="no"
+fi
+
+       if test "$vi_cv_icelib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lICE"
+       fi
+       { echo "$as_me:$LINENO: checking for main in -lXext" >&5
+echo $ECHO_N "checking for main in -lXext... $ECHO_C" >&6; }
+if test "${ac_cv_lib_Xext_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXext "$XLIBS" $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_Xext_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_Xext_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_main" >&5
+echo "${ECHO_T}$ac_cv_lib_Xext_main" >&6; }
+if test $ac_cv_lib_Xext_main = yes; then
+  vi_cv_xextlib="yes"
+else
+  vi_cv_xextlib="no"
+fi
+
+       if test "$vi_cv_xextlib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lXext"
+       fi
+       { echo "$as_me:$LINENO: checking for main in -lXpm" >&5
+echo $ECHO_N "checking for main in -lXpm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_Xpm_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXpm "$XLIBS" $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_Xpm_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_Xpm_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_Xpm_main" >&5
+echo "${ECHO_T}$ac_cv_lib_Xpm_main" >&6; }
+if test $ac_cv_lib_Xpm_main = yes; then
+  vi_cv_xpmlib="yes"
+else
+  vi_cv_xpmlib="no"
+fi
+
+       if test "$vi_cv_xpmlib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lXpm"
+       fi
+       MOTIFLIBS="$MOTIFLIBS $XLIBS -lm $LIBS"
+fi
+
+
+{ echo "$as_me:$LINENO: checking if --enable-threads option specified" >&5
+echo $ECHO_N "checking if --enable-threads option specified... $ECHO_C" >&6; }
+# Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then
+  enableval=$enable_threads; vi_cv_threads=$enableval
+else
+  vi_cv_threads="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_threads" >&5
+echo "${ECHO_T}$vi_cv_threads" >&6; }
+if test "$vi_cv_threads" = "yes"; then
+       LIBS="$LIBS -lpthread"
+       if test "${vi_cv_have_pthreads+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <pthread.h>
+int
+main ()
+{
+pthread_self()
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_pthreads=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_pthreads=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_pthreads" = "no"; then
+               { { echo "$as_me:$LINENO: error: No threading library found" >&5
+echo "$as_me: error: No threading library found" >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       IPCOBJS="pthread.o $IPCOBJS"
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD 1
+_ACEOF
+
+else
+       IPCOBJS="nothread.o $IPCOBJS"
+fi
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking if --enable-perlinterp option specified" >&5
+echo $ECHO_N "checking if --enable-perlinterp option specified... $ECHO_C" >&6; }
+# Check whether --enable-perlinterp was given.
+if test "${enable_perlinterp+set}" = set; then
+  enableval=$enable_perlinterp; vi_cv_perlinterp=$enableval
+else
+  vi_cv_perlinterp="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_perlinterp" >&5
+echo "${ECHO_T}$vi_cv_perlinterp" >&6; }
+if test "$vi_cv_perlinterp" = "yes"; then
+       if test "$vi_cv_path_perl" = no; then
+               { { echo "$as_me:$LINENO: error: No perl5 utility found." >&5
+echo "$as_me: error: No perl5 utility found." >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       $vi_cv_path_perl -e 'require 5.004' || {
+               { { echo "$as_me:$LINENO: error: perl5 must be version 5.004 or later." >&5
+echo "$as_me: error: perl5 must be version 5.004 or later." >&2;}
+   { (exit 1); exit 1; }; }
+       }
+       if test "$vi_cv_threads" = "yes"; then
+               useithreads=`$vi_cv_path_perl -MConfig -e 'print $Config{useithreads}'`
+               if test "X$useithreads" != "Xdefine"; then
+                       { { echo "$as_me:$LINENO: error: vi threading only compatible with perl's ithreads." >&5
+echo "$as_me: error: vi threading only compatible with perl's ithreads." >&2;}
+   { (exit 1); exit 1; }; }
+               fi
+       fi
+
+       eval `$vi_cv_path_perl -V:shrpenv`
+       vi_cv_perllib=`$vi_cv_path_perl -MConfig -e 'print $Config{privlib}'`
+       perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+               -e 'ccflags;perl_inc'`
+       if test "X$perlcppflags" != "X"; then
+               CPPFLAGS="$perlcppflags $CPPFLAGS"
+       fi
+       perllibs=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+               -e 'ldopts'`
+       perlldflags=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+               -e 'ccdlflags'`
+       LIBOBJS="perl.o perlxsi.o perlsfio.o $LIBOBJS"
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_PERL_INTERP 1
+_ACEOF
+
+       { echo "$as_me:$LINENO: checking whether we need to use perl's setenv" >&5
+echo $ECHO_N "checking whether we need to use perl's setenv... $ECHO_C" >&6; }
+if test "${vi_cv_perl_setenv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+               if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+int main(){
+#if defined(USE_ENVIRON_ARRAY) && !defined(PERL_USE_SAFE_PUTENV)
+exit(0);
+#else
+exit(1);
+#endif
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_perl_setenv=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_perl_setenv=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_perl_setenv" >&5
+echo "${ECHO_T}$vi_cv_perl_setenv" >&6; }
+       if test "$vi_cv_perl_setenv" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define USE_PERL_SETENV 1
+_ACEOF
+
+       fi
+fi
+
+{ echo "$as_me:$LINENO: checking if --enable-tclinterp option specified" >&5
+echo $ECHO_N "checking if --enable-tclinterp option specified... $ECHO_C" >&6; }
+# Check whether --enable-tclinterp was given.
+if test "${enable_tclinterp+set}" = set; then
+  enableval=$enable_tclinterp; vi_cv_tclinterp=$enableval
+else
+  vi_cv_tclinterp="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_tclinterp" >&5
+echo "${ECHO_T}$vi_cv_tclinterp" >&6; }
+if test "$vi_cv_tclinterp" = "yes"; then
+       { echo "$as_me:$LINENO: checking for tclConfig.sh" >&5
+echo $ECHO_N "checking for tclConfig.sh... $ECHO_C" >&6; }
+       if test "${vi_cv_tclconfig+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+               vi_cv_tclconfig=`$srcdir/findconfig`
+fi
+
+       { echo "$as_me:$LINENO: result: $vi_cv_tclconfig" >&5
+echo "${ECHO_T}$vi_cv_tclconfig" >&6; }
+       if test "x$vi_cv_tclconfig" = x; then
+               { { echo "$as_me:$LINENO: error: No Tcl library found;" >&5
+echo "$as_me: error: No Tcl library found;" >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       . $vi_cv_tclconfig
+       LIBOBJS="tcl.o $LIBOBJS"
+       LIBS="$TCL_LIB_SPEC $TCL_LIBS $LIBS"
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_TCL_INTERP 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+       SAVELIBS="$LIBS"
+       SAVELDFLAGS="$LDFLAGS"
+       SAVECPPFLAGS="$CPPFLAGS"
+
+# Check whether --with-curses was given.
+if test "${with_curses+set}" = set; then
+  withval=$with_curses;
+fi
+
+       if test "x$with_curses" != "x"; then
+               CURSLDFLAGS="`echo $with_curses/lib | sed "$LRscript"` $CURSLDFLAGS"
+               CURSCPPFLAGS="-I$with_curses/include $CURSCPPFLAGS"
+       fi;
+       LDFLAGS="$CURSLDFLAGS $LDFLAGS"
+       CPPFLAGS="$CURSCPPFLAGS $CPPFLAGS"
+
+       if test "$vi_cv_widechar" = "yes"; then
+           for vi_cv_curses in ncurses ncursesw curses; do
+               as_ac_Lib=`echo "ac_cv_lib_$vi_cv_curses''_waddnwstr" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for waddnwstr in -l$vi_cv_curses" >&5
+echo $ECHO_N "checking for waddnwstr in -l$vi_cv_curses... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$vi_cv_curses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char waddnwstr ();
+int
+main ()
+{
+return waddnwstr ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_Lib=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Lib=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  break
+fi
+
+               vi_cv_curses=unknown
+           done
+       else
+           for vi_cv_curses in ncurses ncursesw curses; do
+               as_ac_Lib=`echo "ac_cv_lib_$vi_cv_curses''_initscr" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for initscr in -l$vi_cv_curses" >&5
+echo $ECHO_N "checking for initscr in -l$vi_cv_curses... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$vi_cv_curses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char initscr ();
+int
+main ()
+{
+return initscr ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_Lib=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Lib=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  break
+fi
+
+               vi_cv_curses=unknown
+           done
+       fi
+
+       if test "$vi_cv_curses" != "unknown"; then
+           CURSHEADER=curses.h
+           if test "$vi_cv_curses" = "ncurses"; then
+
+for ac_header in ncurses.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ CURSHEADER=ncurses.h
+fi
+
+done
+
+           fi
+           if test "$vi_cv_curses" = "ncursesw"; then
+
+for ac_header in ncursesw/ncurses.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ CURSHEADER=ncursesw/ncurses.h
+fi
+
+done
+
+           fi
+           vi_programs="vi $vi_programs"
+           CURSLIBS="-l$vi_cv_curses"
+       else
+           { echo "$as_me:$LINENO: WARNING: *** No suitable curses library found." >&5
+echo "$as_me: WARNING: *** No suitable curses library found." >&2;}
+           if test "$vi_programs"X = X; then
+               { { echo "$as_me:$LINENO: error: No executable to build." >&5
+echo "$as_me: error: No executable to build." >&2;}
+   { (exit 1); exit 1; }; }
+           fi
+       fi
+
+as_ac_Lib=`echo "ac_cv_lib_$vi_cv_curses''_tgetent" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for tgetent in -l$vi_cv_curses" >&5
+echo $ECHO_N "checking for tgetent in -l$vi_cv_curses... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$vi_cv_curses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent ();
+int
+main ()
+{
+return tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_Lib=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Lib=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  vi_cv_curses_tgetent=yes
+else
+  vi_cv_curses_tgetent=no
+fi
+
+if test "$vi_cv_curses_tgetent" = no; then
+       { echo "$as_me:$LINENO: checking for tgetent in -ltermlib" >&5
+echo $ECHO_N "checking for tgetent in -ltermlib... $ECHO_C" >&6; }
+if test "${ac_cv_lib_termlib_tgetent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltermlib  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent ();
+int
+main ()
+{
+return tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_termlib_tgetent=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_termlib_tgetent=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_termlib_tgetent" >&5
+echo "${ECHO_T}$ac_cv_lib_termlib_tgetent" >&6; }
+if test $ac_cv_lib_termlib_tgetent = yes; then
+  vi_cv_termlib=-ltermlib
+else
+  vi_cv_termlib=no
+fi
+
+       if test "$vi_cv_termlib" = no; then
+               { echo "$as_me:$LINENO: checking for tgetent in -ltermcap" >&5
+echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6; }
+if test "${ac_cv_lib_termcap_tgetent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltermcap  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent ();
+int
+main ()
+{
+return tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_termcap_tgetent=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_termcap_tgetent=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_termcap_tgetent" >&5
+echo "${ECHO_T}$ac_cv_lib_termcap_tgetent" >&6; }
+if test $ac_cv_lib_termcap_tgetent = yes; then
+  vi_cv_termlib=-ltermcap
+else
+  vi_cv_termlib=no
+fi
+
+       fi
+fi
+if test "$vi_cv_termlib" != no; then
+       CURSLIBS="$CURSLIBS $vi_cv_termlib"
+fi
+
+       LIBS="$SAVELIBS"
+       LDFLAGS="$SAVELDFLAGS"
+       CPPFLAGS="$SAVECPPFLAGS"
+
+{ echo "$as_me:$LINENO: checking for sys/mman.h" >&5
+echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6; }
+if test "${vi_cv_include_sys_mman+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/mman.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  vi_cv_include_sys_mman=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  vi_cv_include_sys_mman=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+fi
+
+if test "$vi_cv_include_sys_mman" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_MMAN_H 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_include_sys_mman" >&5
+echo "${ECHO_T}$vi_cv_include_sys_mman" >&6; }
+
+{ echo "$as_me:$LINENO: checking for sys/select.h" >&5
+echo $ECHO_N "checking for sys/select.h... $ECHO_C" >&6; }
+if test "${vi_cv_include_sys_select+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/select.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  vi_cv_include_sys_select=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  vi_cv_include_sys_select=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+fi
+
+if test "$vi_cv_include_sys_select" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_SELECT_H 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_include_sys_select" >&5
+echo "${ECHO_T}$vi_cv_include_sys_select" >&6; }
+
+{ echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_ssize_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef ssize_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_ssize_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_ssize_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6; }
+if test $ac_cv_type_ssize_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if  ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+       && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long int l;
+    char c[sizeof (long int)];
+  } u;
+  u.l = 1;
+  return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for struct stat.st_blksize" >&5
+echo $ECHO_N "checking for struct stat.st_blksize... $ECHO_C" >&6; }
+if test "${ac_cv_member_struct_stat_st_blksize+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_blksize)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_blksize=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_blksize)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_blksize=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_member_struct_stat_st_blksize=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_blksize" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_blksize" >&6; }
+if test $ac_cv_member_struct_stat_st_blksize = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ST_BLKSIZE 1
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for mode_t" >&5
+echo $ECHO_N "checking for mode_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_mode_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef mode_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_mode_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_mode_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5
+echo "${ECHO_T}$ac_cv_type_mode_t" >&6; }
+if test $ac_cv_type_mode_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define mode_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef off_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_off_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_pid_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef pid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_pid_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_pid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6; }
+if test $ac_cv_type_pid_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; }
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+                                    int *p = &tm.tm_sec;
+                                    return !p;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_struct_tm=sys/time.h
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+for ac_func in bsearch gethostname memchr memset
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+
+
+
+
+
+for ac_func in mkstemp mmap strdup strpbrk
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+
+
+
+for ac_func in snprintf vsnprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+
+
+
+for ac_func in select
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in setenv
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ need_env=no
+else
+  need_env=yes
+fi
+done
+
+
+for ac_func in strsep
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ need_strsep=no
+else
+  need_strsep=yes
+fi
+done
+
+
+for ac_func in unsetenv
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  need_env=yes
+fi
+done
+
+
+
+
+for ac_header in stdlib.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking for working mmap" >&5
+echo $ECHO_N "checking for working mmap... $ECHO_C" >&6; }
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+       mmap private not fixed
+       mmap private fixed at somewhere currently unmapped
+       mmap private fixed at somewhere already mapped
+       mmap shared not fixed
+       mmap shared fixed at somewhere currently unmapped
+       mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the file system buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propagated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#ifndef HAVE_GETPAGESIZE
+/* Assume that all systems that can run configure have sys/param.h.  */
+# ifndef HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  ifdef HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192  /* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+  char *data, *data2, *data3;
+  int i, pagesize;
+  int fd;
+
+  pagesize = getpagesize ();
+
+  /* First, make a file with some known garbage in it. */
+  data = (char *) malloc (pagesize);
+  if (!data)
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    *(data + i) = rand ();
+  umask (0);
+  fd = creat ("conftest.mmap", 0600);
+  if (fd < 0)
+    return 1;
+  if (write (fd, data, pagesize) != pagesize)
+    return 1;
+  close (fd);
+
+  /* Next, try to mmap the file at a fixed address which already has
+     something else allocated at it.  If we can, also make sure that
+     we see the same garbage.  */
+  fd = open ("conftest.mmap", O_RDWR);
+  if (fd < 0)
+    return 1;
+  data2 = (char *) malloc (2 * pagesize);
+  if (!data2)
+    return 1;
+  data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1);
+  if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+                    MAP_PRIVATE | MAP_FIXED, fd, 0L))
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data2 + i))
+      return 1;
+
+  /* Finally, make sure that changes to the mapped area do not
+     percolate back to the file as seen by read().  (This is a bug on
+     some variants of i386 svr4.0.)  */
+  for (i = 0; i < pagesize; ++i)
+    *(data2 + i) = *(data2 + i) + 1;
+  data3 = (char *) malloc (pagesize);
+  if (!data3)
+    return 1;
+  if (read (fd, data3, pagesize) != pagesize)
+    return 1;
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data3 + i))
+      return 1;
+  close (fd);
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6; }
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+rm -f conftest.mmap
+
+
+for ac_header in vfork.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_func in fork vfork
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+  { echo "$as_me:$LINENO: checking for working fork" >&5
+echo $ECHO_N "checking for working fork... $ECHO_C" >&6; }
+if test "${ac_cv_func_fork_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_fork_works=cross
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+         /* By Ruediger Kuhlmann. */
+         return fork () < 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_fork_works=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_fork_works" >&5
+echo "${ECHO_T}$ac_cv_func_fork_works" >&6; }
+
+else
+  ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+  case $host in
+    *-*-amigaos* | *-*-msdosdjgpp*)
+      # Override, as these systems have only a dummy fork() stub
+      ac_cv_func_fork_works=no
+      ;;
+    *)
+      ac_cv_func_fork_works=yes
+      ;;
+  esac
+  { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+  { echo "$as_me:$LINENO: checking for working vfork" >&5
+echo $ECHO_N "checking for working vfork... $ECHO_C" >&6; }
+if test "${ac_cv_func_vfork_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_vfork_works=cross
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Thanks to Paul Eggert for this test.  */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+   argument registers are propagated back to the parent.  The compiler
+   is told about this with #include <vfork.h>, but some compilers
+   (e.g. gcc -O) don't grok <vfork.h>.  Test for this by using a
+   static variable whose address is put into a register that is
+   clobbered by the vfork.  */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+  static pid_t child;
+  if (!child) {
+    child = vfork ();
+    if (child < 0) {
+      perror ("vfork");
+      _exit(2);
+    }
+    if (!child) {
+      arg = getpid();
+      write(-1, "", 0);
+      _exit (arg);
+    }
+  }
+}
+
+int
+main ()
+{
+  pid_t parent = getpid ();
+  pid_t child;
+
+  sparc_address_test (0);
+
+  child = vfork ();
+
+  if (child == 0) {
+    /* Here is another test for sparc vfork register problems.  This
+       test uses lots of local variables, at least as many local
+       variables as main has allocated so far including compiler
+       temporaries.  4 locals are enough for gcc 1.40.3 on a Solaris
+       4.1.3 sparc, but we use 8 to be safe.  A buggy compiler should
+       reuse the register of parent for one of the local variables,
+       since it will think that parent can't possibly be used any more
+       in this routine.  Assigning to the local variable will thus
+       munge parent in the parent process.  */
+    pid_t
+      p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+      p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+    /* Convince the compiler that p..p7 are live; otherwise, it might
+       use the same hardware register for all 8 local variables.  */
+    if (p != p1 || p != p2 || p != p3 || p != p4
+       || p != p5 || p != p6 || p != p7)
+      _exit(1);
+
+    /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+       from child file descriptors.  If the child closes a descriptor
+       before it execs or exits, this munges the parent's descriptor
+       as well.  Test for this by closing stdout in the child.  */
+    _exit(close(fileno(stdout)) != 0);
+  } else {
+    int status;
+    struct stat st;
+
+    while (wait(&status) != child)
+      ;
+    return (
+        /* Was there some problem with vforking?  */
+        child < 0
+
+        /* Did the child fail?  (This shouldn't happen.)  */
+        || status
+
+        /* Did the vfork/compiler bug occur?  */
+        || parent != getpid()
+
+        /* Did the file descriptor bug occur?  */
+        || fstat(fileno(stdout), &st) != 0
+        );
+  }
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_vfork_works=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_vfork_works" >&5
+echo "${ECHO_T}$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+  ac_cv_func_vfork_works=$ac_cv_func_vfork
+  { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_VFORK 1
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define vfork fork
+_ACEOF
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_FORK 1
+_ACEOF
+
+fi
+
+
+if test "$need_env" = yes; then
+       LIBOBJS="env.o $LIBOBJS"
+fi
+
+if test "$need_strsep" = yes; then
+       LIBOBJS="strsep.o $LIBOBJS"
+fi
+
+{ echo "$as_me:$LINENO: checking for fcntl/flock" >&5
+echo $ECHO_N "checking for fcntl/flock... $ECHO_C" >&6; }
+if test "${vi_cv_lock+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       vi_cv_lock=none
+       case "$host_os" in
+       dgux*);;
+       irix*);;
+       *)
+               cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <fcntl.h>
+int
+main ()
+{
+flock(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_lock=flock
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext;;
+       esac
+       if test "$vi_cv_lock" = none; then
+               cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <fcntl.h>
+int
+main ()
+{
+fcntl(0, F_SETLK, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_lock=fcntl
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+       fi
+fi
+
+
+if test "$vi_cv_lock" = flock; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOCK_FLOCK 1
+_ACEOF
+
+fi
+if test "$vi_cv_lock" = fcntl; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOCK_FCNTL 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_lock" >&5
+echo "${ECHO_T}$vi_cv_lock" >&6; }
+
+{ echo "$as_me:$LINENO: checking for ftruncate/chsize" >&5
+echo $ECHO_N "checking for ftruncate/chsize... $ECHO_C" >&6; }
+if test "${vi_cv_ftruncate+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <unistd.h>
+int
+main ()
+{
+ftruncate(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_ftruncate=ftruncate
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <unistd.h>
+int
+main ()
+{
+chsize(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_ftruncate=chsize
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_ftruncate=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test "$vi_cv_ftruncate" = ftruncate; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_FTRUNCATE_FTRUNCATE 1
+_ACEOF
+
+fi
+if test "$vi_cv_ftruncate" = chsize; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_FTRUNCATE_CHSIZE 1
+_ACEOF
+
+fi
+if test "$vi_cv_ftruncate" = no; then
+       { { echo "$as_me:$LINENO: error: No file truncation system call." >&5
+echo "$as_me: error: No file truncation system call." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_ftruncate" >&5
+echo "${ECHO_T}$vi_cv_ftruncate" >&6; }
+
+CSAVELIBS="$LIBS"
+CSAVELDFLAGS="$LDFLAGS"
+CSAVECPPFLAGS="$CPPFLAGS"
+LIBS="$CURSLIBS $LIBS"
+LDFLAGS="$CURSLDFLAGS $LDFLAGS"
+CPPFLAGS="$CURSCPPFLAGS $CPPFLAGS"
+{ echo "$as_me:$LINENO: checking for tigetstr/tigetnum" >&5
+echo $ECHO_N "checking for tigetstr/tigetnum... $ECHO_C" >&6; }
+if test "${vi_cv_have_curses_tigetstr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+tigetstr(0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_tigetstr=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_tigetstr=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test "$vi_cv_have_curses_tigetstr" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_TIGETSTR 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_have_curses_tigetstr" >&5
+echo "${ECHO_T}$vi_cv_have_curses_tigetstr" >&6; }
+
+if test "$vi_cv_curses" = "bundled curses"; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_BSD_CURSES 1
+_ACEOF
+
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_WADDNSTR 1
+_ACEOF
+
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_IDLOK 1
+_ACEOF
+
+else
+               { echo "$as_me:$LINENO: checking for waddnstr" >&5
+echo $ECHO_N "checking for waddnstr... $ECHO_C" >&6; }
+       if test "${vi_cv_have_curses_waddnstr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+waddnstr(stdscr, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_waddnstr=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_waddnstr=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_curses_waddnstr" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_WADDNSTR 1
+_ACEOF
+
+       fi
+       { echo "$as_me:$LINENO: result: $vi_cv_have_curses_waddnstr" >&5
+echo "${ECHO_T}$vi_cv_have_curses_waddnstr" >&6; }
+
+               { echo "$as_me:$LINENO: checking for beep" >&5
+echo $ECHO_N "checking for beep... $ECHO_C" >&6; }
+       if test "${vi_cv_have_curses_beep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+beep();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_beep=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_beep=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_curses_beep" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_BEEP 1
+_ACEOF
+
+       fi
+       { echo "$as_me:$LINENO: result: $vi_cv_have_curses_beep" >&5
+echo "${ECHO_T}$vi_cv_have_curses_beep" >&6; }
+
+               { echo "$as_me:$LINENO: checking for flash" >&5
+echo $ECHO_N "checking for flash... $ECHO_C" >&6; }
+       if test "${vi_cv_have_curses_flash+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+flash();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_flash=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_flash=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_curses_flash" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_FLASH 1
+_ACEOF
+
+       fi
+       { echo "$as_me:$LINENO: result: $vi_cv_have_curses_flash" >&5
+echo "${ECHO_T}$vi_cv_have_curses_flash" >&6; }
+
+               { echo "$as_me:$LINENO: checking for idlok" >&5
+echo $ECHO_N "checking for idlok... $ECHO_C" >&6; }
+       if test "${vi_cv_have_curses_idlok+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+idlok(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_idlok=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_idlok=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_curses_idlok" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_IDLOK 1
+_ACEOF
+
+       fi
+       { echo "$as_me:$LINENO: result: $vi_cv_have_curses_idlok" >&5
+echo "${ECHO_T}$vi_cv_have_curses_idlok" >&6; }
+
+               { echo "$as_me:$LINENO: checking for keypad" >&5
+echo $ECHO_N "checking for keypad... $ECHO_C" >&6; }
+       if test "${vi_cv_have_curses_keypad+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+keypad(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_keypad=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_keypad=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_curses_keypad" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_KEYPAD 1
+_ACEOF
+
+       fi
+       { echo "$as_me:$LINENO: result: $vi_cv_have_curses_keypad" >&5
+echo "${ECHO_T}$vi_cv_have_curses_keypad" >&6; }
+
+               { echo "$as_me:$LINENO: checking for newterm" >&5
+echo $ECHO_N "checking for newterm... $ECHO_C" >&6; }
+       if test "${vi_cv_have_curses_newterm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+newterm(0, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_newterm=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_newterm=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+       if test "$vi_cv_have_curses_newterm" = yes; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_NEWTERM 1
+_ACEOF
+
+       fi
+       { echo "$as_me:$LINENO: result: $vi_cv_have_curses_newterm" >&5
+echo "${ECHO_T}$vi_cv_have_curses_newterm" >&6; }
+
+       if test "$vi_cv_have_curses_newterm" = no; then
+               cat >>confdefs.h <<\_ACEOF
+#define HAVE_BSD_CURSES 1
+_ACEOF
+
+       fi
+fi
+
+{ echo "$as_me:$LINENO: checking for setupterm" >&5
+echo $ECHO_N "checking for setupterm... $ECHO_C" >&6; }
+if test "${vi_cv_have_curses_setupterm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$CURSHEADER>
+int
+main ()
+{
+setupterm(0, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_have_curses_setupterm=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_have_curses_setupterm=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test "$vi_cv_have_curses_setupterm" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_SETUPTERM 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_have_curses_setupterm" >&5
+echo "${ECHO_T}$vi_cv_have_curses_setupterm" >&6; }
+LIBS="$CSAVELIBS"
+LDFLAGS="$CSAVELDFLAGS"
+CPPFLAGS="$CSAVECPPFLAGS"
+
+{ echo "$as_me:$LINENO: checking for broken gettimeofday system call" >&5
+echo $ECHO_N "checking for broken gettimeofday system call... $ECHO_C" >&6; }
+if test "${vi_cv_gettimeofday+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+int
+main ()
+{
+gettimeofday(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_gettimeofday=okay
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_gettimeofday=broken
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test "$vi_cv_gettimeofday" = broken; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_BROKEN_GETTIMEOFDAY 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_gettimeofday" >&5
+echo "${ECHO_T}$vi_cv_gettimeofday" >&6; }
+
+{ echo "$as_me:$LINENO: checking for System V pty calls" >&5
+echo $ECHO_N "checking for System V pty calls... $ECHO_C" >&6; }
+if test "${vi_cv_sys5_pty+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+grantpt(0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_sys5_pty=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_sys5_pty=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test "$vi_cv_sys5_pty" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS5_PTY 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_sys5_pty" >&5
+echo "${ECHO_T}$vi_cv_sys5_pty" >&6; }
+
+{ echo "$as_me:$LINENO: checking for revoke system call" >&5
+echo $ECHO_N "checking for revoke system call... $ECHO_C" >&6; }
+if test "${vi_cv_revoke+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+revoke("a");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_revoke=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_revoke=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test "$vi_cv_revoke" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_REVOKE 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_revoke" >&5
+echo "${ECHO_T}$vi_cv_revoke" >&6; }
+
+{ echo "$as_me:$LINENO: checking for int type sprintf return value" >&5
+echo $ECHO_N "checking for int type sprintf return value... $ECHO_C" >&6; }
+if test "${vi_cv_sprintf_count+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){char buf[20]; exit(sprintf(buf, "XXX") != 3);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_sprintf_count=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_sprintf_count=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+if test "$vi_cv_sprintf_count" = no; then
+       cat >>confdefs.h <<\_ACEOF
+#define SPRINTF_RET_CHARPNT 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_sprintf_count" >&5
+echo "${ECHO_T}$vi_cv_sprintf_count" >&6; }
+
+
+
+{ echo "$as_me:$LINENO: checking for u_char" >&5
+echo $ECHO_N "checking for u_char... $ECHO_C" >&6; }
+if test "${vi_cv_uchar+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_char foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_uchar=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_uchar=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_uchar" >&5
+echo "${ECHO_T}$vi_cv_uchar" >&6; }
+if test "$vi_cv_uchar" = no; then
+       u_char_decl="typedef unsigned char u_char;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for u_short" >&5
+echo $ECHO_N "checking for u_short... $ECHO_C" >&6; }
+if test "${vi_cv_ushort+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_short foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_ushort=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_ushort=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_ushort" >&5
+echo "${ECHO_T}$vi_cv_ushort" >&6; }
+if test "$vi_cv_ushort" = no; then
+       u_short_decl="typedef unsigned short u_short;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for u_int" >&5
+echo $ECHO_N "checking for u_int... $ECHO_C" >&6; }
+if test "${vi_cv_uint+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_int foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_uint=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_uint=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_uint" >&5
+echo "${ECHO_T}$vi_cv_uint" >&6; }
+if test "$vi_cv_uint" = no; then
+       u_int_decl="typedef unsigned int u_int;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for u_long" >&5
+echo $ECHO_N "checking for u_long... $ECHO_C" >&6; }
+if test "${vi_cv_ulong+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_long foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_ulong=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_ulong=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_ulong" >&5
+echo "${ECHO_T}$vi_cv_ulong" >&6; }
+if test "$vi_cv_ulong" = no; then
+       u_long_decl="typedef unsigned long u_long;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for u_int8_t" >&5
+echo $ECHO_N "checking for u_int8_t... $ECHO_C" >&6; }
+if test "${vi_cv_uint8+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_int8_t foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_uint8=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(unsigned char) != 1);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_uint8="unsigned char"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_uint8=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_uint8" >&5
+echo "${ECHO_T}$vi_cv_uint8" >&6; }
+if test "$vi_cv_uint8" = no; then
+       { { echo "$as_me:$LINENO: error: No unsigned 8-bit integral type." >&5
+echo "$as_me: error: No unsigned 8-bit integral type." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test "$vi_cv_uint8" != yes; then
+       u_int8_decl="typedef $vi_cv_uint8 u_int8_t;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for u_int16_t" >&5
+echo $ECHO_N "checking for u_int16_t... $ECHO_C" >&6; }
+if test "${vi_cv_uint16+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_int16_t foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_uint16=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(unsigned short) != 2);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_uint16="unsigned short"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(unsigned int) != 2);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_uint16="unsigned int"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_uint16=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_uint16" >&5
+echo "${ECHO_T}$vi_cv_uint16" >&6; }
+if test "$vi_cv_uint16" = no; then
+       { { echo "$as_me:$LINENO: error: No unsigned 16-bit integral type." >&5
+echo "$as_me: error: No unsigned 16-bit integral type." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test "$vi_cv_uint16" != yes; then
+       u_int16_decl="typedef $vi_cv_uint16 u_int16_t;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for int16_t" >&5
+echo $ECHO_N "checking for int16_t... $ECHO_C" >&6; }
+if test "${vi_cv_int16+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+int16_t foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_int16=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(short) != 2);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_int16="short"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(int) != 2);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_int16="int"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_int16=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_int16" >&5
+echo "${ECHO_T}$vi_cv_int16" >&6; }
+if test "$vi_cv_int16" = no; then
+       { { echo "$as_me:$LINENO: error: No signed 16-bit integral type." >&5
+echo "$as_me: error: No signed 16-bit integral type." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test "$vi_cv_int16" != yes; then
+       int16_decl="typedef $vi_cv_int16 int16_t;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for u_int32_t" >&5
+echo $ECHO_N "checking for u_int32_t... $ECHO_C" >&6; }
+if test "${vi_cv_uint32+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+u_int32_t foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_uint32=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(unsigned int) != 4);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_uint32="unsigned int"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(unsigned long) != 4);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_uint32="unsigned long"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_uint32=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_uint32" >&5
+echo "${ECHO_T}$vi_cv_uint32" >&6; }
+if test "$vi_cv_uint32" = no; then
+       { { echo "$as_me:$LINENO: error: No unsigned 32-bit integral type." >&5
+echo "$as_me: error: No unsigned 32-bit integral type." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test "$vi_cv_uint32" != yes; then
+       u_int32_decl="typedef $vi_cv_uint32 u_int32_t;"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for int32_t" >&5
+echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; }
+if test "${vi_cv_int32+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+int32_t foo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_int32=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(int) != 4);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_int32="int"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+main(){exit(sizeof(long) != 4);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  vi_cv_int32="long"
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+vi_cv_int32=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_int32" >&5
+echo "${ECHO_T}$vi_cv_int32" >&6; }
+if test "$vi_cv_int32" = no; then
+       { { echo "$as_me:$LINENO: error: No signed 32-bit integral type." >&5
+echo "$as_me: error: No signed 32-bit integral type." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test "$vi_cv_int32" != yes; then
+       int32_decl="typedef $vi_cv_int32 int32_t;"
+fi
+
+{ echo "$as_me:$LINENO: checking return type of fprintf" >&5
+echo $ECHO_N "checking return type of fprintf... $ECHO_C" >&6; }
+if test "${vi_cv_type_fprintf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int fprintf ();
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_type_fprintf=int
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_type_fprintf=void
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_type_fprintf" >&5
+echo "${ECHO_T}$vi_cv_type_fprintf" >&6; }
+
+
+{ echo "$as_me:$LINENO: checking fprintf prototype needed" >&5
+echo $ECHO_N "checking fprintf prototype needed... $ECHO_C" >&6; }
+if test "${vi_cv_proto_fprintf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+ #include <stdio.h>
+typedef int     (*funcPtr)();
+
+int
+main ()
+{
+funcPtr ptr = (funcPtr) fprintf;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  vi_cv_proto_fprintf=no
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_proto_fprintf=yes
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $vi_cv_proto_fprintf" >&5
+echo "${ECHO_T}$vi_cv_proto_fprintf" >&6; }
+if test "$vi_cv_proto_fprintf" = yes; then
+       cat >>confdefs.h <<\_ACEOF
+#define NEED_FPRINTF_PROTO 1
+_ACEOF
+
+fi
+
+
+# Check whether --with-db_type was given.
+if test "${with_db_type+set}" = set; then
+  withval=$with_db_type;
+fi
+
+case "$with_db_type" in
+"db1")
+       { echo "$as_me:$LINENO: WARNING: Use of db1 is not officially supported." >&5
+echo "$as_me: WARNING: Use of db1 is not officially supported." >&2;}
+       cat >>confdefs.h <<\_ACEOF
+#define USE_DB1 1
+_ACEOF
+
+       ;;
+"system")
+       ;;
+*)
+       with_db_type="bundled"
+       ;;
+esac
+
+
+# Check whether --with-db_prefix was given.
+if test "${with_db_prefix+set}" = set; then
+  withval=$with_db_prefix;
+fi
+
+
+SAVELDFLAGS="$LDFLAGS"
+if test "x$with_db_prefix" != "x"; then
+       LDFLAGS="-L$with_db_prefix/lib $LDFLAGS"
+       CPPFLAGS="-I$with_db_prefix/include $CPPFLAGS"
+fi
+if test "$with_db_type" != db1; then
+       SAVELIBS="$LIBS"
+
+       LIBS="$LIBS -ldb"
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <db.h>
+int
+main ()
+{
+db_create(NULL,NULL,0)
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  vi_cv_dbfatal="no"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       vi_cv_dbfatal="yes"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+       if test "$vi_cv_dbfatal" = "yes"; then
+               { { echo "$as_me:$LINENO: error: Need DB 3." >&5
+echo "$as_me: error: Need DB 3." >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+
+       LIBS="$SAVELIBS"
+fi
+LDFLAGS="$SAVELDFLAGS"
+
+
+{ echo "$as_me:$LINENO: checking if --enable-dynamic-loading option specified" >&5
+echo $ECHO_N "checking if --enable-dynamic-loading option specified... $ECHO_C" >&6; }
+# Check whether --enable-dynamic-loading was given.
+if test "${enable_dynamic_loading+set}" = set; then
+  enableval=$enable_dynamic_loading; vi_cv_dl=$enableval
+else
+  vi_cv_dl="no"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_dl" >&5
+echo "${ECHO_T}$vi_cv_dl" >&6; }
+if test "$vi_cv_dl" = yes; then
+       { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  vi_cv_dlfatal="no"
+else
+  vi_cv_dlfatal="yes"
+fi
+
+       if test "$vi_cv_dlfatal" = "yes"; then
+               { { echo "$as_me:$LINENO: error: Need dl to support dynamic loading." >&5
+echo "$as_me: error: Need dl to support dynamic loading." >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       OLDPATH="$PATH"
+
+       PATH="$with_db_prefix/lib:/usr/lib:/lib"
+       # Extract the first word of "libdb-3.so", so it can be a program name with args.
+set dummy libdb-3.so; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_vi_cv_path_db3+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_db3 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_db3="$vi_cv_path_db3" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_vi_cv_path_db3="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_vi_cv_path_db3" && ac_cv_path_vi_cv_path_db3="no"
+  ;;
+esac
+fi
+vi_cv_path_db3=$ac_cv_path_vi_cv_path_db3
+if test -n "$vi_cv_path_db3"; then
+  { echo "$as_me:$LINENO: result: $vi_cv_path_db3" >&5
+echo "${ECHO_T}$vi_cv_path_db3" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+       if test "$vi_cv_path_db3" = no; then
+               { { echo "$as_me:$LINENO: error: Path of libdb-3.so not found." >&5
+echo "$as_me: error: Path of libdb-3.so not found." >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+       PATH="$OLDPATH"
+
+       cat >>confdefs.h <<\_ACEOF
+#define USE_DYNAMIC_LOADING 1
+_ACEOF
+
+       LIBOBJS="dldb.o $LIBOBJS"
+       dl_src=../common/dldb.c
+       LIBS="-ldl $LIBS"
+else
+       LIBS="-ldb $LIBS"
+       if test "X$with_db_prefix" != "X"; then
+               LDFLAGS="`echo $with_db_prefix/lib | sed "$LRscript"` $LDFLAGS"
+       fi
+fi
+
+
+# Check whether --with-db_build was given.
+if test "${with_db_build+set}" = set; then
+  withval=$with_db_build;
+fi
+
+if test "x$with_db_build" != "x"; then
+       vi_cv_dbsrc=`$AWK '/^srcdir/ {gsub("srcdir[ \t]*=","");print $1}' \
+                    $with_db_build/Makefile`
+       case $with_db_build in
+       *[\\/]);;
+       *)
+           with_db_build="$with_db_build/";;
+       esac
+       case $vi_cv_dbsrc in
+       [\\/]*);;
+       *)
+           vi_cv_dbsrc="$with_db_build$vi_cv_dbsrc";;
+       esac
+fi;
+
+vi_cv_db4="no"
+# Check whether --enable-log4 was given.
+if test "${enable_log4+set}" = set; then
+  enableval=$enable_log4;
+       { echo "$as_me:$LINENO: checking for DB 4" >&5
+echo $ECHO_N "checking for DB 4... $ECHO_C" >&6; }
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <db.h>
+       DB_VERSION_MAJOR
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "^4" >/dev/null 2>&1; then
+  vi_cv_db4="yes"
+else
+  vi_cv_db4="no"
+fi
+rm -f conftest*
+
+       { echo "$as_me:$LINENO: result: $vi_cv_db4" >&5
+echo "${ECHO_T}$vi_cv_db4" >&6; }
+
+fi
+
+if test "$vi_cv_db4" = "yes"; then
+       CPPFLAGS="-I$vi_cv_dbsrc/include $CPPFLAGS"
+       CPPFLAGS="-I$vi_cv_dbsrc/include_auto $CPPFLAGS"
+       CPPFLAGS="-I$with_db_build $CPPFLAGS"
+       cat >>confdefs.h <<\_ACEOF
+#define USE_DB4_LOGGING 1
+_ACEOF
+
+       LIBOBJS="log4.o vi_auto.o vi_rec.o $LIBOBJS"
+else
+       LIBOBJS="log.o $LIBOBJS"
+fi
+
+{ echo "$as_me:$LINENO: checking if --disable-re option specified" >&5
+echo $ECHO_N "checking if --disable-re option specified... $ECHO_C" >&6; }
+# Check whether --enable-re was given.
+if test "${enable_re+set}" = set; then
+  enableval=$enable_re; if test "$enable_re" = "yes"; then
+               vi_cv_re_lib="bundled RE"
+       else
+               vi_cv_re_lib="other RE"
+       fi
+else
+  vi_cv_re_lib="bundled RE"
+fi
+
+{ echo "$as_me:$LINENO: result: $vi_cv_re_lib" >&5
+echo "${ECHO_T}$vi_cv_re_lib" >&6; }
+case "$vi_cv_re_lib" in
+"bundled RE")
+       CPPFLAGS="-I\$(visrcdir)/regex $CPPFLAGS"
+       LIBOBJS="regcomp.o regerror.o regexec.o regfree.o $LIBOBJS";;
+"other RE")
+       ;;
+esac
+
+ac_config_files="$ac_config_files Makefile port.h:port.h.in pathnames.h:pathnames.h.in recover:recover.in"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+       case $1 in
+        -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "port.h") CONFIG_FILES="$CONFIG_FILES port.h:port.h.in" ;;
+    "pathnames.h") CONFIG_FILES="$CONFIG_FILES pathnames.h:pathnames.h.in" ;;
+    "recover") CONFIG_FILES="$CONFIG_FILES recover:recover.in" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+am__isrc!$am__isrc$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+SED!$SED$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LN_S!$LN_S$ac_delim
+ECHO!$ECHO$ac_delim
+AR!$AR$ac_delim
+RANLIB!$RANLIB$ac_delim
+CPP!$CPP$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+CXXCPP!$CXXCPP$ac_delim
+F77!$F77$ac_delim
+FFLAGS!$FFLAGS$ac_delim
+ac_ct_F77!$ac_ct_F77$ac_delim
+LIBTOOL!$LIBTOOL$ac_delim
+OPTFLAG!$OPTFLAG$ac_delim
+no_op_OPTFLAG!$no_op_OPTFLAG$ac_delim
+vi_cv_path_shell!$vi_cv_path_shell$ac_delim
+vi_cv_path_sendmail!$vi_cv_path_sendmail$ac_delim
+vi_cv_path_perl!$vi_cv_path_perl$ac_delim
+vi_cv_path_preserve!$vi_cv_path_preserve$ac_delim
+vi_cv_path_fuser!$vi_cv_path_fuser$ac_delim
+vi_cv_path_lsof!$vi_cv_path_lsof$ac_delim
+INUSE!$INUSE$ac_delim
+vi_cv_path_ar!$vi_cv_path_ar$ac_delim
+vi_cv_path_chmod!$vi_cv_path_chmod$ac_delim
+vi_cv_path_cp!$vi_cv_path_cp$ac_delim
+vi_cv_path_ln!$vi_cv_path_ln$ac_delim
+vi_cv_path_mkdir!$vi_cv_path_mkdir$ac_delim
+vi_cv_path_rm!$vi_cv_path_rm$ac_delim
+vi_cv_path_ranlib!$vi_cv_path_ranlib$ac_delim
+vi_cv_path_strip!$vi_cv_path_strip$ac_delim
+XMKMF!$XMKMF$ac_delim
+XINCS!$XINCS$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+vi_programs!$vi_programs$ac_delim
+vi_ipc!$vi_ipc$ac_delim
+GTKLIBS!$GTKLIBS$ac_delim
+GTKINCS!$GTKINCS$ac_delim
+PKG_CONFIG!$PKG_CONFIG$ac_delim
+GTK_CONFIG!$GTK_CONFIG$ac_delim
+GTK_CFLAGS!$GTK_CFLAGS$ac_delim
+GTK_LIBS!$GTK_LIBS$ac_delim
+MOTIFLIBS!$MOTIFLIBS$ac_delim
+IPCOBJS!$IPCOBJS$ac_delim
+shrpenv!$shrpenv$ac_delim
+perlldflags!$perlldflags$ac_delim
+perllibs!$perllibs$ac_delim
+vi_cv_perllib!$vi_cv_perllib$ac_delim
+CURSLIBS!$CURSLIBS$ac_delim
+CURSCPPFLAGS!$CURSCPPFLAGS$ac_delim
+CURSLDFLAGS!$CURSLDFLAGS$ac_delim
+HAVE_NCURSESW!$HAVE_NCURSESW$ac_delim
+u_char_decl!$u_char_decl$ac_delim
+u_short_decl!$u_short_decl$ac_delim
+u_int_decl!$u_int_decl$ac_delim
+u_long_decl!$u_long_decl$ac_delim
+u_int8_decl!$u_int8_decl$ac_delim
+u_int16_decl!$u_int16_decl$ac_delim
+int16_decl!$int16_decl$ac_delim
+u_int32_decl!$u_int32_decl$ac_delim
+int32_decl!$int32_decl$ac_delim
+NEED_FPRINTF_PROTO!$NEED_FPRINTF_PROTO$ac_delim
+dl_src!$dl_src$ac_delim
+vi_cv_path_db3!$vi_cv_path_db3$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 56; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+         echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([  #]*\\)[^        ]*\\([  ]*'
+ac_dB='\\)[     (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+       t rset
+       :rset
+       s/^[     ]*#[    ]*define[       ][      ]*//
+       t ok
+       d
+       :ok
+       s/[\\&,]/\\&/g
+       s/^\('"$ac_word_re"'\)\(([^()]*)\)[      ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+       s/^\('"$ac_word_re"'\)[  ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[    #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:         sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:        sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:    sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[     ]*#[    ]*undef[        ][      ]*$ac_word_re[  ]*\$/b def
+/^[     ]*#[    ]*define[       ][      ]*$ac_word_re[(         ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $ac_file | $ac_file:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $ac_file" >`$as_dirname -- $ac_file ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X$ac_file : 'X\(//\)[^/]' \| \
+        X$ac_file : 'X\(//\)$' \| \
+        X$ac_file : 'X\(/\)' \| . 2>/dev/null ||
+echo X$ac_file |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
+    dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$mf" : 'X\(//\)[^/]' \| \
+        X"$mf" : 'X\(//\)$' \| \
+        X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$file" : 'X\(//\)[^/]' \| \
+        X"$file" : 'X\(//\)$' \| \
+        X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+    { as_dir=$dirpart/$fdir
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+
+  esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/dist/nvi/dist/configure.in b/dist/nvi/dist/configure.in
new file mode 100644 (file)
index 0000000..082aa60
--- /dev/null
@@ -0,0 +1,1073 @@
+dnl    Id: configure.in,v 8.192 2003/02/17 20:09:07 skimo Exp
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(../common/main.c)
+AC_CONFIG_AUX_DIR(.)
+AM_INIT_AUTOMAKE(vi, 1.81.6)
+AM_CONFIG_HEADER(config.h)
+
+dnl Configure setup.
+AC_PROG_INSTALL()
+AC_CANONICAL_HOST
+dnl part of AM_INIT_AUTOMAKE ?
+dnl AC_ARG_PROGRAM()
+
+AC_PROG_LIBTOOL
+
+dnl If the user wants a debugging environment, set OPTFLAG now, some
+dnl compilers won't mix optimizing and debug flags.)
+AC_MSG_CHECKING(if --enable-debug option specified)
+AC_ARG_ENABLE(debug,
+       [  --enable-debug          Build a debugging version.],
+       [vi_cv_debug=$enableval], [vi_cv_debug="no"])
+AC_MSG_RESULT($vi_cv_debug)
+if test "$vi_cv_debug" = yes; then
+       AC_DEFINE(DEBUG)
+       OPTFLAG=${OPTFLAG-"-g"}
+       no_op_OPTFLAG=${no_op_OPTFLAG-"-g"}
+fi
+
+dnl This is where we handle stuff that autoconf can't handle.
+dnl XXX
+dnl Don't override anything if it's already set from the environment.
+
+dnl Compiler, preprocessor and load flags.
+dnl AUX:       -ZP disables _BSD_SOURCE et al, but enables POSIX at link time.
+dnl LynxOS:    We check for gcc 2.x or better, the gcc 1 that was shipped with
+dnl            LynxOS historically wasn't good enough.
+AC_SUBST(CPPFLAGS)
+case "$host_os" in
+aix3.2.5)  OPTFLAG=${OPTFLAG-"-O"};;
+aix4.1*)   CFLAGS=${CFLAGS-"-qstrict"}
+          OPTFLAG=${OPTFLAG-"-O3"};;
+aux*)     CPPFLAGS=${CPPFLAGS-"-ZP -D_BSD_SOURCE -D_SYSV_SOURCE -D_AUX_SOURCE"}
+          LDFLAGS=${LDFLAGS-"-ZP"}
+          OPTFLAG=${OPTFLAG-"-O"};;
+bsd4.4)    OPTFLAG=${OPTFLAG-"-O2"};;
+bsdi*)    CC=${CC-"shlicc"}
+          OPTFLAG=${OPTFLAG-"-O2"};;
+irix6*)           OPTFLAG=${OPTFLAG-"-O2"};;
+irix*)    OPTFLAG=${OPTFLAG-"-O2"};;
+lynxos*)   AC_PROG_CC()
+          AC_MSG_CHECKING([for GNU C (gcc) version 2.x])
+          ac_cv_gcc_vers=`${CC-cc} -v 2>&1 | \
+               grep "gcc version " | sed 's/.*version //'`
+          ac_cv_gcc_major=`echo "$ac_cv_gcc_vers" | sed 's/\..*//'`
+          if test "$ac_cv_gcc_major" = "2" ; then
+               AC_MSG_RESULT(yes)
+          else
+               AC_MSG_RESULT(no)
+               AC_MSG_WARN([Nvi requires gcc 2.x to build on LynxOS.])
+               AC_MSG_ERROR([See build/README.LynxOS for more information.])
+          fi;;
+nextstep3) CPPFLAGS=${CPPFLAGS-"-w -pipe -posix"}
+          LDFLAGS=${LDFLAGS-"-posix"}
+          OPTFLAG=${OPTFLAG-"-O2"};;
+osf*)     CFLAGS=${CFLAGS-"-Olimit 1000"};;
+solaris*)  no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+sunos*)           no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+esac
+
+dnl The default OPTFLAG is -O
+AC_SUBST(OPTFLAG)
+OPTFLAG=${OPTFLAG-"-O"}
+
+dnl The default compiler is cc (NOT gcc), the default CFLAGS is empty,
+dnl NOT whatever AC_PROG_CC sets.
+AC_SUBST(CC)
+CC=${CC-cc}
+CFLAGS=${CFLAGS-""}
+AC_PROG_CC
+
+if test "$GCC" = yes; then
+       AC_DEFINE(HAVE_GCC)
+fi
+
+dnl The SunOS/Solaris compiler can't optimize vi/v_txt.c; the symptom is
+dnl that the command 35i==<esc> turns into an infinite loop.
+AC_SUBST(no_op_OPTFLAG)
+no_op_OPTFLAG=${no_op_OPTFLAG-"$OPTFLAG"}
+
+dnl Libraries.
+case "$host_os" in
+bsdi2.1)   LIBS=${LIBS-"-lipc"};;
+dgux*)    LIBS=${LIBS-"-ldgc"};;
+irix6*)           LIBS=${LIBS-"-lbsd"};;
+irix*)    LIBS=${LIBS-"-lc_s -lbsd"};;
+isc*)     LIBS=${LIBS-"-lcposix -linet"};;
+netbsd1*)  LIBS=${LIBS-"-lcrypt"};;
+ptx*)     LIBS=${LIBS-"-lseq -linet -lsocket"};;
+sco3.2*)   LIBS=${LIBS-"-lsocket"};;
+sinix*)           LIBS=${LIBS-"-lelf -lc"};;
+solaris*)  LIBS=${LIBS-"-lsocket -lnsl -ldl"};;
+wgs*)     LIBS=${LIBS-"-lnsl"};;
+esac
+
+dnl A/UX has a broken getopt(3), strpbrk(3).
+case "$host_os" in
+aux*)     LIBOBJS="getopt.o strpbrk.o $LIBOBJS";;
+esac
+
+dnl Ultrix has a broken POSIX.1 VDISABLE value.
+case "$host_os" in
+ultrix*)   AC_DEFINE(HAVE_BROKEN_VDISABLE);;
+esac
+
+AC_MSG_CHECKING(whether recording of pathnames of libraries is enabled)
+AC_ARG_ENABLE(runpath,
+       [  --disable-runpath       Don't record path of libraries in binary.],
+       [vi_cv_runpath="$enableval"], [vi_cv_runpath="yes"])
+AC_MSG_RESULT($vi_cv_runpath)
+
+if test "X$vi_cv_runpath" = "Xyes"; then
+       LRscript='s/^\(.*\)/-R\1 -L\1 /'
+else
+       LRscript='s/^\(.*\)/-L\1 /'
+fi
+
+dnl If the user wants a tracing version, add the TRACE compile flag.
+AC_MSG_CHECKING(if --enable-trace option specified)
+AC_ARG_ENABLE(trace,
+       [  --enable-trace          Build a tracing version.],
+       [vi_cv_trace="yes"], [vi_cv_trace="no"])
+if test "$vi_cv_trace" = yes; then
+       CPPFLAGS="-DTRACE $CPPFLAGS"
+fi
+AC_MSG_RESULT($vi_cv_trace)
+
+dnl The user may have additional CPP information.
+CPPFLAGS="$ADDCPPFLAGS $CPPFLAGS"
+
+dnl The user may have additional load line information.
+LDFLAGS="$ADDLDFLAGS $LDFLAGS"
+
+dnl The user may have additional library information.
+LIBS="$ADDLIBS $LIBS"
+
+dnl Checks for programs.
+PATH="$PATH:/usr/bin:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib:/usr/ucblib"
+
+dnl Check for the shell path.
+AC_PATH_PROG(vi_cv_path_shell, sh, no)
+if test "$vi_cv_path_shell" = no; then
+       AC_MSG_ERROR([No shell utility found.])
+fi
+
+dnl Check for the sendmail path.
+AC_PATH_PROG(vi_cv_path_sendmail, sendmail, no)
+if test "$vi_cv_path_sendmail" = no; then
+       AC_MSG_WARN([No sendmail utility found;])
+       AC_MSG_WARN([    users will not be told of saved files.])
+fi
+
+dnl Check for the perl5/perl path.
+AC_SUBST(vi_cv_path_perl)
+AC_PATH_PROGS(vi_cv_path_perl, perl5 perl, no)
+
+dnl Check for the "preserve" path.
+dnl Historically, nvi has used /var/tmp/vi.recover.  The Linux filesystem
+dnl standard (FSSTND) uses /var/preserve; we add the vi.recover directory
+dnl beneath it so that we don't have name collisions with other editors.
+dnl Other systems have /var/preserve as well, so we test first for an already
+dnl existing name, and then use the first one that's writeable.
+AC_SUBST(vi_cv_path_preserve)
+AC_MSG_CHECKING(for preserve directory)
+AC_CACHE_VAL(vi_cv_path_preserve, [dnl
+       dirlist="/var/preserve /var/tmp /usr/tmp"
+       vi_cv_path_preserve=no
+       for i in $dirlist; do
+               if test -d $i/vi.recover; then
+                       vi_cv_path_preserve=$i/vi.recover
+                       break;
+               fi
+       done
+       if test "$vi_cv_path_preserve" = no; then
+               for i in $dirlist; do
+                       if test -d $i -a -w $i; then
+                               vi_cv_path_preserve=$i/vi.recover
+                               break;
+                       fi
+               done
+
+       fi])
+if test "$vi_cv_path_preserve" = no; then
+       AC_MSG_ERROR([No writeable preserve directory found.])
+fi
+AC_MSG_RESULT($vi_cv_path_preserve)
+AC_PATH_PROG(vi_cv_path_fuser, fuser, no)
+AC_PATH_PROG(vi_cv_path_lsof, lsof, no)
+AC_SUBST(INUSE)
+INUSE=""
+if test "$vi_cv_path_lsof" != no; then
+       INUSE='test `lsof -t $i`'
+fi
+if test "$vi_cv_path_fuser" != no; then
+       INUSE='fuser -s $i'
+fi
+
+dnl Check for programs used for installation
+AC_PROG_AWK
+AC_PATH_PROG(vi_cv_path_ar, ar, missing_ar)
+AC_PATH_PROG(vi_cv_path_chmod, chmod, missing_chmod)
+AC_PATH_PROG(vi_cv_path_cp, cp, missing_cp)
+AC_PATH_PROG(vi_cv_path_ln, ln, missing_ln)
+AC_PATH_PROG(vi_cv_path_mkdir, mkdir, missing_mkdir)
+AC_PATH_PROG(vi_cv_path_rm, rm, missing_rm)
+AC_PATH_PROG(vi_cv_path_ranlib, ranlib, missing_ranlib)
+AC_PATH_PROG(vi_cv_path_strip, strip, missing_strip)
+
+dnl Checks for libraries.
+dnl Find the X libraries and includes.
+AC_PATH_X
+AC_SUBST(XINCS)
+if test "$no_x" != yes; then
+       if test "X$x_libraries" != "X"; then
+               XLIBS="`echo $x_libraries | sed "$LRscript"` $XLIBS"
+       fi
+       XLIBS="$XLIBS -lX11"
+       if test "X$x_includes" != "X"; then
+               XINCS="-I$x_includes"
+       fi
+fi
+
+AC_DEFUN([VI_CV_REPLACE_FUNCS],
+[AC_FOREACH([AC_Func], [$1], [])dnl
+AC_CHECK_FUNCS([$1], , [_AC_LIBOBJ($ac_func)])
+])
+
+dnl Check if the user wants widechar support.
+AC_MSG_CHECKING(if --enable-widechar option specified)
+AC_ARG_ENABLE(widechar,
+       [  --enable-widechar       Build a wide char aware vi.],
+       [vi_cv_widechar=$enableval], [vi_cv_widechar="no"])
+if test "$vi_cv_widechar" = "yes"; then
+       AC_DEFINE(USE_WIDECHAR)
+fi
+AC_MSG_RESULT($vi_cv_widechar)
+
+dnl Check whether we can use iconv
+AC_CHECK_HEADER(langinfo.h, [
+       AC_CHECK_HEADER(iconv.h, [
+               AC_DEFINE(USE_ICONV)
+               VI_CV_REPLACE_FUNCS(iswblank)
+       ])
+])
+
+dnl If the user wants a Gtk IPC front-end for nvi, build it.
+AC_SUBST(vi_programs)
+AC_SUBST(vi_ipc)
+AC_SUBST(GTKLIBS)
+AC_SUBST(GTKINCS)
+AC_MSG_CHECKING(if --enable-gtk option specified)
+AC_ARG_ENABLE(gtk,
+       [  --enable-gtk            Build a Gtk front-end for vi.],
+       [vi_cv_gtk=$enableval], [vi_cv_gtk="no"])
+AC_MSG_RESULT($vi_cv_gtk)
+if test "$vi_cv_gtk" = "yes"; then
+       #
+       # Find pkg-config
+       #
+       AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+       if test x$PKG_CONFIG = xno ; then
+           if test "$vi_cv_widechar" = "yes"; then
+               AC_MSG_ERROR(
+[*** pkg-config not found. See http://pkgconfig.sourceforge.net])
+           fi
+
+       else
+           if ! $PKG_CONFIG --atleast-pkgconfig-version 0.5 ; then
+               if test "$vi_cv_widechar" = "yes"; then
+                   AC_MSG_ERROR(
+[*** pkg-config too old; version 0.5 or better required.])
+               fi
+               PKG_CONFIG=no
+           fi
+
+       fi
+       if test x$PKG_CONFIG = xno ; then
+           PKG_CONFIG=/bin/false
+       fi
+
+       vi_programs="$vi_programs vi-gtk"
+       vi_ipc=vi-ipc
+       AC_MSG_CHECKING(for gtk+)
+       if $PKG_CONFIG gtk+-2.0 ; then
+             GTKINCS=`$PKG_CONFIG --cflags gtk+-2.0`
+             GTKLIBS=`$PKG_CONFIG --libs gtk+-2.0`
+
+             AC_MSG_RESULT(ok)
+             AC_DEFINE(HAVE_PANGO)
+       else
+           if test "$vi_cv_widechar" = "yes"; then
+               AC_MSG_ERROR([
+*** gtk+-2.0 is required. The latest version of gtk
+*** is always available from ftp://ftp.gtk.org/.
+               ])
+           else
+               AM_PATH_GTK(1.2.0)
+               GTKINCS="$GTK_CFLAGS"
+               GTKLIBS="$GTK_LIBS $LIBS"
+           fi
+       fi
+
+       SAVELIBS="$LIBS"
+       LIBS="-lutil $GTKLIBS"
+       AC_CHECK_LIB(nvizvt, zvt_get_ptys,
+               [vi_cv_zvt="yes"], [vi_cv_zvt="no"])
+       if test "$vi_cv_zvt" = "yes"; then
+               GTKLIBS="-lnvizvt $LIBS"
+               AC_DEFINE(HAVE_ZVT)
+       fi
+       LIBS="$SAVELIBS"
+#      AC_PATH_PROG(vi_cv_gnome_config, gnome-config, no)
+#      if test "$vi_cv_gnome_config" != "no"; then
+#              ZVTLIBS=`$vi_cv_gnome_config zvt --libs`
+#              GTKLIBS="$ZVTLIBS $GTKLIBS"
+#      fi
+fi
+
+dnl If the user wants a Motif IPC front-end for nvi, build it.
+AC_SUBST(MOTIFLIBS)
+AC_MSG_CHECKING(if --enable-motif option specified)
+AC_ARG_ENABLE(motif,
+       [  --enable-motif          Build a Motif front-end for vi.],
+       [vi_cv_motif=$enableval], [vi_cv_motif="no"])
+AC_MSG_RESULT($vi_cv_motif)
+if test "$vi_cv_motif" = "yes"; then
+       vi_programs="$vi_programs vi-motif"
+       vi_ipc=vi-ipc
+
+       dnl XXX
+       dnl BSDI's Motif libraries aren't shared.
+
+       case "$host_os" in
+       bsdi*)  CC=cc;;
+       esac
+
+       dnl XXX
+       dnl The Xinside Motif distribution requires -lSM, -lICE and -lXext.
+       dnl -lXext is generally available, the others aren't.
+       dnl
+       dnl XXX
+       dnl Color icons require -lXpm, which may or may not be available,
+       dnl depending on the version of X11.
+
+       MOTIFLIBS="-lXm -lXt"
+       AC_CHECK_LIB(SM, main,
+           [vi_cv_smlib="yes"], [vi_cv_smlib="no"], "$XLIBS")
+       if test "$vi_cv_smlib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lSM"
+       fi
+       AC_CHECK_LIB(ICE, main,
+           [vi_cv_icelib="yes"], [vi_cv_icelib="no"], "$XLIBS")
+       if test "$vi_cv_icelib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lICE"
+       fi
+       AC_CHECK_LIB(Xext, main,
+           [vi_cv_xextlib="yes"], [vi_cv_xextlib="no"], "$XLIBS")
+       if test "$vi_cv_xextlib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lXext"
+       fi
+       AC_CHECK_LIB(Xpm, main,
+           [vi_cv_xpmlib="yes"], [vi_cv_xpmlib="no"], "$XLIBS")
+       if test "$vi_cv_xpmlib" = "yes"; then
+               MOTIFLIBS="$MOTIFLIBS -lXpm"
+       fi
+       MOTIFLIBS="$MOTIFLIBS $XLIBS -lm $LIBS"
+fi
+
+AC_SUBST(IPCOBJS)
+dnl Check for threads
+AC_MSG_CHECKING(if --enable-threads option specified)
+AC_ARG_ENABLE(threads,
+       [  --enable-threads        Turn on thread support.],
+       [vi_cv_threads=$enableval], [vi_cv_threads="no"])
+AC_MSG_RESULT($vi_cv_threads)
+if test "$vi_cv_threads" = "yes"; then
+       LIBS="$LIBS -lpthread"
+       AC_CACHE_VAL(vi_cv_have_pthreads, [dnl
+       AC_TRY_LINK([#include <pthread.h>],
+               [pthread_self()],
+               [vi_cv_have_pthreads=yes],
+               [vi_cv_have_pthreads=no])])
+       if test "$vi_cv_have_pthreads" = "no"; then
+               AC_MSG_ERROR(No threading library found)
+       fi
+       IPCOBJS="pthread.o $IPCOBJS"
+       AC_DEFINE(HAVE_PTHREAD)
+else
+       IPCOBJS="nothread.o $IPCOBJS"
+fi
+
+dnl If the user wants a Perl interpreter in nvi, load it.
+AC_SUBST(shrpenv)
+AC_SUBST(perlldflags)
+AC_SUBST(perllibs)
+AC_SUBST(vi_cv_perllib)
+AC_MSG_CHECKING(if --enable-perlinterp option specified)
+AC_ARG_ENABLE(perlinterp,
+       [  --enable-perlinterp     Include a Perl interpreter in vi.],
+       [vi_cv_perlinterp=$enableval], [vi_cv_perlinterp="no"])
+AC_MSG_RESULT($vi_cv_perlinterp)
+if test "$vi_cv_perlinterp" = "yes"; then
+       if test "$vi_cv_path_perl" = no; then
+               AC_MSG_ERROR([No perl5 utility found.])
+       fi
+       $vi_cv_path_perl -e 'require 5.004' || {
+               AC_MSG_ERROR([perl5 must be version 5.004 or later.])
+       }
+       if test "$vi_cv_threads" = "yes"; then
+               useithreads=`$vi_cv_path_perl -MConfig -e 'print $Config{useithreads}'`
+               if test "X$useithreads" != "Xdefine"; then
+                       AC_MSG_ERROR([vi threading only compatible with perl's ithreads.])
+               fi
+       fi
+
+       eval `$vi_cv_path_perl -V:shrpenv`
+       vi_cv_perllib=`$vi_cv_path_perl -MConfig -e 'print $Config{privlib}'`
+       perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+               -e 'ccflags;perl_inc'`
+       if test "X$perlcppflags" != "X"; then
+               CPPFLAGS="$perlcppflags $CPPFLAGS"
+       fi
+       perllibs=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+               -e 'ldopts'`
+       perlldflags=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+               -e 'ccdlflags'`
+       LIBOBJS="perl.o perlxsi.o perlsfio.o $LIBOBJS"
+       AC_DEFINE(HAVE_PERL_INTERP)
+       AC_CACHE_CHECK([whether we need to use perl's setenv], 
+               vi_cv_perl_setenv, [
+               AC_TRY_RUN([
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+int main(){
+#if defined(USE_ENVIRON_ARRAY) && !defined(PERL_USE_SAFE_PUTENV)
+exit(0);
+#else
+exit(1);
+#endif
+}
+               ], [vi_cv_perl_setenv=yes], [vi_cv_perl_setenv=no])])
+       if test "$vi_cv_perl_setenv" = yes; then
+               AC_DEFINE(USE_PERL_SETENV)
+       fi
+fi
+
+dnl If the user wants a Tk/Tcl interpreter in nvi, load it.  Make sure that
+dnl we can find a Tk/Tcl library.
+AC_MSG_CHECKING(if --enable-tclinterp option specified)
+AC_ARG_ENABLE(tclinterp,
+       [  --enable-tclinterp      Include a Tk/Tcl interpreter in vi.],
+       [vi_cv_tclinterp=$enableval], [vi_cv_tclinterp="no"])
+AC_MSG_RESULT($vi_cv_tclinterp)
+if test "$vi_cv_tclinterp" = "yes"; then
+       AC_MSG_CHECKING([for tclConfig.sh])
+       AC_CACHE_VAL(vi_cv_tclconfig, [
+               vi_cv_tclconfig=`$srcdir/findconfig`])
+       AC_MSG_RESULT($vi_cv_tclconfig)
+       if test "x$vi_cv_tclconfig" = x; then
+               AC_MSG_ERROR([No Tcl library found;])
+       fi
+       . $vi_cv_tclconfig
+       LIBOBJS="tcl.o $LIBOBJS"
+       LIBS="$TCL_LIB_SPEC $TCL_LIBS $LIBS"
+       AC_DEFINE(HAVE_TCL_INTERP)
+fi
+
+dnl check for curses
+AC_SUBST(CURSLIBS)
+AC_SUBST(CURSCPPFLAGS)
+AC_SUBST(CURSLDFLAGS)
+AC_SUBST(HAVE_NCURSESW)
+
+dnl AC_ARG_WITH(slang,
+dnl    [  --with-slang[=DIR]     Use S-Lang instead of curses. ],
+dnl    [
+dnl    if test "$withval" != yes; then
+dnl            LDFLAGS="-L${withval}/lib $LDFLAGS"
+dnl            CPPFLAGS="-I${withval}/include $CPPFLAGS"
+dnl    fi
+dnl    AC_DEFINE(USE_SLANG_CURSES)
+dnl         AC_CHECK_LIB(slang, SLtt_get_terminfo,
+dnl                 [CURSLIBS="$CURSLIBS -lslang -lm"],
+dnl                 [AC_MSG_ERROR(unable to compile.  check config.log)], -lm)
+dnl 
+dnl    vi_cv_curses=slcurses
+dnl    ],
+dnl    [
+       SAVELIBS="$LIBS"
+       SAVELDFLAGS="$LDFLAGS"
+       SAVECPPFLAGS="$CPPFLAGS"
+       AC_ARG_WITH(curses,
+               [  --with-curses=DIR       Path to curses installation. ])
+       if test "x$with_curses" != "x"; then
+               CURSLDFLAGS="`echo $with_curses/lib | sed "$LRscript"` $CURSLDFLAGS"
+               CURSCPPFLAGS="-I$with_curses/include $CURSCPPFLAGS"
+       fi;
+       LDFLAGS="$CURSLDFLAGS $LDFLAGS"
+       CPPFLAGS="$CURSCPPFLAGS $CPPFLAGS"
+
+       if test "$vi_cv_widechar" = "yes"; then
+           for vi_cv_curses in ncurses ncursesw curses; do
+               AC_CHECK_LIB($vi_cv_curses, waddnwstr,[break])
+               vi_cv_curses=unknown
+           done
+       else 
+           for vi_cv_curses in ncurses ncursesw curses; do
+               AC_CHECK_LIB($vi_cv_curses, initscr, [break])
+               vi_cv_curses=unknown
+           done
+       fi
+
+       if test "$vi_cv_curses" != "unknown"; then
+           CURSHEADER=curses.h
+           if test "$vi_cv_curses" = "ncurses"; then
+               AC_CHECK_HEADERS(ncurses.h, [CURSHEADER=ncurses.h])
+           fi
+           if test "$vi_cv_curses" = "ncursesw"; then
+               AC_CHECK_HEADERS(ncursesw/ncurses.h, 
+                       [CURSHEADER=ncursesw/ncurses.h])
+           fi
+           vi_programs="vi $vi_programs"
+           CURSLIBS="-l$vi_cv_curses"
+       else
+           AC_MSG_WARN([*** No suitable curses library found.])
+           if test "$vi_programs"X = X; then
+               AC_MSG_ERROR([No executable to build.])
+           fi
+       fi
+
+dnl Check for the termcap/termlib library.  These two checks must occur in the
+dnl current order, and -lcurses must be loaded before -ltermcap/-ltermlib.
+dnl On Solaris curses==termlib, but different versions of curses
+dnl can be used. Avoid loading termlib is curses has tgetent.
+AC_CHECK_LIB($vi_cv_curses, tgetent,
+       [vi_cv_curses_tgetent=yes], [vi_cv_curses_tgetent=no])
+if test "$vi_cv_curses_tgetent" = no; then
+       AC_CHECK_LIB(termlib, tgetent,
+               [vi_cv_termlib=-ltermlib], [vi_cv_termlib=no])
+       if test "$vi_cv_termlib" = no; then
+               AC_CHECK_LIB(termcap, tgetent,
+                       [vi_cv_termlib=-ltermcap], [vi_cv_termlib=no])
+       fi
+fi
+if test "$vi_cv_termlib" != no; then
+       CURSLIBS="$CURSLIBS $vi_cv_termlib"
+fi
+
+       LIBS="$SAVELIBS"
+       LDFLAGS="$SAVELDFLAGS"
+       CPPFLAGS="$SAVECPPFLAGS"
+dnl    ])
+
+dnl Checks for header files.
+AC_MSG_CHECKING(for sys/mman.h)
+AC_CACHE_VAL(vi_cv_include_sys_mman, [dnl
+AC_TRY_CPP([#include <sys/mman.h>],
+       [vi_cv_include_sys_mman=yes], [vi_cv_include_sys_mman=no])])
+if test "$vi_cv_include_sys_mman" = yes; then
+       AC_DEFINE(HAVE_SYS_MMAN_H)
+fi
+AC_MSG_RESULT($vi_cv_include_sys_mman)
+
+AC_MSG_CHECKING(for sys/select.h)
+AC_CACHE_VAL(vi_cv_include_sys_select, [dnl
+AC_TRY_CPP([#include <sys/select.h>],
+       [vi_cv_include_sys_select=yes], [vi_cv_include_sys_select=no])])
+if test "$vi_cv_include_sys_select" = yes; then
+       AC_DEFINE(HAVE_SYS_SELECT_H)
+fi
+AC_MSG_RESULT($vi_cv_include_sys_select)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_CHECK_TYPE(ssize_t, int)
+AC_C_BIGENDIAN
+AC_C_CONST
+AC_STRUCT_ST_BLKSIZE
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+VI_CV_REPLACE_FUNCS(bsearch gethostname memchr memset)
+VI_CV_REPLACE_FUNCS(mkstemp mmap strdup strpbrk)
+VI_CV_REPLACE_FUNCS(snprintf vsnprintf)
+
+AC_CHECK_FUNCS(select memcpy)
+AC_CHECK_FUNCS(setenv, [need_env=no], [need_env=yes])
+AC_CHECK_FUNCS(strsep, [need_strsep=no], [need_strsep=yes])
+AC_CHECK_FUNCS(unsetenv,, [need_env=yes])
+
+AC_FUNC_MMAP
+AC_FUNC_VFORK
+
+dnl If we needed setenv or unsetenv, add in the clib/env.c replacement file.
+if test "$need_env" = yes; then
+       LIBOBJS="env.o $LIBOBJS"
+fi
+
+dnl If we need strsep, add it and define it so we get a prototype.
+if test "$need_strsep" = yes; then
+       LIBOBJS="strsep.o $LIBOBJS"
+fi
+
+dnl Check for fcntl/flock
+dnl Use flock preferentially, since it has cleaner semantics and won't
+dnl hang up the editor.
+dnl XXX
+dnl Ultrix has a broken fcntl, but a working flock.
+dnl IRIX and DGUX have a broken flock, but working fcntl.
+AC_MSG_CHECKING(for fcntl/flock)
+AC_CACHE_VAL(vi_cv_lock, [dnl
+       vi_cv_lock=none
+       case "$host_os" in
+       dgux*);;
+       irix*);;
+       *)
+               AC_TRY_LINK([#include <fcntl.h>], [flock(0, 0);],
+                   [vi_cv_lock=flock]);;
+       esac
+       if test "$vi_cv_lock" = none; then
+               AC_TRY_LINK([#include <fcntl.h>], [fcntl(0, F_SETLK, 0);],
+                   [vi_cv_lock=fcntl])
+       fi])
+
+if test "$vi_cv_lock" = flock; then
+       AC_DEFINE(HAVE_LOCK_FLOCK)
+fi
+if test "$vi_cv_lock" = fcntl; then
+       AC_DEFINE(HAVE_LOCK_FCNTL)
+fi
+AC_MSG_RESULT($vi_cv_lock)
+
+dnl Check for ftruncate/chsize
+AC_MSG_CHECKING(for ftruncate/chsize)
+AC_CACHE_VAL(vi_cv_ftruncate, [dnl
+AC_TRY_LINK([#include <unistd.h>], [ftruncate(0, 0);],
+       [vi_cv_ftruncate=ftruncate],
+AC_TRY_LINK([#include <unistd.h>], [chsize(0, 0);],
+       [vi_cv_ftruncate=chsize], [vi_cv_ftruncate=no]))])
+if test "$vi_cv_ftruncate" = ftruncate; then
+       AC_DEFINE(HAVE_FTRUNCATE_FTRUNCATE)
+fi
+if test "$vi_cv_ftruncate" = chsize; then
+       AC_DEFINE(HAVE_FTRUNCATE_CHSIZE)
+fi
+if test "$vi_cv_ftruncate" = no; then
+       AC_MSG_ERROR([No file truncation system call.])
+fi
+AC_MSG_RESULT($vi_cv_ftruncate)
+
+CSAVELIBS="$LIBS"
+CSAVELDFLAGS="$LDFLAGS"
+CSAVECPPFLAGS="$CPPFLAGS"
+LIBS="$CURSLIBS $LIBS"
+LDFLAGS="$CURSLDFLAGS $LDFLAGS"
+CPPFLAGS="$CURSCPPFLAGS $CPPFLAGS"
+dnl Check for the tigetstr/tigetnum functions.
+AC_MSG_CHECKING(for tigetstr/tigetnum)
+AC_CACHE_VAL(vi_cv_have_curses_tigetstr, [dnl
+AC_TRY_LINK([#include <$CURSHEADER>], [tigetstr(0);],
+       [vi_cv_have_curses_tigetstr=yes],
+       [vi_cv_have_curses_tigetstr=no])])
+if test "$vi_cv_have_curses_tigetstr" = yes; then
+       AC_DEFINE(HAVE_CURSES_TIGETSTR)
+fi
+AC_MSG_RESULT($vi_cv_have_curses_tigetstr)
+
+dnl Check for potentially missing curses functions in system or user-specified
+dnl libraries.  We also have to guess at whether the specified library is a
+dnl BSD or System V style curses.  Use the newterm function, all System V
+dnl curses implementations have it, none, as far as I know, of the BSD ones do.
+if test "$vi_cv_curses" = "bundled curses"; then
+       AC_DEFINE(HAVE_BSD_CURSES)
+       AC_DEFINE(HAVE_CURSES_WADDNSTR)
+       AC_DEFINE(HAVE_CURSES_IDLOK)
+else
+       dnl Check for the waddnstr function.
+       AC_MSG_CHECKING(for waddnstr)
+       AC_CACHE_VAL(vi_cv_have_curses_waddnstr, [dnl
+       AC_TRY_LINK([#include <$CURSHEADER>], [waddnstr(stdscr, 0, 0);],
+               [vi_cv_have_curses_waddnstr=yes],
+               [vi_cv_have_curses_waddnstr=no])])
+       if test "$vi_cv_have_curses_waddnstr" = yes; then
+               AC_DEFINE(HAVE_CURSES_WADDNSTR)
+       fi
+       AC_MSG_RESULT($vi_cv_have_curses_waddnstr)
+
+       dnl Check for the beep function.
+       AC_MSG_CHECKING(for beep)
+       AC_CACHE_VAL(vi_cv_have_curses_beep, [dnl
+       AC_TRY_LINK([#include <$CURSHEADER>], [beep();],
+               [vi_cv_have_curses_beep=yes],
+               [vi_cv_have_curses_beep=no])])
+       if test "$vi_cv_have_curses_beep" = yes; then
+               AC_DEFINE(HAVE_CURSES_BEEP)
+       fi
+       AC_MSG_RESULT($vi_cv_have_curses_beep)
+
+       dnl Check for the flash function.
+       AC_MSG_CHECKING(for flash)
+       AC_CACHE_VAL(vi_cv_have_curses_flash, [dnl
+       AC_TRY_LINK([#include <$CURSHEADER>], [flash();],
+               [vi_cv_have_curses_flash=yes],
+               [vi_cv_have_curses_flash=no])])
+       if test "$vi_cv_have_curses_flash" = yes; then
+               AC_DEFINE(HAVE_CURSES_FLASH)
+       fi
+       AC_MSG_RESULT($vi_cv_have_curses_flash)
+
+       dnl Check for the idlok function.
+       AC_MSG_CHECKING(for idlok)
+       AC_CACHE_VAL(vi_cv_have_curses_idlok, [dnl
+       AC_TRY_LINK([#include <$CURSHEADER>], [idlok(0, 0);],
+               [vi_cv_have_curses_idlok=yes],
+               [vi_cv_have_curses_idlok=no])])
+       if test "$vi_cv_have_curses_idlok" = yes; then
+               AC_DEFINE(HAVE_CURSES_IDLOK)
+       fi
+       AC_MSG_RESULT($vi_cv_have_curses_idlok)
+
+       dnl Check for the keypad function.
+       AC_MSG_CHECKING(for keypad)
+       AC_CACHE_VAL(vi_cv_have_curses_keypad, [dnl
+       AC_TRY_LINK([#include <$CURSHEADER>], [keypad(0, 0);],
+               [vi_cv_have_curses_keypad=yes],
+               [vi_cv_have_curses_keypad=no])])
+       if test "$vi_cv_have_curses_keypad" = yes; then
+               AC_DEFINE(HAVE_CURSES_KEYPAD)
+       fi
+       AC_MSG_RESULT($vi_cv_have_curses_keypad)
+
+       dnl Check for the newterm function.
+       AC_MSG_CHECKING(for newterm)
+       AC_CACHE_VAL(vi_cv_have_curses_newterm, [dnl
+       AC_TRY_LINK([#include <$CURSHEADER>], [newterm(0, 0, 0);],
+               [vi_cv_have_curses_newterm=yes],
+               [vi_cv_have_curses_newterm=no])])
+       if test "$vi_cv_have_curses_newterm" = yes; then
+               AC_DEFINE(HAVE_CURSES_NEWTERM)
+       fi
+       AC_MSG_RESULT($vi_cv_have_curses_newterm)
+
+       if test "$vi_cv_have_curses_newterm" = no; then
+               AC_DEFINE(HAVE_BSD_CURSES)
+       fi
+fi
+
+dnl Check for the setupterm function.  We make this check regardless of
+dnl using the system library, because it may be part of the underlying
+dnl termcap/termlib support, and we want to use the local one.
+AC_MSG_CHECKING(for setupterm)
+AC_CACHE_VAL(vi_cv_have_curses_setupterm, [dnl
+AC_TRY_LINK([#include <$CURSHEADER>], [setupterm(0, 0, 0);],
+       [vi_cv_have_curses_setupterm=yes],
+       [vi_cv_have_curses_setupterm=no])])
+if test "$vi_cv_have_curses_setupterm" = yes; then
+       AC_DEFINE(HAVE_CURSES_SETUPTERM)
+fi
+AC_MSG_RESULT($vi_cv_have_curses_setupterm)
+LIBS="$CSAVELIBS"
+LDFLAGS="$CSAVELDFLAGS"
+CPPFLAGS="$CSAVECPPFLAGS"
+
+dnl Some moron decided to drop off an argument from the gettimeofday call,
+dnl without changing the name.
+AC_MSG_CHECKING(for broken gettimeofday system call)
+AC_CACHE_VAL(vi_cv_gettimeofday, [dnl
+AC_TRY_LINK([#include <sys/types.h>
+#include <sys/time.h>], [gettimeofday(0, 0);],
+       [vi_cv_gettimeofday=okay], [vi_cv_gettimeofday=broken])])
+if test "$vi_cv_gettimeofday" = broken; then
+       AC_DEFINE(HAVE_BROKEN_GETTIMEOFDAY)
+fi
+AC_MSG_RESULT($vi_cv_gettimeofday)
+
+dnl Check for which version of openpty to use, System V or Berkeley.
+AC_MSG_CHECKING(for System V pty calls)
+AC_CACHE_VAL(vi_cv_sys5_pty, [dnl
+AC_TRY_LINK(, [grantpt(0);],
+       [vi_cv_sys5_pty=yes], [vi_cv_sys5_pty=no])])
+if test "$vi_cv_sys5_pty" = yes; then
+       AC_DEFINE(HAVE_SYS5_PTY)
+fi
+AC_MSG_RESULT($vi_cv_sys5_pty)
+
+dnl Check for the revoke system call.
+AC_MSG_CHECKING(for revoke system call)
+AC_CACHE_VAL(vi_cv_revoke, [dnl
+AC_TRY_LINK(, [revoke("a");],
+       [vi_cv_revoke=yes], [vi_cv_revoke=no])])
+if test "$vi_cv_revoke" = yes; then
+       AC_DEFINE(HAVE_REVOKE)
+fi
+AC_MSG_RESULT($vi_cv_revoke)
+
+dnl Some versions of sprintf return a pointer to the first argument instead
+dnl of a character count.  We assume that the return value of snprintf and
+dnl vsprintf etc. will be the same as sprintf, and check the easy one.
+AC_MSG_CHECKING(for int type sprintf return value)
+AC_CACHE_VAL(vi_cv_sprintf_count, [dnl
+AC_TRY_RUN([main(){char buf[20]; exit(sprintf(buf, "XXX") != 3);}],
+       [vi_cv_sprintf_count=yes], [vi_cv_sprintf_count=no])])
+if test "$vi_cv_sprintf_count" = no; then
+       AC_DEFINE(SPRINTF_RET_CHARPNT)
+fi
+AC_MSG_RESULT($vi_cv_sprintf_count)
+
+
+dnl Check for the standard shorthand types.
+AC_SUBST(u_char_decl)
+AC_CACHE_CHECK([for u_char], vi_cv_uchar, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_char foo;,
+       [vi_cv_uchar=yes], [vi_cv_uchar=no])])
+if test "$vi_cv_uchar" = no; then
+       u_char_decl="typedef unsigned char u_char;"
+fi
+
+AC_SUBST(u_short_decl)
+AC_CACHE_CHECK([for u_short], vi_cv_ushort, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_short foo;,
+       [vi_cv_ushort=yes], [vi_cv_ushort=no])])
+if test "$vi_cv_ushort" = no; then
+       u_short_decl="typedef unsigned short u_short;"
+fi
+
+AC_SUBST(u_int_decl)
+AC_CACHE_CHECK([for u_int], vi_cv_uint, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int foo;,
+       [vi_cv_uint=yes], [vi_cv_uint=no])])
+if test "$vi_cv_uint" = no; then
+       u_int_decl="typedef unsigned int u_int;"
+fi
+
+AC_SUBST(u_long_decl)
+AC_CACHE_CHECK([for u_long], vi_cv_ulong, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_long foo;,
+       [vi_cv_ulong=yes], [vi_cv_ulong=no])])
+if test "$vi_cv_ulong" = no; then
+       u_long_decl="typedef unsigned long u_long;"
+fi
+
+dnl DB/Vi use specific integer sizes.
+AC_SUBST(u_int8_decl)
+AC_CACHE_CHECK([for u_int8_t], vi_cv_uint8, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int8_t foo;,
+       [vi_cv_uint8=yes],
+       AC_TRY_RUN([main(){exit(sizeof(unsigned char) != 1);}],
+           [vi_cv_uint8="unsigned char"], [vi_cv_uint8=no]))])
+if test "$vi_cv_uint8" = no; then
+       AC_MSG_ERROR(No unsigned 8-bit integral type.)
+fi
+if test "$vi_cv_uint8" != yes; then
+       u_int8_decl="typedef $vi_cv_uint8 u_int8_t;"
+fi
+
+AC_SUBST(u_int16_decl)
+AC_CACHE_CHECK([for u_int16_t], vi_cv_uint16, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int16_t foo;,
+       [vi_cv_uint16=yes],
+AC_TRY_RUN([main(){exit(sizeof(unsigned short) != 2);}],
+       [vi_cv_uint16="unsigned short"],
+AC_TRY_RUN([main(){exit(sizeof(unsigned int) != 2);}],
+       [vi_cv_uint16="unsigned int"], [vi_cv_uint16=no])))])
+if test "$vi_cv_uint16" = no; then
+       AC_MSG_ERROR([No unsigned 16-bit integral type.])
+fi
+if test "$vi_cv_uint16" != yes; then
+       u_int16_decl="typedef $vi_cv_uint16 u_int16_t;"
+fi
+
+AC_SUBST(int16_decl)
+AC_CACHE_CHECK([for int16_t], vi_cv_int16, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], int16_t foo;,
+       [vi_cv_int16=yes],
+AC_TRY_RUN([main(){exit(sizeof(short) != 2);}],
+       [vi_cv_int16="short"],
+AC_TRY_RUN([main(){exit(sizeof(int) != 2);}],
+       [vi_cv_int16="int"], [vi_cv_int16=no])))])
+if test "$vi_cv_int16" = no; then
+       AC_MSG_ERROR([No signed 16-bit integral type.])
+fi
+if test "$vi_cv_int16" != yes; then
+       int16_decl="typedef $vi_cv_int16 int16_t;"
+fi
+
+AC_SUBST(u_int32_decl)
+AC_CACHE_CHECK([for u_int32_t], vi_cv_uint32, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int32_t foo;,
+       [vi_cv_uint32=yes],
+AC_TRY_RUN([main(){exit(sizeof(unsigned int) != 4);}],
+       [vi_cv_uint32="unsigned int"],
+AC_TRY_RUN([main(){exit(sizeof(unsigned long) != 4);}],
+       [vi_cv_uint32="unsigned long"], [vi_cv_uint32=no])))])
+if test "$vi_cv_uint32" = no; then
+       AC_MSG_ERROR([No unsigned 32-bit integral type.])
+fi
+if test "$vi_cv_uint32" != yes; then
+       u_int32_decl="typedef $vi_cv_uint32 u_int32_t;"
+fi
+
+AC_SUBST(int32_decl)
+AC_CACHE_CHECK([for int32_t], vi_cv_int32, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], int32_t foo;,
+       [vi_cv_int32=yes],
+AC_TRY_RUN([main(){exit(sizeof(int) != 4);}],
+       [vi_cv_int32="int"],
+AC_TRY_RUN([main(){exit(sizeof(long) != 4);}],
+       [vi_cv_int32="long"], [vi_cv_int32=no])))])
+if test "$vi_cv_int32" = no; then
+       AC_MSG_ERROR([No signed 32-bit integral type.])
+fi
+if test "$vi_cv_int32" != yes; then
+       int32_decl="typedef $vi_cv_int32 int32_t;"
+fi
+
+AC_CACHE_CHECK([return type of fprintf], vi_cv_type_fprintf,
+[AC_TRY_COMPILE([#include <stdio.h>
+int fprintf ();
+],[int i;], vi_cv_type_fprintf=int, vi_cv_type_fprintf=void)])
+
+AC_SUBST(NEED_FPRINTF_PROTO)
+AC_CACHE_CHECK([fprintf prototype needed], vi_cv_proto_fprintf,
+[AC_TRY_COMPILE([ #include <stdio.h>
+typedef int     (*funcPtr)();
+],[funcPtr ptr = (funcPtr) fprintf;], 
+vi_cv_proto_fprintf=no, 
+[vi_cv_proto_fprintf=yes])])
+if test "$vi_cv_proto_fprintf" = yes; then
+       AC_DEFINE(NEED_FPRINTF_PROTO)
+fi
+
+AC_ARG_WITH(db_type,
+       [  --with-db=bundled|system Which db to use. ])
+case "$with_db_type" in
+"db1")
+       AC_MSG_WARN([Use of db1 is not officially supported.])
+       AC_DEFINE(USE_DB1)
+       ;;
+"system")
+       ;;
+*)
+       with_db_type="bundled"
+       ;;
+esac
+
+dnl Check for DB 3
+AC_ARG_WITH(db_prefix,
+       [  --with-db-prefix=PFX    Path to db installation. ])
+
+SAVELDFLAGS="$LDFLAGS"
+if test "x$with_db_prefix" != "x"; then
+       LDFLAGS="-L$with_db_prefix/lib $LDFLAGS"
+       CPPFLAGS="-I$with_db_prefix/include $CPPFLAGS"
+fi
+if test "$with_db_type" != db1; then
+       SAVELIBS="$LIBS"
+
+       LIBS="$LIBS -ldb"
+       AC_TRY_LINK([#include <db.h>],
+               [db_create(NULL,NULL,0)],
+               [vi_cv_dbfatal="no"], [vi_cv_dbfatal="yes"])
+       if test "$vi_cv_dbfatal" = "yes"; then
+               AC_MSG_ERROR([Need DB 3.])
+       fi
+
+       LIBS="$SAVELIBS"
+fi
+LDFLAGS="$SAVELDFLAGS"
+
+AC_SUBST(dl_src)
+AC_MSG_CHECKING(if --enable-dynamic-loading option specified)
+AC_ARG_ENABLE(dynamic-loading,
+       [  --enable-dynamic-loading Load DB 3 dynamically.],
+       [vi_cv_dl=$enableval], [vi_cv_dl="no"])
+AC_MSG_RESULT($vi_cv_dl)
+if test "$vi_cv_dl" = yes; then
+       AC_CHECK_LIB(dl, dlopen,
+               [vi_cv_dlfatal="no"], [vi_cv_dlfatal="yes"])
+       if test "$vi_cv_dlfatal" = "yes"; then
+               AC_MSG_ERROR([Need dl to support dynamic loading.])
+       fi
+       OLDPATH="$PATH"
+
+       PATH="$with_db_prefix/lib:/usr/lib:/lib"
+       AC_PATH_PROG(vi_cv_path_db3, libdb-3.so, no)
+       if test "$vi_cv_path_db3" = no; then
+               AC_MSG_ERROR([Path of libdb-3.so not found.])
+       fi
+       PATH="$OLDPATH"
+
+       AC_DEFINE(USE_DYNAMIC_LOADING)
+       LIBOBJS="dldb.o $LIBOBJS"
+       dl_src=../common/dldb.c
+       LIBS="-ldl $LIBS"
+else
+       LIBS="-ldb $LIBS"
+       if test "X$with_db_prefix" != "X"; then
+               LDFLAGS="`echo $with_db_prefix/lib | sed "$LRscript"` $LDFLAGS"
+       fi
+fi
+
+AC_ARG_WITH(db_build,
+       [  --with-db-build=prefix  Path to db build. ])
+if test "x$with_db_build" != "x"; then
+       vi_cv_dbsrc=`$AWK '/^srcdir/ {gsub("srcdir[[ \t]]*=","");print $1}' \
+                    $with_db_build/Makefile`
+       case $with_db_build in
+       *[[\\/]]);;
+       *)
+           with_db_build="$with_db_build/";;
+       esac
+       case $vi_cv_dbsrc in
+       [[\\/]]*);;
+       *)
+           vi_cv_dbsrc="$with_db_build$vi_cv_dbsrc";;
+       esac
+fi;
+
+vi_cv_db4="no"
+AC_ARG_ENABLE(log4,
+       [  --enable-db4-logging    Enable experimental/broken db4 logging.],
+       [
+       AC_MSG_CHECKING(for DB 4)
+       AC_EGREP_CPP([^4],
+               [#include <db.h>
+       DB_VERSION_MAJOR],
+               [vi_cv_db4="yes"], [vi_cv_db4="no"])
+       AC_MSG_RESULT($vi_cv_db4)
+       ])
+if test "$vi_cv_db4" = "yes"; then
+       CPPFLAGS="-I$vi_cv_dbsrc/include $CPPFLAGS"
+       CPPFLAGS="-I$vi_cv_dbsrc/include_auto $CPPFLAGS"
+       CPPFLAGS="-I$with_db_build $CPPFLAGS"
+       AC_DEFINE(USE_DB4_LOGGING)
+       LIBOBJS="log4.o vi_auto.o vi_rec.o $LIBOBJS"
+else
+       LIBOBJS="log.o $LIBOBJS"
+fi
+
+dnl We compile in nvi's RE routines unless the user specifies otherwise.
+AC_MSG_CHECKING(if --disable-re option specified)
+AC_ARG_ENABLE(re,
+       [  --disable-re            DON'T use the nvi-provided RE routines.],
+       [if test "$enable_re" = "yes"; then
+               vi_cv_re_lib="bundled RE"
+       else
+               vi_cv_re_lib="other RE"
+       fi],[vi_cv_re_lib="bundled RE"])
+AC_MSG_RESULT($vi_cv_re_lib)
+case "$vi_cv_re_lib" in
+"bundled RE")
+       CPPFLAGS="-I\$(visrcdir)/regex $CPPFLAGS"
+       LIBOBJS="regcomp.o regerror.o regexec.o regfree.o $LIBOBJS";;
+"other RE")
+       ;;
+esac
+
+AC_OUTPUT(Makefile port.h:port.h.in
+    pathnames.h:pathnames.h.in recover:recover.in)
diff --git a/dist/nvi/dist/depcomp b/dist/nvi/dist/depcomp
new file mode 100644 (file)
index 0000000..6589965
--- /dev/null
@@ -0,0 +1,411 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+  "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  This file always lives in the current directory.
+  # Also, the AIX compiler puts `$object:' at the start of each line;
+  # $object doesn't have directory information.
+  stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+  tmpdepfile="$stripped.u"
+  outname="$stripped.o"
+  if test "$libtool" = yes; then
+    "$@" -Wc,-M
+  else
+    "$@" -M
+  fi
+
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+tru64)
+   # The Tru64 AIX compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+
+   tmpdepfile1="$object.d"
+   tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` 
+   if test "$libtool" = yes; then
+      "$@" -Wc,-MD
+   else
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2"
+      exit $stat
+   fi
+
+   if test -f "$tmpdepfile1"; then
+      tmpdepfile="$tmpdepfile1"
+   else
+      tmpdepfile="$tmpdepfile2"
+   fi
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a space and a tab in the [].
+      sed -e 's,^.*\.[a-z]*:[  ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  test -z "$dashmflag" && dashmflag=-M
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*) # this is libtool, let us make it quiet
+      for arg
+      do # cycle over the arguments
+        case "$arg" in
+       "--mode=compile")
+         # insert --quiet before "--mode=compile"
+         set fnord "$@" --quiet
+         shift # fnord
+         ;;
+       esac
+       set fnord "$@" "$arg"
+       shift # fnord
+       shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" $dashmflag | sed 's:^[^:]*\:[         ]*:'"$object"'\: :' > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  # X makedepend
+  (
+    shift
+    cleared=no
+    for arg in "$@"; do
+      case $cleared in no)
+        set ""; shift
+       cleared=yes
+      esac
+      case "$arg" in
+        -D*|-I*)
+         set fnord "$@" "$arg"; shift;;
+       -*)
+         ;;
+       *)
+         set fnord "$@" "$arg"; shift;;
+      esac
+    done
+    obj_suffix="`echo $object | sed 's/^.*\././'`"
+    touch "$tmpdepfile"
+    ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tail +3 "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*)
+      for arg
+      do # cycle over the arguments
+        case $arg in
+       "--mode=compile")
+         # insert --quiet before "--mode=compile"
+         set fnord "$@" --quiet
+         shift # fnord
+         ;;
+       esac
+       set fnord "$@" "$arg"
+       shift # fnord
+       shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" -E |
+    sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*)
+      for arg
+      do # cycle over the arguments
+        case $arg in
+       "--mode=compile")
+         # insert --quiet before "--mode=compile"
+         set fnord "$@" --quiet
+         shift # fnord
+         ;;
+       esac
+       set fnord "$@" "$arg"
+       shift # fnord
+       shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" -E |
+    sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::   \1 \\:p' >> "$depfile"
+  echo "       " >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
diff --git a/dist/nvi/dist/distrib b/dist/nvi/dist/distrib
new file mode 100644 (file)
index 0000000..4faa66b
--- /dev/null
@@ -0,0 +1,88 @@
+#! /bin/sh
+# Id: distrib,v 8.24 2001/06/25 11:20:24 skimo Exp (Berkeley) Date: 2001/06/25 11:20:24
+
+echo "Running libtoolize"
+libtoolize -c --force
+
+echo "Building aclocal.m4"
+rm -f aclocal.m4
+aclocal -I m4
+
+# Build autoconf structure.
+echo "Running autoheader"
+autoheader 2>&1 | sed '/warning: AC_TRY_RUN called without default/d'
+chmod 444 config.h.in
+echo "Running automake"
+automake -a -c --foreign $@
+rm -f configure
+echo "Running autoconf"
+autoconf 2>&1 | sed '/warning: AC_TRY_RUN called without default/d'
+chmod 555 configure config.guess config.sub install-sh
+
+msg="/* Do not edit: automatically built by build/distrib. */"
+# Build automatically generated header files.
+f=../ipc/ipc_def.h
+echo "Building $f"
+rm -f $f
+(echo "$msg" && \
+    awk -f ../ipc/ipc.awk ../ipc/ipc_cmd.c &&
+    awk -f ../ipc/vipc.awk ../ip/ip_read.c) > $f
+chmod 444 $f
+
+f=../ipc/ipc_gen.c
+echo "Building $f"
+rm -f $f
+(echo "$msg" && \
+    perl -n ../ip/vipc.pl ../ip/ip_read.c) > $f
+chmod 444 $f
+
+f=../ex/ex_def.h
+echo "Building $f"
+rm -f $f
+(echo "$msg" && \
+    awk -f ../ex/ex.awk ../ex/ex_cmd.c) > $f
+chmod 444 $f
+
+f=../common/options_def.h
+echo "Building $f"
+rm -f $f
+(echo "$msg" && \
+    awk -f ../common/options.awk ../common/options.c) > $f
+chmod 444 $f
+
+# Build the automatically generated function prototype files.
+for i in cl common ex gtk ip ipc motif motif_l tcl_api vi; do
+       f=../$i/extern.h
+       rm -f $f
+       echo "Building $f"
+       (echo "$msg" && \
+           sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../$i/*.c) > $f
+       chmod 444 $f
+done
+
+# Build the automatically generated function prototype files.
+for i in perl_api ; do
+       f=../$i/extern.h
+       rm -f $f
+       echo "Building $f"
+       (echo "$msg" && \
+           sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../$i/*.c ../$i/*.xs) > $f
+       chmod 444 $f
+done
+
+# Build tags files.
+echo "Building tags files"
+f=tags
+rm -f $f
+if test $USER = 'bostic'; then ctagsopt = '-d'; fi
+ctags $ctagsopt -w \
+       ../cl/*.[ch] ../common/*.[ch] ../ex/*.[ch] ../gtk/*.[ch] ../ip/*.[ch] \
+       ../ipc/*.[ch] ../motif/*.[ch] ../motif_l/*.[ch] ../perl_api/*.[ch] \
+       ../tcl_api/*.[ch] ../vi/*.[ch]
+chmod 444 $f
+
+date=`date +%Y-%m-%d`
+echo "Building ../ex/version.h"
+echo '#define VI_VERSION "'`git-describe` '('$date')"' > ../ex/version.h
+
+touch stamp-h.in
diff --git a/dist/nvi/dist/export b/dist/nvi/dist/export
new file mode 100644 (file)
index 0000000..c0fe056
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+revision=${@:-HEAD}
+gitrev=`git describe $revision`
+dir=$gitrev
+version=`echo $gitrev | sed -e 's/nvi-//'`
+date=`date +%Y-%m-%d`
+(cd .. && git archive --format=tar --prefix=$dir/ $revision) | tar x $dir
+(cd $dir/dist
+    sh distrib --ignore-deps
+    rm export
+)
+(cd $dir/docs
+    mkdir html
+    for i in edit exref vi.man vi.ref vitut; do 
+       (cd $i; 
+        make;
+        rm -f core # grops sometimes dumps core on me
+        ); 
+    done
+)
+(cd $dir
+    perl -pi -e "s/version 1.80/version $version/" README
+    perl -pi -e "s(%H%)($date)" README
+)
+tar czf $dir.tar.gz $dir
+tar cjf $dir.tar.bz2 $dir
diff --git a/dist/nvi/dist/findconfig b/dist/nvi/dist/findconfig
new file mode 100644 (file)
index 0000000..166a03d
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+# the next line restarts using tclsh \
+exec tclsh "$0" "$@"
+
+# A utility that searches for the 'tclConfig.sh' shell script
+# which contains platform-specific compiler/linker options for
+# building Tcl programs and shared libraries.
+
+foreach dir $tcl_pkgPath {
+    if [file exists $dir/tclConfig.sh] {
+        puts $dir/tclConfig.sh
+        exit
+    }
+}
diff --git a/dist/nvi/dist/install-sh b/dist/nvi/dist/install-sh
new file mode 100644 (file)
index 0000000..4fbbae7
--- /dev/null
@@ -0,0 +1,507 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-10-14.15
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+posix_glob=
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chmodcmd=$chmodprog
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c         (ignored)
+-d         create directories instead of installing files.
+-g GROUP   $chgrpprog installed files to GROUP.
+-m MODE    $chmodprog installed files to MODE.
+-o USER    $chownprog installed files to USER.
+-s         $stripprog installed files.
+-t DIRECTORY  install into DIRECTORY.
+-T         report an error if DSTFILE is a directory.
+--help     display this help and exit.
+--version  display version info and exit.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+        shift
+        shift
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t) dstarg=$2
+       shift
+       shift
+       continue;;
+
+    -T) no_target_directory=true
+       shift
+       continue;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
+       break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
+  esac
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dstarg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dstarg"
+      shift # fnord
+    fi
+    shift # arg
+    dstarg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src ;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dstarg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dstarg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst ;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+       echo "$0: $dstarg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writeable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+       /*) prefix=/ ;;
+       -*) prefix=./ ;;
+       *)  prefix= ;;
+      esac
+
+      case $posix_glob in
+        '')
+         if (set -f) 2>/dev/null; then
+           posix_glob=true
+         else
+           posix_glob=false
+         fi ;;
+      esac
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob && set -f
+      set fnord $dstdir
+      shift
+      $posix_glob && set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test -z "$d" && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # Now rename the file to the real destination.
+    { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
+      || {
+          # The rename failed, perhaps because mv can't rename something else
+          # to itself, or perhaps because mv is so ancient that it does not
+          # support -f.
+
+          # Now remove or move aside any old file at destination location.
+          # We try this two ways since rm can't unlink itself on some
+          # systems and the destination file might be busy for other
+          # reasons.  In this case, the final cleanup might fail but the new
+          # file should still install successfully.
+          {
+            if test -f "$dst"; then
+              $doit $rmcmd -f "$dst" 2>/dev/null \
+              || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
+                    && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
+              || {
+                echo "$0: cannot unlink or rename $dst" >&2
+                (exit 1); exit 1
+              }
+            else
+              :
+            fi
+          } &&
+
+          # Now rename the file to the real destination.
+          $doit $mvcmd "$dsttmp" "$dst"
+        }
+    } || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/dist/nvi/dist/ltconfig b/dist/nvi/dist/ltconfig
new file mode 100644 (file)
index 0000000..a362c48
--- /dev/null
@@ -0,0 +1,2967 @@
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+echo=echo
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec "$SHELL" "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != "Xset"; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) PATH_SEPARATOR=';' ;;
+    *)     PATH_SEPARATOR=':' ;;
+  esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
+
+if test "X${echo_test_string+set}" != "Xset"; then
+  # find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
+   test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+  for dir in $PATH /usr/ucb; do
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running ltconfig again with it.
+      ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
+    else
+      # Try using printf.
+      echo='printf "%s\n"'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+          test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+       CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+          test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "$0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# The name of this program.
+progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.3.2
+TIMESTAMP=" (1.385.2.150 1999/05/26 00:28:32)"
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking.
+enable_static=yes
+enable_fast_install=yes
+enable_dlopen=unknown
+enable_win32_dll=no
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+ofile="$default_ofile"
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+need_locks=yes
+ac_ext=c
+objext=o
+libext=a
+cache_file=
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LDFLAGS="$LDFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_LIBS="$LIBS"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+old_DLLTOOL="$DLLTOOL"
+old_OBJDUMP="$OBJDUMP"
+old_AS="$AS"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+  case "$option" in
+  -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    eval "$prev=\$option"
+    prev=
+    continue
+  fi
+
+  case "$option" in
+  --help) cat <<EOM
+Usage: $progname [OPTION]... [HOST [LTMAIN]]
+
+Generate a system-specific libtool script.
+
+    --debug                enable verbose shell tracing
+    --disable-shared       do not build shared libraries
+    --disable-static       do not build static libraries
+    --disable-fast-install do not optimize for fast installation
+    --enable-dlopen        enable dlopen support
+    --enable-win32-dll     enable building dlls on win32 hosts
+    --help                 display this help and exit
+    --no-verify            do not verify that HOST is a valid host type
+-o, --output=FILE          specify the output file [default=$default_ofile]
+    --quiet                same as \`--silent'
+    --silent               do not print informational messages
+    --srcdir=DIR           find \`config.guess' in DIR
+    --version              output version information and exit
+    --with-gcc             assume that the GNU C compiler will be used
+    --with-gnu-ld          assume that the C compiler uses the GNU linker
+    --disable-lock         disable file locking
+    --cache-file=FILE      configure cache file
+
+LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
+that provides basic libtool functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+  exit 0
+  ;;
+
+  --debug)
+    echo "$progname: enabling shell trace mode"
+    set -x
+    ;;
+
+  --disable-shared) enable_shared=no ;;
+
+  --disable-static) enable_static=no ;;
+
+  --disable-fast-install) enable_fast_install=no ;;
+
+  --enable-dlopen) enable_dlopen=yes ;;
+
+  --enable-win32-dll) enable_win32_dll=yes ;;
+
+  --quiet | --silent) silent=yes ;;
+
+  --srcdir) prev=srcdir ;;
+  --srcdir=*) srcdir="$optarg" ;;
+
+  --no-verify) verify_host=no ;;
+
+  --output | -o) prev=ofile ;;
+  --output=*) ofile="$optarg" ;;
+
+  --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
+
+  --with-gcc) with_gcc=yes ;;
+  --with-gnu-ld) with_gnu_ld=yes ;;
+
+  --disable-lock) need_locks=no ;;
+
+  --cache-file=*) cache_file="$optarg" ;;
+
+  -*)
+    echo "$progname: unrecognized option \`$option'" 1>&2
+    echo "$help" 1>&2
+    exit 1
+    ;;
+
+  *)
+    if test -z "$ltmain"; then
+      ltmain="$option"
+    elif test -z "$host"; then
+# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+#      if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+#        echo "$progname: warning \`$option' is not a valid host type" 1>&2
+#      fi
+      host="$option"
+    else
+      echo "$progname: too many arguments" 1>&2
+      echo "$help" 1>&2
+      exit 1
+    fi ;;
+  esac
+done
+
+if test -z "$ltmain"; then
+  echo "$progname: you must specify a LTMAIN file" 1>&2
+  echo "$help" 1>&2
+  exit 1
+fi
+
+if test ! -f "$ltmain"; then
+  echo "$progname: \`$ltmain' does not exist" 1>&2
+  echo "$help" 1>&2
+  exit 1
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+  case "$arg" in
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ltconfig_args="$ltconfig_args '$arg'" ;;
+  *) ltconfig_args="$ltconfig_args $arg" ;;
+  esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+
+if test -n "$cache_file" && test -r "$cache_file"; then
+  echo "loading cache $cache_file within ltconfig"
+  . $cache_file
+fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+  # Assume the source directory is the same one as the path to LTMAIN.
+  srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
+  test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+  # Check for config.guess and config.sub.
+  ac_aux_dir=
+  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+    if test -f $ac_dir/config.guess; then
+      ac_aux_dir=$ac_dir
+      break
+    fi
+  done
+  if test -z "$ac_aux_dir"; then
+    echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+    echo "$help" 1>&2
+    exit 1
+  fi
+  ac_config_guess=$ac_aux_dir/config.guess
+  ac_config_sub=$ac_aux_dir/config.sub
+
+  # Make sure we can run config.sub.
+  if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
+  else
+    echo "$progname: cannot run $ac_config_sub" 1>&2
+    echo "$help" 1>&2
+    exit 1
+  fi
+
+  echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+  host_alias=$host
+  case "$host_alias" in
+  "")
+    if host_alias=`$SHELL $ac_config_guess`; then :
+    else
+      echo "$progname: cannot guess host type; you must specify one" 1>&2
+      echo "$help" 1>&2
+      exit 1
+    fi ;;
+  esac
+  host=`$SHELL $ac_config_sub $host_alias`
+  echo "$ac_t$host" 1>&6
+
+  # Make sure the host verified.
+  test -z "$host" && exit 1
+
+elif test -z "$host"; then
+  echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+  echo "$help" 1>&2
+  exit 1
+else
+  host_alias=$host
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host_os" in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "${COLLECT_NAMES+set}" != set; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# Set a sane default for `OBJDUMP'.
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+  result=no
+
+  echo $ac_n "checking for ranlib... $ac_c" 1>&6
+  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+  for dir in $PATH; do
+    test -z "$dir" && dir=.
+    if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
+      RANLIB="ranlib"
+      result="ranlib"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+  old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+fi
+
+# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$AS" && AS=as
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+  # If CC is not set, then try to find GCC or a usable CC.
+  if test -z "$CC"; then
+    echo $ac_n "checking for gcc... $ac_c" 1>&6
+    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    for dir in $PATH; do
+      test -z "$dir" && dir=.
+      if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
+       CC="gcc"
+       break
+      fi
+    done
+    IFS="$save_ifs"
+
+    if test -n "$CC"; then
+      echo "$ac_t$CC" 1>&6
+    else
+      echo "$ac_t"no 1>&6
+    fi
+  fi
+
+  # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+  if test -z "$CC"; then
+    echo $ac_n "checking for cc... $ac_c" 1>&6
+    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    cc_rejected=no
+    for dir in $PATH; do
+      test -z "$dir" && dir=.
+      if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
+       if test "$dir/cc" = "/usr/ucb/cc"; then
+         cc_rejected=yes
+         continue
+       fi
+       CC="cc"
+       break
+      fi
+    done
+    IFS="$save_ifs"
+    if test $cc_rejected = yes; then
+      # We found a bogon in the path, so make sure we never use it.
+      set dummy $CC
+      shift
+      if test $# -gt 0; then
+       # We chose a different compiler from the bogus one.
+       # However, it has the same name, so the bogon will be chosen
+       # first if we set CC to just the name; use the full file name.
+       shift
+       set dummy "$dir/cc" "$@"
+       shift
+       CC="$@"
+      fi
+    fi
+
+    if test -n "$CC"; then
+      echo "$ac_t$CC" 1>&6
+    else
+      echo "$ac_t"no 1>&6
+    fi
+
+    if test -z "$CC"; then
+      echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+      exit 1
+    fi
+  fi
+
+  # Now see if the compiler is really GCC.
+  with_gcc=no
+  echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+  echo "$progname:579: checking whether we are using GNU C" >&5
+
+  $rm conftest.c
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+  if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:587: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+    with_gcc=yes
+  fi
+  $rm conftest.c
+  echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for object suffix... $ac_c" 1>&6
+$rm conftest*
+echo 'int i = 1;' > conftest.c
+echo "$progname:601: checking for object suffix" >& 5
+if { (eval echo $progname:602: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
+  # Append any warnings to the config.log.
+  cat conftest.err 1>&5
+
+  for ac_file in conftest.*; do
+    case $ac_file in
+    *.c) ;;
+    *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
+    esac
+  done
+else
+  cat conftest.err 1>&5
+  echo "$progname: failed program was:" >&5
+  cat conftest.c >&5
+fi
+$rm conftest*
+echo "$ac_t$objext" 1>&6
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+  wl='-Wl,'
+  link_static_flag='-static'
+
+  case "$host_os" in
+  beos* | irix5* | irix6* | osf3* | osf4*)
+    # PIC is the default for these OSes.
+    ;;
+  aix*)
+    # Below there is a dirty hack to force normal static linking with -ldl
+    # The problem is because libdl dynamically linked with both libc and
+    # libC (AIX C++ library), which obviously doesn't included in libraries
+    # list by gcc. This cause undefined symbols with -static flags.
+    # This hack allows C programs to be linked with "-static -ldl", but
+    # we not sure about C++ programs.
+    link_static_flag="$link_static_flag ${wl}-lC"
+    ;;
+  cygwin* | mingw* | os2*)
+    # We can build DLLs from non-PIC.
+    ;;
+  amigaos*)
+    # FIXME: we need at least 68020 code to build shared libraries, but
+    # adding the `-m68020' flag to GCC prevents building anything better,
+    # like `-m68040'.
+    pic_flag='-m68020 -resident32 -malways-restore-a4'
+    ;;
+  sysv4*MP*)
+    if test -d /usr/nec; then
+       pic_flag=-Kconform_pic
+    fi
+    ;;
+  *)
+    pic_flag='-fPIC'
+    ;;
+  esac
+else
+  # PORTME Check for PIC flags for the system compiler.
+  case "$host_os" in
+  aix3* | aix4*)
+    # All AIX code is PIC.
+    link_static_flag='-bnso -bI:/lib/syscalls.exp'
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    # Is there a better link_static_flag that works with the bundled CC?
+    wl='-Wl,'
+    link_static_flag="${wl}-a ${wl}archive"
+    pic_flag='+Z'
+    ;;
+
+  irix5* | irix6*)
+    wl='-Wl,'
+    link_static_flag='-non_shared'
+    # PIC (with -KPIC) is the default.
+    ;;
+
+  cygwin* | mingw* | os2*)
+    # We can build DLLs from non-PIC.
+    ;;
+
+  osf3* | osf4*)
+    # All OSF/1 code is PIC.
+    wl='-Wl,'
+    link_static_flag='-non_shared'
+    ;;
+
+  sco3.2v5*)
+    pic_flag='-Kpic'
+    link_static_flag='-dn'
+    special_shlib_compile_flags='-belf'
+    ;;
+
+  solaris*)
+    pic_flag='-KPIC'
+    link_static_flag='-Bstatic'
+    wl='-Wl,'
+    ;;
+
+  sunos4*)
+    pic_flag='-PIC'
+    link_static_flag='-Bstatic'
+    wl='-Qoption ld '
+    ;;
+
+  sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+    pic_flag='-KPIC'
+    link_static_flag='-Bstatic'
+    wl='-Wl,'
+    ;;
+
+  uts4*)
+    pic_flag='-pic'
+    link_static_flag='-Bstatic'
+    ;;
+  sysv4*MP*)
+    if test -d /usr/nec ;then
+      pic_flag='-Kconform_pic'
+      link_static_flag='-Bstatic'
+    fi
+    ;;
+  *)
+    can_build_shared=no
+    ;;
+  esac
+fi
+
+if test -n "$pic_flag"; then
+  echo "$ac_t$pic_flag" 1>&6
+
+  # Check to make sure the pic_flag actually works.
+  echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+  $rm conftest*
+  echo "int some_variable = 0;" > conftest.c
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $pic_flag -DPIC"
+  echo "$progname:742: checking if $compiler PIC flag $pic_flag works" >&5
+  if { (eval echo $progname:743: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
+    # Append any warnings to the config.log.
+    cat conftest.err 1>&5
+    
+    case "$host_os" in
+    hpux9* | hpux10* | hpux11*)
+      # On HP-UX, both CC and GCC only warn that PIC is supported... then they
+      # create non-PIC objects.  So, if there were any warnings, we assume that
+      # PIC is not supported.
+      if test -s conftest.err; then
+       echo "$ac_t"no 1>&6
+       can_build_shared=no
+       pic_flag=
+      else
+       echo "$ac_t"yes 1>&6
+       pic_flag=" $pic_flag"
+      fi
+      ;;
+    *)
+      echo "$ac_t"yes 1>&6
+      pic_flag=" $pic_flag"
+      ;;
+    esac
+  else
+    # Append any errors to the config.log.
+    cat conftest.err 1>&5
+    can_build_shared=no
+    pic_flag=
+    echo "$ac_t"no 1>&6
+  fi
+  CFLAGS="$save_CFLAGS"
+  $rm conftest*
+else
+  echo "$ac_t"none 1>&6
+fi
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+$rm conftest*
+echo "int some_variable = 0;" > conftest.c
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory.  Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.o"
+echo "$progname:795: checking if $compiler supports -c -o file.o" >&5
+if { (eval echo $progname:796: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
+
+  # The compiler can only warn and ignore the option if not recognized
+  # So say no if there are warnings
+    if test -s out/conftest.err; then
+      echo "$ac_t"no 1>&6
+      compiler_c_o=no
+    else
+      echo "$ac_t"yes 1>&6
+      compiler_c_o=yes
+    fi
+else
+  # Append any errors to the config.log.
+  cat out/conftest.err 1>&5
+  compiler_c_o=no
+  echo "$ac_t"no 1>&6
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+if test x"$compiler_c_o" = x"yes"; then
+  # Check to see if we can write to a .lo
+  echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
+  $rm conftest*
+  echo "int some_variable = 0;" > conftest.c
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -c -o conftest.lo"
+  echo "$progname:828: checking if $compiler supports -c -o file.lo" >&5
+if { (eval echo $progname:829: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
+
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+      if test -s conftest.err; then
+       echo "$ac_t"no 1>&6
+       compiler_o_lo=no
+      else
+       echo "$ac_t"yes 1>&6
+       compiler_o_lo=yes
+      fi
+  else
+    # Append any errors to the config.log.
+    cat conftest.err 1>&5
+    compiler_o_lo=no
+    echo "$ac_t"no 1>&6
+  fi
+  CFLAGS="$save_CFLAGS"
+  $rm conftest*
+else
+  compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  echo "$ac_t$hard_links" 1>&6
+  $rm conftest*
+  if test "$hard_links" = no; then
+    echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+if test "$with_gcc" = yes; then
+  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+  echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
+  $rm conftest*
+  echo "int some_variable = 0;" > conftest.c
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
+  echo "$progname:880: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+  if { (eval echo $progname:881: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+      if test -s conftest.err; then
+       echo "$ac_t"no 1>&6
+       compiler_rtti_exceptions=no
+      else
+       echo "$ac_t"yes 1>&6
+       compiler_rtti_exceptions=yes
+      fi
+  else
+    # Append any errors to the config.log.
+    cat conftest.err 1>&5
+    compiler_rtti_exceptions=no
+    echo "$ac_t"no 1>&6
+  fi
+  CFLAGS="$save_CFLAGS"
+  $rm conftest*
+
+  if test "$compiler_rtti_exceptions" = "yes"; then
+    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+  else
+    no_builtin_flag=' -fno-builtin'
+  fi
+  
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+  echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+  if echo "$old_CC $old_CFLAGS " | egrep -e "[         ]$special_shlib_compile_flags[  ]" >/dev/null; then :
+  else
+    echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+    can_build_shared=no
+  fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:924: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:925: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  echo "$ac_t$link_static_flag" 1>&6
+else
+  echo "$ac_t"none 1>&6
+  link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+  # Check to see if we can use ln -s, or we need hard links.
+  echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+  $rm conftest.dat
+  if ln -s X conftest.dat 2>/dev/null; then
+    $rm conftest.dat
+    LN_S="ln -s"
+  else
+    LN_S=ln
+  fi
+  if test "$LN_S" = "ln -s"; then
+    echo "$ac_t"yes 1>&6
+  else
+    echo "$ac_t"no 1>&6
+  fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+  ac_prog=ld
+  if test "$with_gcc" = yes; then
+    # Check if gcc -print-prog-name=ld gives a path.
+    echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+    echo "$progname:957: checking for ld used by GCC" >&5
+    ac_prog=`($CC -print-prog-name=ld) 2>&5`
+    case "$ac_prog" in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+    "")
+      # If it fails, then pretend we are not using GCC.
+      ac_prog=ld
+      ;;
+    *)
+      # If it is relative, then search for the first ld in PATH.
+      with_gnu_ld=unknown
+      ;;
+    esac
+  elif test "$with_gnu_ld" = yes; then
+    echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+    echo "$progname:981: checking for GNU ld" >&5
+  else
+    echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+    echo "$progname:984: checking for non-GNU ld" >&5
+  fi
+
+  if test -z "$LD"; then
+    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    for ac_dir in $PATH; do
+      test -z "$ac_dir" && ac_dir=.
+      if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+       LD="$ac_dir/$ac_prog"
+       # Check to see if the program is GNU ld.  I'd rather use --version,
+       # but apparently some GNU ld's only accept -v.
+       # Break only if it was the GNU/non-GNU ld that we prefer.
+       if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+         test "$with_gnu_ld" != no && break
+       else
+         test "$with_gnu_ld" != yes && break
+       fi
+      fi
+    done
+    IFS="$ac_save_ifs"
+  fi
+
+  if test -n "$LD"; then
+    echo "$ac_t$LD" 1>&6
+  else
+    echo "$ac_t"no 1>&6
+  fi
+
+  if test -z "$LD"; then
+    echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+    exit 1
+  fi
+fi
+
+# Check to see if it really is or is not GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced.  Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+
+case "$host_os" in
+cygwin* | mingw*)
+  # FIXME: the MSVC++ port hasn't been tested in a loooong time
+  # When not using gcc, we currently assume that we are using
+  # Microsoft Visual C++.
+  if test "$with_gcc" != yes; then
+    with_gnu_ld=no
+  fi
+  ;;
+
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # If archive_cmds runs LD, not CC, wlarc should be empty
+  wlarc='${wl}'
+
+  # See if GNU ld supports shared libraries.
+  case "$host_os" in
+  aix3* | aix4*)
+    # On AIX, the GNU linker is very broken
+    ld_shlibs=no
+    cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+
+    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+    # that the semantics of dynamic libraries on AmigaOS, at least up
+    # to version 4, is to share data among multiple programs linked
+    # with the same dynamic library.  Since this doesn't match the
+    # behavior of shared libraries on other platforms, we can use
+    # them.
+    ld_shlibs=no
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  cygwin* | mingw*)
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec='-L$libdir'
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+
+    # Extract the symbol export list from an `--export-all' def file,
+    # then regenerate the def file from the symbol export list, so that
+    # the compiled dll only exports the symbol export list.
+    export_symbols_cmds='rm -f $objdir/$soname-ltdll.c~
+      sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+      (cd $objdir && $CC -c $soname-ltdll.c)~
+      $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def  $objdir/$soname-ltdll.$objext $libobjs~
+      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols'
+
+    archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
+      _lt_hint=1;
+      for symbol in `cat $export_symbols`; do
+       echo "  \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def;
+       _lt_hint=`expr 1 + \$_lt_hint`;
+      done~
+      $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+      $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+      $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
+
+      old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a'
+    ;;
+
+  netbsd*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
+      # can we support soname and/or expsyms with a.out? -oliva
+    fi
+    ;;
+
+  solaris*)
+    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+      ld_shlibs=no
+      cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;      
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
+    wlarc=
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+  esac
+
+  if test "$ld_shlibs" = yes; then
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    case $host_os in
+    cygwin* | mingw*)
+      # dlltool doesn't understand --whole-archive et. al.
+      whole_archive_flag_spec=
+      ;;
+    *)
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      ;;
+    esac
+  fi
+else
+  # PORTME fill in a description of your system's linker (not GNU ld)
+  case "$host_os" in
+  aix3*)
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+    archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
+    # Note: this linker hardcodes the directories in LIBPATH if there
+    # are no directories specified by -L.
+    hardcode_minus_L=yes
+    if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+      # Neither direct hardcoding nor static linking is supported with a
+      # broken collect2.
+      hardcode_direct=unsupported
+    fi
+    ;;
+
+  aix4*)
+    hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
+    hardcode_libdir_separator=':'
+    if test "$with_gcc" = yes; then
+      collect2name=`${CC} -print-prog-name=collect2`
+      if test -f "$collect2name" && \
+        strings "$collect2name" | grep resolve_lib_name >/dev/null
+      then
+       # We have reworked collect2
+       hardcode_direct=yes
+      else
+       # We have old collect2
+       hardcode_direct=unsupported
+       # It fails to find uninstalled libraries when the uninstalled
+       # path is not listed in the libpath.  Setting hardcode_minus_L
+       # to unsupported forces relinking
+       hardcode_minus_L=yes
+       hardcode_libdir_flag_spec='-L$libdir'
+       hardcode_libdir_separator=
+      fi
+      shared_flag='-shared'
+    else
+      shared_flag='${wl}-bM:SRE'
+      hardcode_direct=yes
+    fi
+    allow_undefined_flag=' ${wl}-berok'
+    archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
+    archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
+    case "$host_os" in aix4.[01]|aix4.[01].*)
+      # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
+      always_export_symbols=yes ;;
+    esac
+   ;;
+
+  amigaos*)
+    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    # see comment about different semantics on the GNU ld section
+    ld_shlibs=no
+    ;;
+
+  cygwin* | mingw*)
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec=' '
+    allow_undefined_flag=unsupported
+    # Tell ltmain to make .lib files, not .a files.
+    libext=lib
+    # FIXME: Setting linknames here is a bad hack.
+    archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+    # The linker will automatically build a .lib file if we build a DLL.
+    old_archive_from_new_cmds='true'
+    # FIXME: Should let the user specify the lib program.
+    old_archive_cmds='lib /OUT:$oldlib$oldobjs'
+    fix_srcfile_path='`cygpath -w $srcfile`'
+    ;;
+
+  freebsd1*)
+    ld_shlibs=no
+    ;;
+
+  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+  # support.  Future versions do this automatically, but an explicit c++rt0.o
+  # does not break anything, and helps significantly (at the cost of a little
+  # extra space).
+  freebsd2.2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+  freebsd2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+  freebsd*)
+    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    case "$host_os" in
+    hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
+    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
+    esac
+    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_direct=yes
+    hardcode_minus_L=yes # Not in the search PATH, but as the default
+                        # location of the library.
+    export_dynamic_flag_spec='${wl}-E'
+    ;;
+
+  irix5* | irix6*)
+    if test "$with_gcc" = yes; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+    else
+      archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'  # a.out
+    else
+      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts'      # ELF
+    fi
+    hardcode_libdir_flag_spec='${wl}-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  openbsd*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  os2*)
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    allow_undefined_flag=unsupported
+    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
+    old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+    ;;
+
+  osf3* | osf4*)
+    if test "$with_gcc" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  sco3.2v5*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    ;;
+
+  solaris*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_shlibpath_var=no
+    case "$host_os" in
+    solaris2.[0-5] | solaris2.[0-5].*) ;;
+    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+    esac
+    ;;
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    hardcode_direct=no #Motorola manual says yes, but my tests say they lie 
+    ;;  
+
+  sysv4.3*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_shlibpath_var=no
+    export_dynamic_flag_spec='-Bexport'
+    ;;
+
+  uts4*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  dgux*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4*MP*)
+    if test -d /usr/nec ;then
+    # archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs'
+    archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    ld_shlibs=yes
+    fi
+    ;;
+
+  *)
+    ld_shlibs=no
+    ;;
+  esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+if test -z "$NM"; then
+  echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+  case "$NM" in
+  [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
+  *)
+    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
+      test -z "$ac_dir" && ac_dir=.
+      if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+         NM="$ac_dir/nm -B"
+         break
+       elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+         NM="$ac_dir/nm -p"
+         break
+       else
+         NM=${NM="$ac_dir/nm"} # keep the first match, but
+         continue # so that we can try to find one that supports BSD flags
+       fi
+      fi
+    done
+    IFS="$ac_save_ifs"
+    test -z "$NM" && NM=nm
+    ;;
+  esac
+  echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+  ;;
+irix*)
+  symcode='[BCDEGRST]'
+  ;;
+solaris*)
+  symcode='[BDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+  global_symbol_pipe="sed -n -e 's/^.*[        ]\($symcode\)[  ][      ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+  $rm conftest*
+  cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  echo "$progname:1557: checking if global_symbol_pipe works" >&5
+  if { (eval echo $progname:1558: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { echo "$progname:1561: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
+
+         cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+         sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
+         cat <<\EOF >> conftest.c
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$objext conftstm.$objext
+         save_LIBS="$LIBS"
+         save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if { (eval echo $progname:1613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+           pipe_works=yes
+         else
+           echo "$progname: failed program was:" >&5
+           cat conftest.c >&5
+         fi
+         LIBS="$save_LIBS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  $rm conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    global_symbol_pipe=
+  fi
+done
+if test "$pipe_works" = yes; then
+  echo "${ac_t}ok" 1>&6
+else
+  echo "${ac_t}failed" 1>&6
+fi
+
+if test -z "$global_symbol_pipe"; then
+  global_symbol_to_cdecl=
+fi
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var"; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$hardcode_shlibpath_var" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+echo "$ac_t$hardcode_action" 1>&6
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linkers may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag" 1>&6
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+file_magic_cmd=
+file_magic_test_file=
+deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [regex]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}.so$major'
+  ;;
+
+aix4*)
+  version_type=linux
+  # AIX has no versioning support, so currently we can not hardcode correct
+  # soname into executable. Probably we can add versioning support to
+  # collect2, so additional links can be useful in future.
+  # We preserve .a as extension for shared libraries though AIX4.2
+  # and later linker supports .so
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
+  shlibpath_var=LIBPATH
+  deplibs_check_method=pass_all
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}.so'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  deplibs_check_method=pass_all
+  lt_cv_dlopen="load_add_on"
+  lt_cv_dlopen_libs=
+  lt_cv_dlopen_self=yes
+  ;;
+
+bsdi4*)
+  version_type=linux
+  library_names_spec='${libname}.so$major ${libname}.so'
+  soname_spec='${libname}.so'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  deplibs_check_method='file_magic ELF 32-bit LSB shared object'
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=/shlib/libc.so
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw*)
+  version_type=windows
+  if test "$with_gcc" = yes; then
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
+  else
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+  fi
+  dynamic_linker='Win32 ld.exe'
+  deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  file_magic_cmd='${OBJDUMP} -f'
+  need_lib_prefix=no
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  lt_cv_dlopen="LoadLibrary"
+  lt_cv_dlopen_libs=
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+  
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case "$version_type" in
+    freebsd-elf*)
+      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+      file_magic_cmd=/usr/bin/file
+      file_magic_test_file=`echo /usr/lib/libc.so*`
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      deplibs_check_method=unknown
+      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+      need_version=yes
+      ;;
+  esac
+  finish_cmds='PATH="\$PATH:/sbin" OBJFORMAT="'"$objformat"'" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+gnu*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  dynamic_linker="$host_os dld.sl"
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  shlibpath_var=SHLIB_PATH
+  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+  soname_spec='${libname}${release}.sl$major'
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6*)
+  version_type=irix
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}.so.$major'
+  library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
+  case "$host_os" in
+  irix5*)
+    libsuff= shlibsuff=
+    # this will be overridden with pass_all, but let us keep it just in case
+    deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case "$LD" in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    # this will be overridden with pass_all, but let us keep it just in case
+    deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  deplibs_check_method='pass_all'
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+
+  if test -f /lib/ld.so.1; then
+    dynamic_linker='GNU ld.so'
+  else
+    # Only the GNU ld.so supports shared libraries on MkLinux.
+    case "$host_cpu" in
+    powerpc*) dynamic_linker=no ;;
+    *) dynamic_linker='Linux ld.so' ;;
+    esac
+  fi
+  ;;
+
+netbsd*)
+  version_type=sunos
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+    soname_spec='${libname}${release}.so$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+openbsd*)
+  version_type=sunos
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+    need_version=no
+  fi
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+os2*)
+  libname_spec='$name'
+  need_lib_prefix=no
+  library_names_spec='$libname.dll $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4*)
+  version_type=osf
+  need_version=no
+  soname_spec='${libname}${release}.so'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  # this will be overridden with pass_all, but let us keep it just in case
+  deplibs_check_method='file_magic COFF format alpha shared library'
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=/shlib/libc.so
+  deplibs_check_method='pass_all'
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=/lib/libc.so
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case "$host_vendor" in
+    ncr)
+      deplibs_check_method='pass_all'
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+      file_magic_cmd=/usr/bin/file
+      file_magic_test_file=`echo /usr/lib/libc.so*`
+      ;;
+  esac
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+    soname_spec='$libname.so.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+echo "$ac_t$dynamic_linker" 1>&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
+# configure.in, otherwise build static only libraries.
+case "$host_os" in
+cygwin* | mingw* | os2*)
+  if test x$can_build_shared = xyes; then
+    test x$enable_win32_dll = xno && can_build_shared=no
+    echo "checking if package supports dlls... $can_build_shared" 1>&6
+  fi
+;;
+esac
+
+if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
+  case "$deplibs_check_method" in
+  "file_magic "*)
+    file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+    if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+       egrep "$file_magic_regex" > /dev/null; then
+      :
+    else
+      cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+    fi ;;
+  esac
+fi
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  test "$enable_shared" = yes && enable_static=no
+  ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
+  lt_cv_dlopen=no lt_cv_dlopen_libs=
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "$progname:2123: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2131 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo $progname:2141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+echo "$progname:2160: checking for dlopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2165 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+dlopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_dlopen=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_dlopen=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
+echo "$progname:2204: checking for dld_link in -ldld" >&5
+ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2212 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dld_link();
+
+int main() {
+dld_link()
+; return 0; }
+EOF
+if { (eval echo $progname:2222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+echo "$progname:2241: checking for shl_load" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2246 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char shl_load();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+shl_load();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_shl_load=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_shl_load=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="shl_load"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+echo "$progname:2286: checking for shl_load in -ldld" >&5
+ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2294 "ltconfig"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char shl_load();
+
+int main() {
+shl_load()
+; return 0; }
+EOF
+if { (eval echo $progname:2305: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+fi
+
+    
+fi
+
+  
+fi
+
+
+fi
+
+fi
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  fi
+
+  case "$lt_cv_dlopen" in
+  dlopen)
+for ac_hdr in dlfcn.h; do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "$progname:2348: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2353 "ltconfig"
+#include <$ac_hdr>
+int fnord = 0;
+EOF
+ac_try="$ac_compile conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo $progname:2358: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+    if test "x$ac_cv_header_dlfcn_h" = xyes; then
+      CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+    fi
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+  echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2386: checking whether a program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self+set}" = set; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    lt_cv_dlopen_self=cross
+  else
+    cat > conftest.c <<EOF
+#line 2394 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL   RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+#  define LTDL_GLOBAL  DL_GLOBAL
+# else
+#  define LTDL_GLOBAL  0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
+# else
+#  ifdef DL_LAZY
+#   define LTDL_LAZY_OR_NOW    DL_LAZY
+#  else
+#   ifdef RTLD_NOW
+#    define LTDL_LAZY_OR_NOW   RTLD_NOW
+#   else
+#    ifdef DL_NOW
+#     define LTDL_LAZY_OR_NOW  DL_NOW
+#    else
+#     define LTDL_LAZY_OR_NOW  0
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+              if(ptr1 || ptr2) exit(0); } exit(1); } 
+
+EOF
+if { (eval echo $progname:2440: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+  lt_cv_dlopen_self=yes
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  lt_cv_dlopen_self=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self" 1>&6
+
+  if test "$lt_cv_dlopen_self" = yes; then
+    LDFLAGS="$LDFLAGS $link_static_flag"
+  echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2459: checking whether a statically linked program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    lt_cv_dlopen_self_static=cross
+  else
+    cat > conftest.c <<EOF
+#line 2467 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL   RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+#  define LTDL_GLOBAL  DL_GLOBAL
+# else
+#  define LTDL_GLOBAL  0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
+# else
+#  ifdef DL_LAZY
+#   define LTDL_LAZY_OR_NOW    DL_LAZY
+#  else
+#   ifdef RTLD_NOW
+#    define LTDL_LAZY_OR_NOW   RTLD_NOW
+#   else
+#    ifdef DL_NOW
+#     define LTDL_LAZY_OR_NOW  DL_NOW
+#    else
+#     define LTDL_LAZY_OR_NOW  0
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+    if(ptr1 || ptr2) exit(0); } exit(1); } 
+
+EOF
+if { (eval echo $progname:2513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+  lt_cv_dlopen_self_static=yes
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  lt_cv_dlopen_self_static=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
+fi
+    ;;
+  esac
+
+  case "$lt_cv_dlopen_self" in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case "$lt_cv_dlopen_self_static" in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+# Copy echo and quote the copy, instead of the original, because it is
+# used later.
+ltecho="$echo"
+if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   ltecho="$CONFIG_SHELL \$0 --fallback-echo"
+fi
+LTSHELL="$SHELL"
+
+LTCONFIG_VERSION="$VERSION"
+
+# Only quote variables if we're using ltmain.sh.
+case "$ltmain" in
+*.sh)
+  # Now quote all the things that may contain metacharacters.
+  for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
+    old_LD old_LDFLAGS old_LIBS \
+    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
+    AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
+    reload_flag reload_cmds wl \
+    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+    library_names_spec soname_spec \
+    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
+    file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
+    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+    case "$var" in
+    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case "$ltecho" in
+  *'\$0 --fallback-echo"')
+    ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+  trap "$rm \"$ofile\"; exit 1" 1 2 15
+  echo "creating $ofile"
+  $rm "$ofile"
+  cat <<EOF > "$ofile"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
+
+### BEGIN LIBTOOL CONFIG
+EOF
+  cfgfile="$ofile"
+  ;;
+
+*)
+  # Double-quote the variables that need it (for aesthetics).
+  for var in old_CC old_CFLAGS old_CPPFLAGS \
+    old_LD old_LDFLAGS old_LIBS \
+    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
+    eval "$var=\\\"\$var\\\""
+  done
+
+  # Just create a config file.
+  cfgfile="$ofile.cfg"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  echo "creating $cfgfile"
+  $rm "$cfgfile"
+  cat <<EOF > "$cfgfile"
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+EOF
+  ;;
+esac
+
+cat <<EOF >> "$cfgfile"
+# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
+# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
+# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
+# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
+#   $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION=$LTCONFIG_VERSION
+
+# Shell to use when invoking shell scripts.
+SHELL=$LTSHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$ltecho
+
+# The archiver.
+AR=$AR
+
+# The default C compiler.
+CC=$CC
+
+# The linker used to build libraries.
+LD=$LD
+
+# Whether we need hard or soft links.
+LN_S=$LN_S
+
+# A BSD-compatible nm program.
+NM=$NM
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$reload_flag
+reload_cmds=$reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$wl
+
+# Object file suffix (normally "o").
+objext="$objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$pic_flag
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$RANLIB
+old_archive_cmds=$old_archive_cmds
+old_postinstall_cmds=$old_postinstall_cmds
+old_postuninstall_cmds=$old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$old_archive_from_new_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$archive_cmds
+archive_expsym_cmds=$archive_expsym_cmds
+postinstall_cmds=$postinstall_cmds
+postuninstall_cmds=$postuninstall_cmds
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$global_symbol_to_cdecl
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$include_expsyms
+
+EOF
+
+case "$ltmain" in
+*.sh)
+  echo '### END LIBTOOL CONFIG' >> "$ofile"
+  echo >> "$ofile"
+  case "$host_os" in
+  aix3*)
+    cat <<\EOF >> "$ofile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "${COLLECT_NAMES+set}" != set; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # Append the ltmain.sh script.
+  cat "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
+
+  chmod +x "$ofile"
+  ;;
+
+*)
+  # Compile the libtool program.
+  echo "FIXME: would compile $ltmain"
+  ;;
+esac
+
+test -n "$cache_file" || exit 0
+
+# AC_CACHE_SAVE
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/dist/nvi/dist/ltmain.sh b/dist/nvi/dist/ltmain.sh
new file mode 100644 (file)
index 0000000..4598ec6
--- /dev/null
@@ -0,0 +1,6930 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007  Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.24
+TIMESTAMP=" (1.1220.2.455 2007/06/24 02:13:29)"
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell, and then maybe $echo will work.
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  SP2NL='tr \040 \012'
+  NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  SP2NL='tr \100 \n'
+  NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+         save_$lt_var=\$$lt_var
+         $lt_var=C
+         export $lt_var
+       fi"
+done
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS="  $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+  $echo "$modename: not configured to build any kind of library" 1>&2
+  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+       # Failing that, at least try and use $RANDOM to avoid a race
+       my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+       save_mktempdir_umask=`umask`
+       umask 0077
+       $mkdir "$my_tmpdir"
+       umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || {
+        $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+       exit $EXIT_FAILURE
+      }
+    fi
+
+    $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+      $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 | \
+       $SED -n -e '1,100{
+               / I /{
+                       s,.*,import,
+                       p
+                       q
+                       }
+               }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+       case $arg in
+         *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       CC_quoted="$CC_quoted $arg"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+       for z in $available_tags; do
+         if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+           # Evaluate the configuration.
+           eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+           CC_quoted=
+           for arg in $CC; do
+           # Double-quote args containing other shell metacharacters.
+           case $arg in
+             *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \     ]*|*]*|"")
+             arg="\"$arg\""
+             ;;
+           esac
+           CC_quoted="$CC_quoted $arg"
+         done
+           case "$@ " in
+             " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+             # The compiler in the base compile command matches
+             # the one in the tagged configuration.
+             # Assume this is the tagged configuration we want.
+             tagname=$z
+             break
+             ;;
+           esac
+         fi
+       done
+       # If $tagname still isn't set, then no tagged configuration
+       # was found and let the user know that the "--tag" command
+       # line option must be used.
+       if test -z "$tagname"; then
+         $echo "$modename: unable to infer tagged configuration"
+         $echo "$modename: specify a tag with \`--tag'" 1>&2
+         exit $EXIT_FAILURE
+#        else
+#          $echo "$modename: using $tagname tagged configuration"
+       fi
+       ;;
+      esac
+    fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+
+    $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+    $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+      exit $EXIT_FAILURE
+    fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+    my_status=""
+
+    $show "${rm}r $my_gentop"
+    $run ${rm}r "$my_gentop"
+    $show "$mkdir $my_gentop"
+    $run $mkdir "$my_gentop"
+    my_status=$?
+    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+      exit $my_status
+    fi
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+       [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+       *) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+       *" $my_xlib_u "*)
+         extracted_serial=`expr $extracted_serial + 1`
+         my_xlib_u=lt$extracted_serial-$my_xlib ;;
+       *) break ;;
+       esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      $show "${rm}r $my_xdir"
+      $run ${rm}r "$my_xdir"
+      $show "$mkdir $my_xdir"
+      $run $mkdir "$my_xdir"
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+       exit $exit_status
+      fi
+      case $host in
+      *-darwin*)
+       $show "Extracting $my_xabs"
+       # Do not bother doing anything if just a dry run
+       if test -z "$run"; then
+         darwin_orig_dir=`pwd`
+         cd $my_xdir || exit $?
+         darwin_archive=$my_xabs
+         darwin_curdir=`pwd`
+         darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+         darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+         if test -n "$darwin_arches"; then 
+           darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+           darwin_arch=
+           $show "$darwin_base_archive has multiple architectures $darwin_arches"
+           for darwin_arch in  $darwin_arches ; do
+             mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+             cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+             cd "$darwin_curdir"
+             $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+           done # $darwin_arches
+      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+           darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+           darwin_file=
+           darwin_files=
+           for darwin_file in $darwin_filelist; do
+             darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+             lipo -create -output "$darwin_file" $darwin_files
+           done # $darwin_filelist
+           ${rm}r unfat-$$
+           cd "$darwin_orig_dir"
+         else
+           cd "$darwin_orig_dir"
+           func_extract_an_archive "$my_xdir" "$my_xabs"
+         fi # $darwin_arches
+       fi # $run
+       ;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+        ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+    func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+  arg="$1"
+  shift
+
+  case $arg in
+  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    case $prev in
+    execute_dlfiles)
+      execute_dlfiles="$execute_dlfiles $arg"
+      ;;
+    tag)
+      tagname="$arg"
+      preserve_args="${preserve_args}=$arg"
+
+      # Check whether tagname contains only valid characters
+      case $tagname in
+      *[!-_A-Za-z0-9,/]*)
+       $echo "$progname: invalid tag name: $tagname" 1>&2
+       exit $EXIT_FAILURE
+       ;;
+      esac
+
+      case $tagname in
+      CC)
+       # Don't test for the "default" C tag, as we know, it's there, but
+       # not specially marked.
+       ;;
+      *)
+       if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+         taglist="$taglist $tagname"
+         # Evaluate the configuration.
+         eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+       else
+         $echo "$progname: ignoring unknown tag $tagname" 1>&2
+       fi
+       ;;
+      esac
+      ;;
+    *)
+      eval "$prev=\$arg"
+      ;;
+    esac
+
+    prev=
+    prevopt=
+    continue
+  fi
+
+  # Have we seen a non-optional argument yet?
+  case $arg in
+  --help)
+    show_help=yes
+    ;;
+
+  --version)
+    echo "\
+$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP
+
+Copyright (C) 2007  Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+    exit $?
+    ;;
+
+  --config)
+    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+    done
+    exit $?
+    ;;
+
+  --debug)
+    $echo "$progname: enabling shell trace mode"
+    set -x
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --dry-run | -n)
+    run=:
+    ;;
+
+  --features)
+    $echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $echo "enable shared libraries"
+    else
+      $echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $echo "enable static libraries"
+    else
+      $echo "disable static libraries"
+    fi
+    exit $?
+    ;;
+
+  --finish) mode="finish" ;;
+
+  --mode) prevopt="--mode" prev=mode ;;
+  --mode=*) mode="$optarg" ;;
+
+  --preserve-dup-deps) duplicate_deps="yes" ;;
+
+  --quiet | --silent)
+    show=:
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --tag)
+    prevopt="--tag"
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
+  --tag=*)
+    set tag "$optarg" ${1+"$@"}
+    shift
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
+
+  -dlopen)
+    prevopt="-dlopen"
+    prev=execute_dlfiles
+    ;;
+
+  -*)
+    $echo "$modename: unrecognized option \`$arg'" 1>&2
+    $echo "$help" 1>&2
+    exit $EXIT_FAILURE
+    ;;
+
+  *)
+    nonopt="$arg"
+    break
+    ;;
+  esac
+done
+
+if test -n "$prevopt"; then
+  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+  $echo "$help" 1>&2
+  exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no) 
+  ;;
+shared)
+  build_libtool_libs=no
+  build_old_libs=yes
+  ;;
+static)
+  build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+  ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+  # Infer the operation mode.
+  if test -z "$mode"; then
+    $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+    $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+    case $nonopt in
+    *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+      mode=link
+      for arg
+      do
+       case $arg in
+       -c)
+          mode=compile
+          break
+          ;;
+       esac
+      done
+      ;;
+    *db | *dbx | *strace | *truss)
+      mode=execute
+      ;;
+    *install*|cp|mv)
+      mode=install
+      ;;
+    *rm)
+      mode=uninstall
+      ;;
+    *)
+      # If we have no mode, but dlfiles were specified, then do execute mode.
+      test -n "$execute_dlfiles" && mode=execute
+
+      # Just use the default operation mode.
+      if test -z "$mode"; then
+       if test -n "$nonopt"; then
+         $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+       else
+         $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+       fi
+      fi
+      ;;
+    esac
+  fi
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+    $echo "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$modename --help --mode=$mode' for more information."
+
+  # These modes are in order of execution frequency so that they run quickly.
+  case $mode in
+  # libtool compile mode
+  compile)
+    modename="$modename: compile"
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+       # do not "continue".  Instead, add this to base_compile
+       lastarg="$arg"
+       arg_mode=normal
+       ;;
+
+      target )
+       libobj="$arg"
+       arg_mode=normal
+       continue
+       ;;
+
+      normal )
+       # Accept any command-line options.
+       case $arg in
+       -o)
+         if test -n "$libobj" ; then
+           $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         arg_mode=target
+         continue
+         ;;
+
+       -static | -prefer-pic | -prefer-non-pic)
+         later="$later $arg"
+         continue
+         ;;
+
+       -no-suppress)
+         suppress_opt=no
+         continue
+         ;;
+
+       -Xcompiler)
+         arg_mode=arg  #  the next one goes into the "base_compile" arg list
+         continue      #  The current "srcfile" will either be retained or
+         ;;            #  replaced later.  I would guess that would be a bug.
+
+       -Wc,*)
+         args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+         lastarg=
+         save_ifs="$IFS"; IFS=','
+         for arg in $args; do
+           IFS="$save_ifs"
+
+           # Double-quote args containing other shell metacharacters.
+           # Many Bourne shells cannot handle close brackets correctly
+           # in scan sets, so we specify it separately.
+           case $arg in
+             *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \     ]*|*]*|"")
+             arg="\"$arg\""
+             ;;
+           esac
+           lastarg="$lastarg $arg"
+         done
+         IFS="$save_ifs"
+         lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+         # Add the arguments to base_compile.
+         base_compile="$base_compile $lastarg"
+         continue
+         ;;
+
+       * )
+         # Accept the current argument as the source file.
+         # The previous "srcfile" becomes the current argument.
+         #
+         lastarg="$srcfile"
+         srcfile="$arg"
+         ;;
+       esac  #  case $arg
+       ;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+      case $lastarg in
+      # Double-quote args containing other shell metacharacters.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, and some SunOS ksh mistreat backslash-escaping
+      # in scan sets (worked around with variable expansion),
+      # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
+      # at all, so we specify them separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       lastarg="\"$lastarg\""
+       ;;
+      esac
+
+      base_compile="$base_compile $lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      $echo "$modename: you must specify an argument for -Xcompile"
+      exit $EXIT_FAILURE
+      ;;
+    target)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    *)
+      # Get the name of the library object.
+      [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    xform='[cCFSifmso]'
+    case $libobj in
+    *.ada) xform=ada ;;
+    *.adb) xform=adb ;;
+    *.ads) xform=ads ;;
+    *.asm) xform=asm ;;
+    *.c++) xform=c++ ;;
+    *.cc) xform=cc ;;
+    *.ii) xform=ii ;;
+    *.class) xform=class ;;
+    *.cpp) xform=cpp ;;
+    *.cxx) xform=cxx ;;
+    *.[fF][09]?) xform=[fF][09]. ;;
+    *.for) xform=for ;;
+    *.java) xform=java ;;
+    *.obj) xform=obj ;;
+    esac
+
+    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+    case $libobj in
+    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+    *)
+      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -static)
+       build_old_libs=yes
+       continue
+       ;;
+
+      -prefer-pic)
+       pic_mode=yes
+       continue
+       ;;
+
+      -prefer-non-pic)
+       pic_mode=no
+       continue
+       ;;
+      esac
+    done
+
+    qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+    case $qlibobj in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       qlibobj="\"$qlibobj\"" ;;
+    esac
+    test "X$libobj" != "X$qlibobj" \
+       && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"'  &()|`$[]' \
+       && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+    objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+    xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$xdir" = "X$obj"; then
+      xdir=
+    else
+      xdir=$xdir/
+    fi
+    lobj=${xdir}$objdir/$objname
+
+    if test -z "$base_compile"; then
+      $echo "$modename: you must specify a compilation command" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    $run $rm $removelist
+    trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+      removelist="$removelist $output_obj $lockfile"
+      trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+       $show "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+       $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+      $echo "$srcfile" > "$lockfile"
+    fi
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+    qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+    case $qsrcfile in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+      qsrcfile="\"$qsrcfile\"" ;;
+    esac
+
+    $run $rm "$libobj" "${libobj}T"
+
+    # Create a libtool object file (analogous to a ".la" file),
+    # but don't create it if we're doing a dry run.
+    test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+       command="$base_compile $qsrcfile $pic_flag"
+      else
+       # Don't build PIC code
+       command="$base_compile $qsrcfile"
+      fi
+
+      if test ! -d "${xdir}$objdir"; then
+       $show "$mkdir ${xdir}$objdir"
+       $run $mkdir ${xdir}$objdir
+       exit_status=$?
+       if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+         exit $exit_status
+       fi
+      fi
+
+      if test -z "$output_obj"; then
+       # Place PIC objects in $objdir
+       command="$command -o $lobj"
+      fi
+
+      $run $rm "$lobj" "$output_obj"
+
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       test -n "$output_obj" && $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+       $show "$mv $output_obj $lobj"
+       if $run $mv $output_obj $lobj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Append the name of the PIC object to the libtool object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+        suppress_output=' >/dev/null 2>&1'
+      fi
+    else
+      # No PIC object so indicate it doesn't exist in the libtool
+      # object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+       # Don't build PIC code
+       command="$base_compile $qsrcfile"
+      else
+       command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+       command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      $run $rm "$obj" "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+       $show "$mv $output_obj $obj"
+       if $run $mv $output_obj $obj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+    else
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+    fi
+
+    $run $mv "${libobj}T" "${libobj}"
+
+    # Unlock the critical section if it was locked
+    if test "$need_locks" != no; then
+      $run $rm "$lockfile"
+    fi
+
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool link mode
+  link | relink)
+    modename="$modename: link"
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args="$nonopt"
+    base_compile="$nonopt $@"
+    compile_command="$nonopt"
+    finalize_command="$nonopt"
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    notinst_path= # paths that contain not-installed libtool libraries
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -all-static | -static | -static-libtool-libs)
+       case $arg in
+       -all-static)
+         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+           $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+         fi
+         if test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       -static)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=built
+         ;;
+       -static-libtool-libs)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       esac
+       build_libtool_libs=no
+       build_old_libs=yes
+       break
+       ;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+       ;;
+      *) qarg=$arg ;;
+      esac
+      libtool_args="$libtool_args $qarg"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+       case $prev in
+       output)
+         compile_command="$compile_command @OUTPUT@"
+         finalize_command="$finalize_command @OUTPUT@"
+         ;;
+       esac
+
+       case $prev in
+       dlfiles|dlprefiles)
+         if test "$preload" = no; then
+           # Add the symbol object into the linking commands.
+           compile_command="$compile_command @SYMFILE@"
+           finalize_command="$finalize_command @SYMFILE@"
+           preload=yes
+         fi
+         case $arg in
+         *.la | *.lo) ;;  # We handle these cases below.
+         force)
+           if test "$dlself" = no; then
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         self)
+           if test "$prev" = dlprefiles; then
+             dlself=yes
+           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+             dlself=yes
+           else
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         *)
+           if test "$prev" = dlfiles; then
+             dlfiles="$dlfiles $arg"
+           else
+             dlprefiles="$dlprefiles $arg"
+           fi
+           prev=
+           continue
+           ;;
+         esac
+         ;;
+       expsyms)
+         export_symbols="$arg"
+         if test ! -f "$arg"; then
+           $echo "$modename: symbol file \`$arg' does not exist"
+           exit $EXIT_FAILURE
+         fi
+         prev=
+         continue
+         ;;
+       expsyms_regex)
+         export_symbols_regex="$arg"
+         prev=
+         continue
+         ;;
+       inst_prefix)
+         inst_prefix_dir="$arg"
+         prev=
+         continue
+         ;;
+       precious_regex)
+         precious_files_regex="$arg"
+         prev=
+         continue
+         ;;
+       release)
+         release="-$arg"
+         prev=
+         continue
+         ;;
+       objectlist)
+         if test -f "$arg"; then
+           save_arg=$arg
+           moreargs=
+           for fil in `cat $save_arg`
+           do
+#            moreargs="$moreargs $fil"
+             arg=$fil
+             # A libtool-controlled object.
+
+             # Check to see that this really is a libtool object.
+             if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+               pic_object=
+               non_pic_object=
+
+               # Read the .lo file
+               # If there is no directory component, then add one.
+               case $arg in
+               */* | *\\*) . $arg ;;
+               *) . ./$arg ;;
+               esac
+
+               if test -z "$pic_object" || \
+                  test -z "$non_pic_object" ||
+                  test "$pic_object" = none && \
+                  test "$non_pic_object" = none; then
+                 $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+                 exit $EXIT_FAILURE
+               fi
+
+               # Extract subdirectory from the argument.
+               xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+               if test "X$xdir" = "X$arg"; then
+                 xdir=
+               else
+                 xdir="$xdir/"
+               fi
+
+               if test "$pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 pic_object="$xdir$pic_object"
+
+                 if test "$prev" = dlfiles; then
+                   if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+                     dlfiles="$dlfiles $pic_object"
+                     prev=
+                     continue
+                   else
+                     # If libtool objects are unsupported, then we need to preload.
+                     prev=dlprefiles
+                   fi
+                 fi
+
+                 # CHECK ME:  I think I busted this.  -Ossama
+                 if test "$prev" = dlprefiles; then
+                   # Preload the old-style object.
+                   dlprefiles="$dlprefiles $pic_object"
+                   prev=
+                 fi
+
+                 # A PIC object.
+                 libobjs="$libobjs $pic_object"
+                 arg="$pic_object"
+               fi
+
+               # Non-PIC object.
+               if test "$non_pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 non_pic_object="$xdir$non_pic_object"
+
+                 # A standard non-PIC object
+                 non_pic_objects="$non_pic_objects $non_pic_object"
+                 if test -z "$pic_object" || test "$pic_object" = none ; then
+                   arg="$non_pic_object"
+                 fi
+               else
+                 # If the PIC object exists, use it instead.
+                 # $xdir was prepended to $pic_object above.
+                 non_pic_object="$pic_object"
+                 non_pic_objects="$non_pic_objects $non_pic_object"
+               fi
+             else
+               # Only an error if not doing a dry-run.
+               if test -z "$run"; then
+                 $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+                 exit $EXIT_FAILURE
+               else
+                 # Dry-run case.
+
+                 # Extract subdirectory from the argument.
+                 xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+                 if test "X$xdir" = "X$arg"; then
+                   xdir=
+                 else
+                   xdir="$xdir/"
+                 fi
+
+                 pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+                 non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+                 libobjs="$libobjs $pic_object"
+                 non_pic_objects="$non_pic_objects $non_pic_object"
+               fi
+             fi
+           done
+         else
+           $echo "$modename: link input file \`$save_arg' does not exist"
+           exit $EXIT_FAILURE
+         fi
+         arg=$save_arg
+         prev=
+         continue
+         ;;
+       rpath | xrpath)
+         # We need an absolute path.
+         case $arg in
+         [\\/]* | [A-Za-z]:[\\/]*) ;;
+         *)
+           $echo "$modename: only absolute run-paths are allowed" 1>&2
+           exit $EXIT_FAILURE
+           ;;
+         esac
+         if test "$prev" = rpath; then
+           case "$rpath " in
+           *" $arg "*) ;;
+           *) rpath="$rpath $arg" ;;
+           esac
+         else
+           case "$xrpath " in
+           *" $arg "*) ;;
+           *) xrpath="$xrpath $arg" ;;
+           esac
+         fi
+         prev=
+         continue
+         ;;
+       xcompiler)
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         compile_command="$compile_command $qarg"
+         finalize_command="$finalize_command $qarg"
+         continue
+         ;;
+       xlinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $wl$qarg"
+         prev=
+         compile_command="$compile_command $wl$qarg"
+         finalize_command="$finalize_command $wl$qarg"
+         continue
+         ;;
+       xcclinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         compile_command="$compile_command $qarg"
+         finalize_command="$finalize_command $qarg"
+         continue
+         ;;
+       shrext)
+         shrext_cmds="$arg"
+         prev=
+         continue
+         ;;
+       darwin_framework|darwin_framework_skip)
+         test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
+         prev=
+         continue
+         ;;
+       *)
+         eval "$prev=\"\$arg\""
+         prev=
+         continue
+         ;;
+       esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+       if test -n "$link_static_flag"; then
+         compile_command="$compile_command $link_static_flag"
+         finalize_command="$finalize_command $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -allow-undefined)
+       # FIXME: remove this flag sometime in the future.
+       $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+       continue
+       ;;
+
+      -avoid-version)
+       avoid_version=yes
+       continue
+       ;;
+
+      -dlopen)
+       prev=dlfiles
+       continue
+       ;;
+
+      -dlpreopen)
+       prev=dlprefiles
+       continue
+       ;;
+
+      -export-dynamic)
+       export_dynamic=yes
+       continue
+       ;;
+
+      -export-symbols | -export-symbols-regex)
+       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+         $echo "$modename: more than one -exported-symbols argument is not allowed"
+         exit $EXIT_FAILURE
+       fi
+       if test "X$arg" = "X-export-symbols"; then
+         prev=expsyms
+       else
+         prev=expsyms_regex
+       fi
+       continue
+       ;;
+
+      -framework|-arch|-isysroot)
+       case " $CC " in
+         *" ${arg} ${1} "* | *" ${arg} ${1} "*) 
+               prev=darwin_framework_skip ;;
+         *) compiler_flags="$compiler_flags $arg"
+            prev=darwin_framework ;;
+       esac
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+       continue
+       ;;
+
+      -inst-prefix-dir)
+       prev=inst_prefix
+       continue
+       ;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+       case $with_gcc/$host in
+       no/*-*-irix* | /*-*-irix*)
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
+         ;;
+       esac
+       continue
+       ;;
+
+      -L*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         absdir=`cd "$dir" && pwd`
+         if test -z "$absdir"; then
+           $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+           absdir="$dir"
+           notinst_path="$notinst_path $dir"
+         fi
+         dir="$absdir"
+         ;;
+       esac
+       case "$deplibs " in
+       *" -L$dir "*) ;;
+       *)
+         deplibs="$deplibs -L$dir"
+         lib_search_path="$lib_search_path $dir"
+         ;;
+       esac
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$dir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$dir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
+         ;;
+       esac
+       continue
+       ;;
+
+      -l*)
+       if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+           # These systems don't actually have a C or math library (as such)
+           continue
+           ;;
+         *-*-os2*)
+           # These systems don't actually have a C library (as such)
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C and math libraries are in the System framework
+           deplibs="$deplibs -framework System"
+           continue
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           test "X$arg" = "X-lc" && continue
+           ;;
+         esac
+       elif test "X$arg" = "X-lc_r"; then
+        case $host in
+        *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+          # Do not include libc_r directly, use -pthread flag.
+          continue
+          ;;
+        esac
+       fi
+       deplibs="$deplibs $arg"
+       continue
+       ;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      -model)
+       compile_command="$compile_command $arg"
+       compiler_flags="$compiler_flags $arg"
+       finalize_command="$finalize_command $arg"
+       prev=xcompiler
+       continue
+       ;;
+
+     -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+       compiler_flags="$compiler_flags $arg"
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+       continue
+       ;;
+
+      -module)
+       module=yes
+       continue
+       ;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m* pass through architecture-specific compiler args for GCC
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+        compile_command="$compile_command $arg"
+        finalize_command="$finalize_command $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      -shrext)
+       prev=shrext
+       continue
+       ;;
+
+      -no-fast-install)
+       fast_install=no
+       continue
+       ;;
+
+      -no-install)
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*)
+         # The PATH hackery in wrapper scripts is required on Windows
+         # and Darwin in order for the loader to find any dlls it needs.
+         $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+         $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+         fast_install=no
+         ;;
+       *) no_install=yes ;;
+       esac
+       continue
+       ;;
+
+      -no-undefined)
+       allow_undefined=no
+       continue
+       ;;
+
+      -objectlist)
+       prev=objectlist
+       continue
+       ;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+       prev=precious_regex
+       continue
+       ;;
+
+      -release)
+       prev=release
+       continue
+       ;;
+
+      -rpath)
+       prev=rpath
+       continue
+       ;;
+
+      -R)
+       prev=xrpath
+       continue
+       ;;
+
+      -R*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         $echo "$modename: only absolute run-paths are allowed" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+       case "$xrpath " in
+       *" $dir "*) ;;
+       *) xrpath="$xrpath $dir" ;;
+       esac
+       continue
+       ;;
+
+      -static | -static-libtool-libs)
+       # The effects of -static are defined in a previous loop.
+       # We used to do the same as -all-static on platforms that
+       # didn't have a PIC flag, but the assumption that the effects
+       # would be equivalent was wrong.  It would break on at least
+       # Digital Unix and AIX.
+       continue
+       ;;
+
+      -thread-safe)
+       thread_safe=yes
+       continue
+       ;;
+
+      -version-info)
+       prev=vinfo
+       continue
+       ;;
+      -version-number)
+       prev=vinfo
+       vinfo_number=yes
+       continue
+       ;;
+
+      -Wc,*)
+       args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+         case $flag in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           flag="\"$flag\""
+           ;;
+         esac
+         arg="$arg $wl$flag"
+         compiler_flags="$compiler_flags $flag"
+       done
+       IFS="$save_ifs"
+       arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+       ;;
+
+      -Wl,*)
+       args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+         case $flag in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           flag="\"$flag\""
+           ;;
+         esac
+         arg="$arg $wl$flag"
+         compiler_flags="$compiler_flags $wl$flag"
+         linker_flags="$linker_flags $flag"
+       done
+       IFS="$save_ifs"
+       arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+       ;;
+
+      -Xcompiler)
+       prev=xcompiler
+       continue
+       ;;
+
+      -Xlinker)
+       prev=xlinker
+       continue
+       ;;
+
+      -XCClinker)
+       prev=xcclinker
+       continue
+       ;;
+
+      # Some other compiler flag.
+      -* | +*)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+
+      *.$objext)
+       # A standard object.
+       objs="$objs $arg"
+       ;;
+
+      *.lo)
+       # A libtool-controlled object.
+
+       # Check to see that this really is a libtool object.
+       if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         pic_object=
+         non_pic_object=
+
+         # Read the .lo file
+         # If there is no directory component, then add one.
+         case $arg in
+         */* | *\\*) . $arg ;;
+         *) . ./$arg ;;
+         esac
+
+         if test -z "$pic_object" || \
+            test -z "$non_pic_object" ||
+            test "$pic_object" = none && \
+            test "$non_pic_object" = none; then
+           $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+
+         # Extract subdirectory from the argument.
+         xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+         if test "X$xdir" = "X$arg"; then
+           xdir=
+         else
+           xdir="$xdir/"
+         fi
+
+         if test "$pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           pic_object="$xdir$pic_object"
+
+           if test "$prev" = dlfiles; then
+             if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+               dlfiles="$dlfiles $pic_object"
+               prev=
+               continue
+             else
+               # If libtool objects are unsupported, then we need to preload.
+               prev=dlprefiles
+             fi
+           fi
+
+           # CHECK ME:  I think I busted this.  -Ossama
+           if test "$prev" = dlprefiles; then
+             # Preload the old-style object.
+             dlprefiles="$dlprefiles $pic_object"
+             prev=
+           fi
+
+           # A PIC object.
+           libobjs="$libobjs $pic_object"
+           arg="$pic_object"
+         fi
+
+         # Non-PIC object.
+         if test "$non_pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           non_pic_object="$xdir$non_pic_object"
+
+           # A standard non-PIC object
+           non_pic_objects="$non_pic_objects $non_pic_object"
+           if test -z "$pic_object" || test "$pic_object" = none ; then
+             arg="$non_pic_object"
+           fi
+         else
+           # If the PIC object exists, use it instead.
+           # $xdir was prepended to $pic_object above.
+           non_pic_object="$pic_object"
+           non_pic_objects="$non_pic_objects $non_pic_object"
+         fi
+       else
+         # Only an error if not doing a dry-run.
+         if test -z "$run"; then
+           $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+           exit $EXIT_FAILURE
+         else
+           # Dry-run case.
+
+           # Extract subdirectory from the argument.
+           xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+           if test "X$xdir" = "X$arg"; then
+             xdir=
+           else
+             xdir="$xdir/"
+           fi
+
+           pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+           non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+           libobjs="$libobjs $pic_object"
+           non_pic_objects="$non_pic_objects $non_pic_object"
+         fi
+       fi
+       ;;
+
+      *.$libext)
+       # An archive.
+       deplibs="$deplibs $arg"
+       old_deplibs="$old_deplibs $arg"
+       continue
+       ;;
+
+      *.la)
+       # A libtool-controlled library.
+
+       if test "$prev" = dlfiles; then
+         # This library was specified with -dlopen.
+         dlfiles="$dlfiles $arg"
+         prev=
+       elif test "$prev" = dlprefiles; then
+         # The library was specified with -dlpreopen.
+         dlprefiles="$dlprefiles $arg"
+         prev=
+       else
+         deplibs="$deplibs $arg"
+       fi
+       continue
+       ;;
+
+      # Some other compiler argument.
+      *)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+      fi
+    done # argument parsing loop
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command="$compile_command $arg"
+      finalize_command="$finalize_command $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$output_objdir" = "X$output"; then
+      output_objdir="$objdir"
+    else
+      output_objdir="$output_objdir/$objdir"
+    fi
+    # Create the object directory.
+    if test ! -d "$output_objdir"; then
+      $show "$mkdir $output_objdir"
+      $run $mkdir $output_objdir
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+       exit $exit_status
+      fi
+    fi
+
+    # Determine the type of output
+    case $output in
+    "")
+      $echo "$modename: you must specify an output file" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    case $host in
+    *cygwin* | *mingw* | *pw32*)
+      # don't eliminate duplications in $postdeps and $predeps
+      duplicate_compiler_generated_deps=yes
+      ;;
+    *)
+      duplicate_compiler_generated_deps=$duplicate_deps
+      ;;
+    esac
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if test "X$duplicate_deps" = "Xyes" ; then
+       case "$libs " in
+       *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+       esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+       for pre_post_dep in $predeps $postdeps; do
+         case "$pre_post_deps " in
+         *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+         esac
+         pre_post_deps="$pre_post_deps $pre_post_dep"
+       done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    case $linkmode in
+    lib)
+       passes="conv link"
+       for file in $dlfiles $dlprefiles; do
+         case $file in
+         *.la) ;;
+         *)
+           $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+           exit $EXIT_FAILURE
+           ;;
+         esac
+       done
+       ;;
+    prog)
+       compile_deplibs=
+       finalize_deplibs=
+       alldeplibs=no
+       newdlfiles=
+       newdlprefiles=
+       passes="conv scan dlopen dlpreopen link"
+       ;;
+    *)  passes="conv"
+       ;;
+    esac
+    for pass in $passes; do
+      if test "$linkmode,$pass" = "lib,link" ||
+        test "$linkmode,$pass" = "prog,scan"; then
+       libs="$deplibs"
+       deplibs=
+      fi
+      if test "$linkmode" = prog; then
+       case $pass in
+       dlopen) libs="$dlfiles" ;;
+       dlpreopen) libs="$dlprefiles" ;;
+       link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+       esac
+      fi
+      if test "$pass" = dlopen; then
+       # Collect dlpreopened libraries
+       save_deplibs="$deplibs"
+       deplibs=
+      fi
+      for deplib in $libs; do
+       lib=
+       found=no
+       case $deplib in
+       -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+         if test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           compiler_flags="$compiler_flags $deplib"
+         fi
+         continue
+         ;;
+       -l*)
+         if test "$linkmode" != lib && test "$linkmode" != prog; then
+           $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+           continue
+         fi
+         name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+         for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+           for search_ext in .la $std_shrext .so .a; do
+             # Search the libtool library
+             lib="$searchdir/lib${name}${search_ext}"
+             if test -f "$lib"; then
+               if test "$search_ext" = ".la"; then
+                 found=yes
+               else
+                 found=no
+               fi
+               break 2
+             fi
+           done
+         done
+         if test "$found" != yes; then
+           # deplib doesn't seem to be a libtool library
+           if test "$linkmode,$pass" = "prog,link"; then
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             deplibs="$deplib $deplibs"
+             test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+           fi
+           continue
+         else # deplib is a libtool library
+           # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+           # We need to do some special things here, and not later.
+           if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+             case " $predeps $postdeps " in
+             *" $deplib "*)
+               if (${SED} -e '2q' $lib |
+                    grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+                 library_names=
+                 old_library=
+                 case $lib in
+                 */* | *\\*) . $lib ;;
+                 *) . ./$lib ;;
+                 esac
+                 for l in $old_library $library_names; do
+                   ll="$l"
+                 done
+                 if test "X$ll" = "X$old_library" ; then # only static version available
+                   found=no
+                   ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+                   test "X$ladir" = "X$lib" && ladir="."
+                   lib=$ladir/$old_library
+                   if test "$linkmode,$pass" = "prog,link"; then
+                     compile_deplibs="$deplib $compile_deplibs"
+                     finalize_deplibs="$deplib $finalize_deplibs"
+                   else
+                     deplibs="$deplib $deplibs"
+                     test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+                   fi
+                   continue
+                 fi
+               fi
+               ;;
+             *) ;;
+             esac
+           fi
+         fi
+         ;; # -l
+       -L*)
+         case $linkmode in
+         lib)
+           deplibs="$deplib $deplibs"
+           test "$pass" = conv && continue
+           newdependency_libs="$deplib $newdependency_libs"
+           newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+           ;;
+         prog)
+           if test "$pass" = conv; then
+             deplibs="$deplib $deplibs"
+             continue
+           fi
+           if test "$pass" = scan; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+           ;;
+         *)
+           $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+           ;;
+         esac # linkmode
+         continue
+         ;; # -L
+       -R*)
+         if test "$pass" = link; then
+           dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+           # Make sure the xrpath contains only unique directories.
+           case "$xrpath " in
+           *" $dir "*) ;;
+           *) xrpath="$xrpath $dir" ;;
+           esac
+         fi
+         deplibs="$deplib $deplibs"
+         continue
+         ;;
+       *.la) lib="$deplib" ;;
+       *.$libext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+           continue
+         fi
+         case $linkmode in
+         lib)
+           valid_a_lib=no
+           case $deplibs_check_method in
+             match_pattern*)
+               set dummy $deplibs_check_method
+               match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+               if eval $echo \"$deplib\" 2>/dev/null \
+                   | $SED 10q \
+                   | $EGREP "$match_pattern_regex" > /dev/null; then
+                 valid_a_lib=yes
+               fi
+               ;;
+             pass_all)
+               valid_a_lib=yes
+               ;;
+            esac
+           if test "$valid_a_lib" != yes; then
+             $echo
+             $echo "*** Warning: Trying to link with static lib archive $deplib."
+             $echo "*** I have the capability to make that library automatically link in when"
+             $echo "*** you link to this library.  But I can only do this if you have a"
+             $echo "*** shared version of the library, which you do not appear to have"
+             $echo "*** because the file extensions .$libext of this argument makes me believe"
+             $echo "*** that it is just a static archive that I should not used here."
+           else
+             $echo
+             $echo "*** Warning: Linking the shared library $output against the"
+             $echo "*** static library $deplib is not portable!"
+             deplibs="$deplib $deplibs"
+           fi
+           continue
+           ;;
+         prog)
+           if test "$pass" != link; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           continue
+           ;;
+         esac # linkmode
+         ;; # *.$libext
+       *.lo | *.$objext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+         elif test "$linkmode" = prog; then
+           if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+             # If there is no dlopen support or we're linking statically,
+             # we need to preload.
+             newdlprefiles="$newdlprefiles $deplib"
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             newdlfiles="$newdlfiles $deplib"
+           fi
+         fi
+         continue
+         ;;
+       %DEPLIBS%)
+         alldeplibs=yes
+         continue
+         ;;
+       esac # case $deplib
+       if test "$found" = yes || test -f "$lib"; then :
+       else
+         $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # Check to see that this really is a libtool archive.
+       if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$ladir" = "X$lib" && ladir="."
+
+       dlname=
+       dlopen=
+       dlpreopen=
+       libdir=
+       library_names=
+       old_library=
+       # If the library was installed with an old release of libtool,
+       # it will not redefine variables installed, or shouldnotlink
+       installed=yes
+       shouldnotlink=no
+       avoidtemprpath=
+
+
+       # Read the .la file
+       case $lib in
+       */* | *\\*) . $lib ;;
+       *) . ./$lib ;;
+       esac
+
+       if test "$linkmode,$pass" = "lib,link" ||
+          test "$linkmode,$pass" = "prog,scan" ||
+          { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+         test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+         test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+       fi
+
+       if test "$pass" = conv; then
+         # Only check for convenience libraries
+         deplibs="$lib $deplibs"
+         if test -z "$libdir"; then
+           if test -z "$old_library"; then
+             $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+             exit $EXIT_FAILURE
+           fi
+           # It is a libtool convenience library, so add in its objects.
+           convenience="$convenience $ladir/$objdir/$old_library"
+           old_convenience="$old_convenience $ladir/$objdir/$old_library"
+           tmp_libs=
+           for deplib in $dependency_libs; do
+             deplibs="$deplib $deplibs"
+              if test "X$duplicate_deps" = "Xyes" ; then
+               case "$tmp_libs " in
+               *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+               esac
+              fi
+             tmp_libs="$tmp_libs $deplib"
+           done
+         elif test "$linkmode" != prog && test "$linkmode" != lib; then
+           $echo "$modename: \`$lib' is not a convenience library" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         continue
+       fi # $pass = conv
+
+
+       # Get the name of the library we link against.
+       linklib=
+       for l in $old_library $library_names; do
+         linklib="$l"
+       done
+       if test -z "$linklib"; then
+         $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # This library was specified with -dlopen.
+       if test "$pass" = dlopen; then
+         if test -z "$libdir"; then
+           $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         if test -z "$dlname" ||
+            test "$dlopen_support" != yes ||
+            test "$build_libtool_libs" = no; then
+           # If there is no dlname, no dlopen support or we're linking
+           # statically, we need to preload.  We also need to preload any
+           # dependent libraries so libltdl's deplib preloader doesn't
+           # bomb out in the load deplibs phase.
+           dlprefiles="$dlprefiles $lib $dependency_libs"
+         else
+           newdlfiles="$newdlfiles $lib"
+         fi
+         continue
+       fi # $pass = dlopen
+
+       # We need an absolute path.
+       case $ladir in
+       [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+       *)
+         abs_ladir=`cd "$ladir" && pwd`
+         if test -z "$abs_ladir"; then
+           $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+           $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+           abs_ladir="$ladir"
+         fi
+         ;;
+       esac
+       laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+       # Find the relevant object directory and library name.
+       if test "X$installed" = Xyes; then
+         if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           $echo "$modename: warning: library \`$lib' was moved." 1>&2
+           dir="$ladir"
+           absdir="$abs_ladir"
+           libdir="$abs_ladir"
+         else
+           dir="$libdir"
+           absdir="$libdir"
+         fi
+         test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+       else
+         if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           dir="$ladir"
+           absdir="$abs_ladir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         else
+           dir="$ladir/$objdir"
+           absdir="$abs_ladir/$objdir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         fi
+       fi # $installed = yes
+       name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+       # This library was specified with -dlpreopen.
+       if test "$pass" = dlpreopen; then
+         if test -z "$libdir"; then
+           $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         # Prefer using a static library (so that no silly _DYNAMIC symbols
+         # are required to link).
+         if test -n "$old_library"; then
+           newdlprefiles="$newdlprefiles $dir/$old_library"
+         # Otherwise, use the dlname, so that lt_dlopen finds it.
+         elif test -n "$dlname"; then
+           newdlprefiles="$newdlprefiles $dir/$dlname"
+         else
+           newdlprefiles="$newdlprefiles $dir/$linklib"
+         fi
+       fi # $pass = dlpreopen
+
+       if test -z "$libdir"; then
+         # Link the convenience library
+         if test "$linkmode" = lib; then
+           deplibs="$dir/$old_library $deplibs"
+         elif test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$dir/$old_library $compile_deplibs"
+           finalize_deplibs="$dir/$old_library $finalize_deplibs"
+         else
+           deplibs="$lib $deplibs" # used for prog,scan pass
+         fi
+         continue
+       fi
+
+
+       if test "$linkmode" = prog && test "$pass" != link; then
+         newlib_search_path="$newlib_search_path $ladir"
+         deplibs="$lib $deplibs"
+
+         linkalldeplibs=no
+         if test "$link_all_deplibs" != no || test -z "$library_names" ||
+            test "$build_libtool_libs" = no; then
+           linkalldeplibs=yes
+         fi
+
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           case $deplib in
+           -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+           esac
+           # Need to link against all dependency_libs?
+           if test "$linkalldeplibs" = yes; then
+             deplibs="$deplib $deplibs"
+           else
+             # Need to hardcode shared library paths
+             # or/and link against static libraries
+             newdependency_libs="$deplib $newdependency_libs"
+           fi
+           if test "X$duplicate_deps" = "Xyes" ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done # for deplib
+         continue
+       fi # $linkmode = prog...
+
+       if test "$linkmode,$pass" = "prog,link"; then
+         if test -n "$library_names" &&
+            { { test "$prefer_static_libs" = no ||
+                test "$prefer_static_libs,$installed" = "built,yes"; } ||
+              test -z "$old_library"; }; then
+           # We need to hardcode the library path
+           if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+             # Make sure the rpath contains only unique directories.
+             case "$temp_rpath " in
+             *" $dir "*) ;;
+             *" $absdir "*) ;;
+             *) temp_rpath="$temp_rpath $absdir" ;;
+             esac
+           fi
+
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+         fi # $linkmode,$pass = prog,link...
+
+         if test "$alldeplibs" = yes &&
+            { test "$deplibs_check_method" = pass_all ||
+              { test "$build_libtool_libs" = yes &&
+                test -n "$library_names"; }; }; then
+           # We only need to search for static libraries
+           continue
+         fi
+       fi
+
+       link_static=no # Whether the deplib will be linked statically
+       use_static_libs=$prefer_static_libs
+       if test "$use_static_libs" = built && test "$installed" = yes ; then
+         use_static_libs=no
+       fi
+       if test -n "$library_names" &&
+          { test "$use_static_libs" = no || test -z "$old_library"; }; then
+         if test "$installed" = no; then
+           notinst_deplibs="$notinst_deplibs $lib"
+           need_relink=yes
+         fi
+         # This is a shared library
+
+         # Warn about portability, can't link against -module's on
+         # some systems (darwin)
+         if test "$shouldnotlink" = yes && test "$pass" = link ; then
+           $echo
+           if test "$linkmode" = prog; then
+             $echo "*** Warning: Linking the executable $output against the loadable module"
+           else
+             $echo "*** Warning: Linking the shared library $output against the loadable module"
+           fi
+           $echo "*** $linklib is not portable!"
+         fi
+         if test "$linkmode" = lib &&
+            test "$hardcode_into_libs" = yes; then
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+         fi
+
+         if test -n "$old_archive_from_expsyms_cmds"; then
+           # figure out the soname
+           set dummy $library_names
+           realname="$2"
+           shift; shift
+           libname=`eval \\$echo \"$libname_spec\"`
+           # use dlname if we got it. it's perfectly good, no?
+           if test -n "$dlname"; then
+             soname="$dlname"
+           elif test -n "$soname_spec"; then
+             # bleh windows
+             case $host in
+             *cygwin* | mingw*)
+               major=`expr $current - $age`
+               versuffix="-$major"
+               ;;
+             esac
+             eval soname=\"$soname_spec\"
+           else
+             soname="$realname"
+           fi
+
+           # Make a new name for the extract_expsyms_cmds to use
+           soroot="$soname"
+           soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+           newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+           # If the library has no export list, then create one now
+           if test -f "$output_objdir/$soname-def"; then :
+           else
+             $show "extracting exported symbol list from \`$soname'"
+             save_ifs="$IFS"; IFS='~'
+             cmds=$extract_expsyms_cmds
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+             done
+             IFS="$save_ifs"
+           fi
+
+           # Create $newlib
+           if test -f "$output_objdir/$newlib"; then :; else
+             $show "generating import library for \`$soname'"
+             save_ifs="$IFS"; IFS='~'
+             cmds=$old_archive_from_expsyms_cmds
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+             done
+             IFS="$save_ifs"
+           fi
+           # make sure the library variables are pointing to the new library
+           dir=$output_objdir
+           linklib=$newlib
+         fi # test -n "$old_archive_from_expsyms_cmds"
+
+         if test "$linkmode" = prog || test "$mode" != relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           lib_linked=yes
+           case $hardcode_action in
+           immediate | unsupported)
+             if test "$hardcode_direct" = no; then
+               add="$dir/$linklib"
+               case $host in
+                 *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+                 *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+                 *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+                   *-*-unixware7*) add_dir="-L$dir" ;;
+                 *-*-darwin* )
+                   # if the lib is a module then we can not link against
+                   # it, someone is ignoring the new warnings I added
+                   if /usr/bin/file -L $add 2> /dev/null |
+                      $EGREP ": [^:]* bundle" >/dev/null ; then
+                     $echo "** Warning, lib $linklib is a module, not a shared library"
+                     if test -z "$old_library" ; then
+                       $echo
+                       $echo "** And there doesn't seem to be a static archive available"
+                       $echo "** The link will probably fail, sorry"
+                     else
+                       add="$dir/$old_library"
+                     fi
+                   fi
+               esac
+             elif test "$hardcode_minus_L" = no; then
+               case $host in
+               *-*-sunos*) add_shlibpath="$dir" ;;
+               esac
+               add_dir="-L$dir"
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = no; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           relink)
+             if test "$hardcode_direct" = yes; then
+               add="$dir/$linklib"
+             elif test "$hardcode_minus_L" = yes; then
+               add_dir="-L$dir"
+               # Try looking first in the location we're being installed to.
+               if test -n "$inst_prefix_dir"; then
+                 case $libdir in
+                   [\\/]*)
+                     add_dir="$add_dir -L$inst_prefix_dir$libdir"
+                     ;;
+                 esac
+               fi
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = yes; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           *) lib_linked=no ;;
+           esac
+
+           if test "$lib_linked" != yes; then
+             $echo "$modename: configuration error: unsupported hardcode properties"
+             exit $EXIT_FAILURE
+           fi
+
+           if test -n "$add_shlibpath"; then
+             case :$compile_shlibpath: in
+             *":$add_shlibpath:"*) ;;
+             *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+             esac
+           fi
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+             test -n "$add" && compile_deplibs="$add $compile_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+             if test "$hardcode_direct" != yes && \
+                test "$hardcode_minus_L" != yes && \
+                test "$hardcode_shlibpath_var" = yes; then
+               case :$finalize_shlibpath: in
+               *":$libdir:"*) ;;
+               *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+               esac
+             fi
+           fi
+         fi
+
+         if test "$linkmode" = prog || test "$mode" = relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           # Finalize command for both is simple: just hardcode it.
+           if test "$hardcode_direct" = yes; then
+             add="$libdir/$linklib"
+           elif test "$hardcode_minus_L" = yes; then
+             add_dir="-L$libdir"
+             add="-l$name"
+           elif test "$hardcode_shlibpath_var" = yes; then
+             case :$finalize_shlibpath: in
+             *":$libdir:"*) ;;
+             *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+             esac
+             add="-l$name"
+           elif test "$hardcode_automatic" = yes; then
+             if test -n "$inst_prefix_dir" &&
+                test -f "$inst_prefix_dir$libdir/$linklib" ; then
+               add="$inst_prefix_dir$libdir/$linklib"
+             else
+               add="$libdir/$linklib"
+             fi
+           else
+             # We cannot seem to hardcode it, guess we'll fake it.
+             add_dir="-L$libdir"
+             # Try looking first in the location we're being installed to.
+             if test -n "$inst_prefix_dir"; then
+               case $libdir in
+                 [\\/]*)
+                   add_dir="$add_dir -L$inst_prefix_dir$libdir"
+                   ;;
+               esac
+             fi
+             add="-l$name"
+           fi
+
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+             test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+           fi
+         fi
+       elif test "$linkmode" = prog; then
+         # Here we assume that one of hardcode_direct or hardcode_minus_L
+         # is not unsupported.  This is valid on all known static and
+         # shared platforms.
+         if test "$hardcode_direct" != unsupported; then
+           test -n "$old_library" && linklib="$old_library"
+           compile_deplibs="$dir/$linklib $compile_deplibs"
+           finalize_deplibs="$dir/$linklib $finalize_deplibs"
+         else
+           compile_deplibs="-l$name -L$dir $compile_deplibs"
+           finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+         fi
+       elif test "$build_libtool_libs" = yes; then
+         # Not a shared library
+         if test "$deplibs_check_method" != pass_all; then
+           # We're trying link a shared library against a static one
+           # but the system doesn't support it.
+
+           # Just print a warning and add the library to dependency_libs so
+           # that the program can be linked against the static library.
+           $echo
+           $echo "*** Warning: This system can not link to static lib archive $lib."
+           $echo "*** I have the capability to make that library automatically link in when"
+           $echo "*** you link to this library.  But I can only do this if you have a"
+           $echo "*** shared version of the library, which you do not appear to have."
+           if test "$module" = yes; then
+             $echo "*** But as you try to build a module library, libtool will still create "
+             $echo "*** a static module, that should work as long as the dlopening application"
+             $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+             if test -z "$global_symbol_pipe"; then
+               $echo
+               $echo "*** However, this would only work if libtool was able to extract symbol"
+               $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+               $echo "*** not find such a program.  So, this module is probably useless."
+               $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+             fi
+             if test "$build_old_libs" = no; then
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         else
+           deplibs="$dir/$old_library $deplibs"
+           link_static=yes
+         fi
+       fi # link shared/static library?
+
+       if test "$linkmode" = lib; then
+         if test -n "$dependency_libs" &&
+            { test "$hardcode_into_libs" != yes ||
+              test "$build_old_libs" = yes ||
+              test "$link_static" = yes; }; then
+           # Extract -R from dependency_libs
+           temp_deplibs=
+           for libdir in $dependency_libs; do
+             case $libdir in
+             -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+                  case " $xrpath " in
+                  *" $temp_xrpath "*) ;;
+                  *) xrpath="$xrpath $temp_xrpath";;
+                  esac;;
+             *) temp_deplibs="$temp_deplibs $libdir";;
+             esac
+           done
+           dependency_libs="$temp_deplibs"
+         fi
+
+         newlib_search_path="$newlib_search_path $absdir"
+         # Link against this library
+         test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+         # ... and its dependency_libs
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           newdependency_libs="$deplib $newdependency_libs"
+           if test "X$duplicate_deps" = "Xyes" ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done
+
+         if test "$link_all_deplibs" != no; then
+           # Add the search paths of all dependency libraries
+           for deplib in $dependency_libs; do
+             case $deplib in
+             -L*) path="$deplib" ;;
+             *.la)
+               dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+               test "X$dir" = "X$deplib" && dir="."
+               # We need an absolute path.
+               case $dir in
+               [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+               *)
+                 absdir=`cd "$dir" && pwd`
+                 if test -z "$absdir"; then
+                   $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+                   absdir="$dir"
+                 fi
+                 ;;
+               esac
+               if grep "^installed=no" $deplib > /dev/null; then
+                 path="$absdir/$objdir"
+               else
+                 eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+                 if test -z "$libdir"; then
+                   $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+                   exit $EXIT_FAILURE
+                 fi
+                 if test "$absdir" != "$libdir"; then
+                   $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+                 fi
+                 path="$absdir"
+               fi
+               depdepl=
+               case $host in
+               *-*-darwin*)
+                 # we do not want to link against static libs,
+                 # but need to link against shared
+                 eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+                 if test -n "$deplibrary_names" ; then
+                   for tmp in $deplibrary_names ; do
+                     depdepl=$tmp
+                   done
+                   if test -f "$path/$depdepl" ; then
+                     depdepl="$path/$depdepl"
+                   fi
+                   # do not add paths which are already there
+                   case " $newlib_search_path " in
+                   *" $path "*) ;;
+                   *) newlib_search_path="$newlib_search_path $path";;
+                   esac
+                 fi
+                 path=""
+                 ;;
+               *)
+                 path="-L$path"
+                 ;;
+               esac
+               ;;
+             -l*)
+               case $host in
+               *-*-darwin*)
+                 # Again, we only want to link against shared libraries
+                 eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+                 for tmp in $newlib_search_path ; do
+                   if test -f "$tmp/lib$tmp_libs.dylib" ; then
+                     eval depdepl="$tmp/lib$tmp_libs.dylib"
+                     break
+                   fi
+                 done
+                 path=""
+                 ;;
+               *) continue ;;
+               esac
+               ;;
+             *) continue ;;
+             esac
+             case " $deplibs " in
+             *" $path "*) ;;
+             *) deplibs="$path $deplibs" ;;
+             esac
+             case " $deplibs " in
+             *" $depdepl "*) ;;
+             *) deplibs="$depdepl $deplibs" ;;
+             esac
+           done
+         fi # link_all_deplibs != no
+       fi # linkmode = lib
+      done # for deplib in $libs
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+       # Link the dlpreopened libraries before other libraries
+       for deplib in $save_deplibs; do
+         deplibs="$deplib $deplibs"
+       done
+      fi
+      if test "$pass" != dlopen; then
+       if test "$pass" != conv; then
+         # Make sure lib_search_path contains only unique directories.
+         lib_search_path=
+         for dir in $newlib_search_path; do
+           case "$lib_search_path " in
+           *" $dir "*) ;;
+           *) lib_search_path="$lib_search_path $dir" ;;
+           esac
+         done
+         newlib_search_path=
+       fi
+
+       if test "$linkmode,$pass" != "prog,link"; then
+         vars="deplibs"
+       else
+         vars="compile_deplibs finalize_deplibs"
+       fi
+       for var in $vars dependency_libs; do
+         # Add libraries to $var in reverse order
+         eval tmp_libs=\"\$$var\"
+         new_libs=
+         for deplib in $tmp_libs; do
+           # FIXME: Pedantically, this is the right thing to do, so
+           #        that some nasty dependency loop isn't accidentally
+           #        broken:
+           #new_libs="$deplib $new_libs"
+           # Pragmatically, this seems to cause very few problems in
+           # practice:
+           case $deplib in
+           -L*) new_libs="$deplib $new_libs" ;;
+           -R*) ;;
+           *)
+             # And here is the reason: when a library appears more
+             # than once as an explicit dependence of a library, or
+             # is implicitly linked in more than once by the
+             # compiler, it is considered special, and multiple
+             # occurrences thereof are not removed.  Compare this
+             # with having the same library being listed as a
+             # dependency of multiple other libraries: in this case,
+             # we know (pedantically, we assume) the library does not
+             # need to be listed more than once, so we keep only the
+             # last copy.  This is not always right, but it is rare
+             # enough that we require users that really mean to play
+             # such unportable linking tricks to link the library
+             # using -Wl,-lname, so that libtool does not consider it
+             # for duplicate removal.
+             case " $specialdeplibs " in
+             *" $deplib "*) new_libs="$deplib $new_libs" ;;
+             *)
+               case " $new_libs " in
+               *" $deplib "*) ;;
+               *) new_libs="$deplib $new_libs" ;;
+               esac
+               ;;
+             esac
+             ;;
+           esac
+         done
+         tmp_libs=
+         for deplib in $new_libs; do
+           case $deplib in
+           -L*)
+             case " $tmp_libs " in
+             *" $deplib "*) ;;
+             *) tmp_libs="$tmp_libs $deplib" ;;
+             esac
+             ;;
+           *) tmp_libs="$tmp_libs $deplib" ;;
+           esac
+         done
+         eval $var=\"$tmp_libs\"
+       done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+       case " $predeps $postdeps $compiler_lib_search_path " in
+       *" $i "*)
+         i=""
+         ;;
+       esac
+       if test -n "$i" ; then
+         tmp_libs="$tmp_libs $i"
+       fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+       $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+      fi
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+       name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+       eval shared_ext=\"$shrext_cmds\"
+       eval libname=\"$libname_spec\"
+       ;;
+      *)
+       if test "$module" = no; then
+         $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+       if test "$need_lib_prefix" != no; then
+         # Add the "lib" prefix for modules if required
+         name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+         eval shared_ext=\"$shrext_cmds\"
+         eval libname=\"$libname_spec\"
+       else
+         libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+       fi
+       ;;
+      esac
+
+      if test -n "$objs"; then
+       if test "$deplibs_check_method" != pass_all; then
+         $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+         exit $EXIT_FAILURE
+       else
+         $echo
+         $echo "*** Warning: Linking the shared library $output against the non-libtool"
+         $echo "*** objects $objs is not portable!"
+         libobjs="$libobjs $objs"
+       fi
+      fi
+
+      if test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+      fi
+
+      set dummy $rpath
+      if test "$#" -gt 2; then
+       $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+      fi
+      install_libdir="$2"
+
+      oldlibs=
+      if test -z "$rpath"; then
+       if test "$build_libtool_libs" = yes; then
+         # Building a libtool convenience library.
+         # Some compilers have problems with a `.al' extension so
+         # convenience libraries should have the same extension an
+         # archive normally would.
+         oldlibs="$output_objdir/$libname.$libext $oldlibs"
+         build_libtool_libs=convenience
+         build_old_libs=yes
+       fi
+
+       if test -n "$vinfo"; then
+         $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+       fi
+
+       if test -n "$release"; then
+         $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+       fi
+      else
+
+       # Parse the version information argument.
+       save_ifs="$IFS"; IFS=':'
+       set dummy $vinfo 0 0 0
+       IFS="$save_ifs"
+
+       if test -n "$8"; then
+         $echo "$modename: too many parameters to \`-version-info'" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # convert absolute version numbers to libtool ages
+       # this retains compatibility with .la files and attempts
+       # to make the code below a bit more comprehensible
+
+       case $vinfo_number in
+       yes)
+         number_major="$2"
+         number_minor="$3"
+         number_revision="$4"
+         #
+         # There are really only two kinds -- those that
+         # use the current revision as the major version
+         # and those that subtract age and use age as
+         # a minor version.  But, then there is irix
+         # which has an extra 1 added just for fun
+         #
+         case $version_type in
+         darwin|linux|osf|windows|none)
+           current=`expr $number_major + $number_minor`
+           age="$number_minor"
+           revision="$number_revision"
+           ;;
+         freebsd-aout|freebsd-elf|sunos)
+           current="$number_major"
+           revision="$number_minor"
+           age="0"
+           ;;
+         irix|nonstopux)
+           current=`expr $number_major + $number_minor`
+           age="$number_minor"
+           revision="$number_minor"
+           lt_irix_increment=no
+           ;;
+         esac
+         ;;
+       no)
+         current="$2"
+         revision="$3"
+         age="$4"
+         ;;
+       esac
+
+       # Check that each of the things are valid numbers.
+       case $current in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       case $revision in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       case $age in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       if test "$age" -gt "$current"; then
+         $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # Calculate the version variables.
+       major=
+       versuffix=
+       verstring=
+       case $version_type in
+       none) ;;
+
+       darwin)
+         # Like Linux, but with the current version available in
+         # verstring for coding it into the library header
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         # Darwin ld doesn't like 0 for these options...
+         minor_current=`expr $current + 1`
+         xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+         verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+         ;;
+
+       freebsd-aout)
+         major=".$current"
+         versuffix=".$current.$revision";
+         ;;
+
+       freebsd-elf)
+         major=".$current"
+         versuffix=".$current";
+         ;;
+
+       irix | nonstopux)
+         if test "X$lt_irix_increment" = "Xno"; then
+           major=`expr $current - $age`
+         else
+           major=`expr $current - $age + 1`
+         fi
+         case $version_type in
+           nonstopux) verstring_prefix=nonstopux ;;
+           *)         verstring_prefix=sgi ;;
+         esac
+         verstring="$verstring_prefix$major.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$revision
+         while test "$loop" -ne 0; do
+           iface=`expr $revision - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring_prefix$major.$iface:$verstring"
+         done
+
+         # Before this point, $major must not contain `.'.
+         major=.$major
+         versuffix="$major.$revision"
+         ;;
+
+       linux)
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         ;;
+
+       osf)
+         major=.`expr $current - $age`
+         versuffix=".$current.$age.$revision"
+         verstring="$current.$age.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$age
+         while test "$loop" -ne 0; do
+           iface=`expr $current - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring:${iface}.0"
+         done
+
+         # Make executables depend on our current version.
+         verstring="$verstring:${current}.0"
+         ;;
+
+       sunos)
+         major=".$current"
+         versuffix=".$current.$revision"
+         ;;
+
+       windows)
+         # Use '-' rather than '.', since we only want one
+         # extension on DOS 8.3 filesystems.
+         major=`expr $current - $age`
+         versuffix="-$major"
+         ;;
+
+       *)
+         $echo "$modename: unknown library version type \`$version_type'" 1>&2
+         $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       # Clear the version info if we defaulted, and they specified a release.
+       if test -z "$vinfo" && test -n "$release"; then
+         major=
+         case $version_type in
+         darwin)
+           # we can't check for "0.0" in archive_cmds due to quoting
+           # problems, so we reset it completely
+           verstring=
+           ;;
+         *)
+           verstring="0.0"
+           ;;
+         esac
+         if test "$need_version" = no; then
+           versuffix=
+         else
+           versuffix=".0.0"
+         fi
+       fi
+
+       # Remove version info from name if versioning should be avoided
+       if test "$avoid_version" = yes && test "$need_version" = no; then
+         major=
+         versuffix=
+         verstring=""
+       fi
+
+       # Check to see if the archive will have undefined symbols.
+       if test "$allow_undefined" = yes; then
+         if test "$allow_undefined_flag" = unsupported; then
+           $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+           build_libtool_libs=no
+           build_old_libs=yes
+         fi
+       else
+         # Don't allow undefined symbols.
+         allow_undefined_flag="$no_undefined_flag"
+       fi
+      fi
+
+      if test "$mode" != relink; then
+       # Remove our outputs, but don't remove object files since they
+       # may have been created when compiling PIC objects.
+       removelist=
+       tempremovelist=`$echo "$output_objdir/*"`
+       for p in $tempremovelist; do
+         case $p in
+           *.$objext)
+              ;;
+           $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+              if test "X$precious_files_regex" != "X"; then
+                if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+                then
+                  continue
+                fi
+              fi
+              removelist="$removelist $p"
+              ;;
+           *) ;;
+         esac
+       done
+       if test -n "$removelist"; then
+         $show "${rm}r $removelist"
+         $run ${rm}r $removelist
+       fi
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+       oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+       # Transform .lo files to .o files.
+       oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #        lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+      #        deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+      #        dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       temp_xrpath=
+       for libdir in $xrpath; do
+         temp_xrpath="$temp_xrpath -R$libdir"
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+       if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+         dependency_libs="$temp_xrpath $dependency_libs"
+       fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+       case " $dlprefiles $dlfiles " in
+       *" $lib "*) ;;
+       *) dlfiles="$dlfiles $lib" ;;
+       esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+       case "$dlprefiles " in
+       *" $lib "*) ;;
+       *) dlprefiles="$dlprefiles $lib" ;;
+       esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+       if test -n "$rpath"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+           # these systems don't actually have a c library (as such)!
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C library is in the System framework
+           deplibs="$deplibs -framework System"
+           ;;
+         *-*-netbsd*)
+           # Don't link with libc until the a.out ld.so is fixed.
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           ;;
+         *)
+           # Add libc to deplibs on all other systems if necessary.
+           if test "$build_libtool_need_lc" = "yes"; then
+             deplibs="$deplibs -lc"
+           fi
+           ;;
+         esac
+       fi
+
+       # Transform deplibs into only deplibs that can be linked in shared.
+       name_save=$name
+       libname_save=$libname
+       release_save=$release
+       versuffix_save=$versuffix
+       major_save=$major
+       # I'm not sure if I'm treating the release correctly.  I think
+       # release should show up in the -l (ie -lgmp5) so we don't want to
+       # add it in twice.  Is that correct?
+       release=""
+       versuffix=""
+       major=""
+       newdeplibs=
+       droppeddeps=no
+       case $deplibs_check_method in
+       pass_all)
+         # Don't check for shared/static.  Everything works.
+         # This might be a little naive.  We might want to check
+         # whether the library exists or not.  But this is on
+         # osf3 & osf4 and I'm not really sure... Just
+         # implementing what was already the behavior.
+         newdeplibs=$deplibs
+         ;;
+       test_compile)
+         # This code stresses the "libraries are programs" paradigm to its
+         # limits. Maybe even breaks it.  We compile a program, linking it
+         # against the deplibs as a proxy for the library.  Then we can check
+         # whether they linked in statically or dynamically with ldd.
+         $rm conftest.c
+         cat > conftest.c <<EOF
+         int main() { return 0; }
+EOF
+         $rm conftest
+         if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             name=`expr $i : '-l\(.*\)'`
+             # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
+               if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                 case " $predeps $postdeps " in
+                 *" $i "*)
+                   newdeplibs="$newdeplibs $i"
+                   i=""
+                   ;;
+                 esac
+               fi
+               if test -n "$i" ; then
+                 libname=`eval \\$echo \"$libname_spec\"`
+                 deplib_matches=`eval \\$echo \"$library_names_spec\"`
+                 set dummy $deplib_matches
+                 deplib_match=$2
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   $echo
+                   $echo "*** Warning: dynamic linker does not accept needed library $i."
+                   $echo "*** I have the capability to make that library automatically link in when"
+                   $echo "*** you link to this library.  But I can only do this if you have a"
+                   $echo "*** shared version of the library, which I believe you do not have"
+                   $echo "*** because a test_compile did reveal that the linker did not use it for"
+                   $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+                 fi
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         else
+           # Error occurred in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             name=`expr $i : '-l\(.*\)'`
+             # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
+               $rm conftest
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+                 ldd_output=`ldd conftest`
+                 if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                   case " $predeps $postdeps " in
+                   *" $i "*)
+                     newdeplibs="$newdeplibs $i"
+                     i=""
+                     ;;
+                   esac
+                 fi
+                 if test -n "$i" ; then
+                   libname=`eval \\$echo \"$libname_spec\"`
+                   deplib_matches=`eval \\$echo \"$library_names_spec\"`
+                   set dummy $deplib_matches
+                   deplib_match=$2
+                   if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                     newdeplibs="$newdeplibs $i"
+                   else
+                     droppeddeps=yes
+                     $echo
+                     $echo "*** Warning: dynamic linker does not accept needed library $i."
+                     $echo "*** I have the capability to make that library automatically link in when"
+                     $echo "*** you link to this library.  But I can only do this if you have a"
+                     $echo "*** shared version of the library, which you do not appear to have"
+                     $echo "*** because a test_compile did reveal that the linker did not use this one"
+                     $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+                   fi
+                 fi
+               else
+                 droppeddeps=yes
+                 $echo
+                 $echo "*** Warning!  Library $i is needed by this library but I was not able to"
+                 $echo "*** make it link in!  You will probably need to install it or some"
+                 $echo "*** library that it depends on before this library will be fully"
+                 $echo "*** functional.  Installing it before continuing would be even better."
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method
+         file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+         for a_deplib in $deplibs; do
+           name=`expr $a_deplib : '-l\(.*\)'`
+           # If $name is empty we are operating on a -L argument.
+            if test "$name" != "" && test  "$name" != "0"; then
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 newdeplibs="$newdeplibs $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval \\$echo \"$libname_spec\"`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                     # Follow soft links.
+                     if ls -lLd "$potent_lib" 2>/dev/null \
+                        | grep " -> " >/dev/null; then
+                       continue
+                     fi
+                     # The statement above tries to avoid entering an
+                     # endless loop below, in case of cyclic links.
+                     # We might still enter an endless loop, since a link
+                     # loop can be closed while we follow links,
+                     # but so what?
+                     potlib="$potent_lib"
+                     while test -h "$potlib" 2>/dev/null; do
+                       potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+                       case $potliblink in
+                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+                       *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+                       esac
+                     done
+                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+                        | ${SED} 10q \
+                        | $EGREP "$file_magic_regex" > /dev/null; then
+                       newdeplibs="$newdeplibs $a_deplib"
+                       a_deplib=""
+                       break 2
+                     fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               $echo
+               $echo "*** Warning: linker path does not have real file for library $a_deplib."
+               $echo "*** I have the capability to make that library automatically link in when"
+               $echo "*** you link to this library.  But I can only do this if you have a"
+               $echo "*** shared version of the library, which you do not appear to have"
+               $echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $echo "*** with $libname but no candidates were found. (...for file magic test)"
+               else
+                 $echo "*** with $libname and none of the candidates passed a file format test"
+                 $echo "*** using a file magic. Last file checked: $potlib"
+               fi
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       match_pattern*)
+         set dummy $deplibs_check_method
+         match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+         for a_deplib in $deplibs; do
+           name=`expr $a_deplib : '-l\(.*\)'`
+           # If $name is empty we are operating on a -L argument.
+           if test -n "$name" && test "$name" != "0"; then
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 newdeplibs="$newdeplibs $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval \\$echo \"$libname_spec\"`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                   potlib="$potent_lib" # see symlink-check above in file_magic test
+                   if eval $echo \"$potent_lib\" 2>/dev/null \
+                       | ${SED} 10q \
+                       | $EGREP "$match_pattern_regex" > /dev/null; then
+                     newdeplibs="$newdeplibs $a_deplib"
+                     a_deplib=""
+                     break 2
+                   fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               $echo
+               $echo "*** Warning: linker path does not have real file for library $a_deplib."
+               $echo "*** I have the capability to make that library automatically link in when"
+               $echo "*** you link to this library.  But I can only do this if you have a"
+               $echo "*** shared version of the library, which you do not appear to have"
+               $echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+               else
+                 $echo "*** with $libname and none of the candidates passed a file format test"
+                 $echo "*** using a regex pattern. Last file checked: $potlib"
+               fi
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       none | unknown | *)
+         newdeplibs=""
+         tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+           -e 's/ -[LR][^ ]*//g'`
+         if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+           for i in $predeps $postdeps ; do
+             # can't use Xsed below, because $i might contain '/'
+             tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+           done
+         fi
+         if $echo "X $tmp_deplibs" | $Xsed -e 's/[     ]//g' \
+           | grep . >/dev/null; then
+           $echo
+           if test "X$deplibs_check_method" = "Xnone"; then
+             $echo "*** Warning: inter-library dependencies are not supported in this platform."
+           else
+             $echo "*** Warning: inter-library dependencies are not known to be supported."
+           fi
+           $echo "*** All declared inter-library dependencies are being dropped."
+           droppeddeps=yes
+         fi
+         ;;
+       esac
+       versuffix=$versuffix_save
+       major=$major_save
+       release=$release_save
+       libname=$libname_save
+       name=$name_save
+
+       case $host in
+       *-*-rhapsody* | *-*-darwin1.[012])
+         # On Rhapsody replace the C library is the System framework
+         newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+         ;;
+       esac
+
+       if test "$droppeddeps" = yes; then
+         if test "$module" = yes; then
+           $echo
+           $echo "*** Warning: libtool could not satisfy all declared inter-library"
+           $echo "*** dependencies of module $libname.  Therefore, libtool will create"
+           $echo "*** a static module, that should work as long as the dlopening"
+           $echo "*** application is linked with the -dlopen flag."
+           if test -z "$global_symbol_pipe"; then
+             $echo
+             $echo "*** However, this would only work if libtool was able to extract symbol"
+             $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+             $echo "*** not find such a program.  So, this module is probably useless."
+             $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+           fi
+           if test "$build_old_libs" = no; then
+             oldlibs="$output_objdir/$libname.$libext"
+             build_libtool_libs=module
+             build_old_libs=yes
+           else
+             build_libtool_libs=no
+           fi
+         else
+           $echo "*** The inter-library dependencies that have been dropped here will be"
+           $echo "*** automatically added whenever a program is linked with this library"
+           $echo "*** or is declared to -dlopen it."
+
+           if test "$allow_undefined" = no; then
+             $echo
+             $echo "*** Since this library must not contain undefined symbols,"
+             $echo "*** because either the platform does not support them or"
+             $echo "*** it was explicitly requested with -no-undefined,"
+             $echo "*** libtool will only create a static version of it."
+             if test "$build_old_libs" = no; then
+               oldlibs="$output_objdir/$libname.$libext"
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         fi
+       fi
+       # Done checking deplibs!
+       deplibs=$newdeplibs
+      fi
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      deplibs="$new_libs"
+
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+       if test "$hardcode_into_libs" = yes; then
+         # Hardcode the library paths
+         hardcode_libdirs=
+         dep_rpath=
+         rpath="$finalize_rpath"
+         test "$mode" != relink && rpath="$compile_rpath$rpath"
+         for libdir in $rpath; do
+           if test -n "$hardcode_libdir_flag_spec"; then
+             if test -n "$hardcode_libdir_separator"; then
+               if test -z "$hardcode_libdirs"; then
+                 hardcode_libdirs="$libdir"
+               else
+                 # Just accumulate the unique libdirs.
+                 case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+                 *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+                   ;;
+                 *)
+                   hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+                   ;;
+                 esac
+               fi
+             else
+               eval flag=\"$hardcode_libdir_flag_spec\"
+               dep_rpath="$dep_rpath $flag"
+             fi
+           elif test -n "$runpath_var"; then
+             case "$perm_rpath " in
+             *" $libdir "*) ;;
+             *) perm_rpath="$perm_rpath $libdir" ;;
+             esac
+           fi
+         done
+         # Substitute the hardcoded libdirs into the rpath.
+         if test -n "$hardcode_libdir_separator" &&
+            test -n "$hardcode_libdirs"; then
+           libdir="$hardcode_libdirs"
+           if test -n "$hardcode_libdir_flag_spec_ld"; then
+             case $archive_cmds in
+             *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;;
+             *)      eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;;
+             esac
+           else
+             eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+           fi
+         fi
+         if test -n "$runpath_var" && test -n "$perm_rpath"; then
+           # We should set the runpath_var.
+           rpath=
+           for dir in $perm_rpath; do
+             rpath="$rpath$dir:"
+           done
+           eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+         fi
+         test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+       fi
+
+       shlibpath="$finalize_shlibpath"
+       test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+       if test -n "$shlibpath"; then
+         eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+       fi
+
+       # Get the real and link names of the library.
+       eval shared_ext=\"$shrext_cmds\"
+       eval library_names=\"$library_names_spec\"
+       set dummy $library_names
+       realname="$2"
+       shift; shift
+
+       if test -n "$soname_spec"; then
+         eval soname=\"$soname_spec\"
+       else
+         soname="$realname"
+       fi
+       if test -z "$dlname"; then
+         dlname=$soname
+       fi
+
+       lib="$output_objdir/$realname"
+       linknames=
+       for link
+       do
+         linknames="$linknames $link"
+       done
+
+       # Use standard objects if they are pic
+       test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+       # Prepare the list of exported symbols
+       if test -z "$export_symbols"; then
+         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+           $show "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $run $rm $export_symbols
+           cmds=$export_symbols_cmds
+           save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             eval cmd=\"$cmd\"
+             if len=`expr "X$cmd" : ".*"` &&
+              test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+               skipped_export=false
+             else
+               # The command line is too long to execute in one step.
+               $show "using reloadable object file for export list..."
+               skipped_export=:
+               # Break out early, otherwise skipped_export may be
+               # set to false by a later but shorter cmd.
+               break
+             fi
+           done
+           IFS="$save_ifs"
+           if test -n "$export_symbols_regex"; then
+             $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+             $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+             $run eval '$mv "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+       fi
+
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+       fi
+
+       tmp_deplibs=
+       for test_deplib in $deplibs; do
+               case " $convenience " in
+               *" $test_deplib "*) ;;
+               *)
+                       tmp_deplibs="$tmp_deplibs $test_deplib"
+                       ;;
+               esac
+       done
+       deplibs="$tmp_deplibs"
+
+       if test -n "$convenience"; then
+         if test -n "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+         else
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           func_extract_archives $gentop $convenience
+           libobjs="$libobjs $func_extract_archives_result"
+         fi
+       fi
+       
+       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+         eval flag=\"$thread_safe_flag_spec\"
+         linker_flags="$linker_flags $flag"
+       fi
+
+       # Make a backup of the uninstalled library when relinking
+       if test "$mode" = relink; then
+         $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+       fi
+
+       # Do each of the archive commands.
+       if test "$module" = yes && test -n "$module_cmds" ; then
+         if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+           eval test_cmds=\"$module_expsym_cmds\"
+           cmds=$module_expsym_cmds
+         else
+           eval test_cmds=\"$module_cmds\"
+           cmds=$module_cmds
+         fi
+       else
+       if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+         eval test_cmds=\"$archive_expsym_cmds\"
+         cmds=$archive_expsym_cmds
+       else
+         eval test_cmds=\"$archive_cmds\"
+         cmds=$archive_cmds
+         fi
+       fi
+
+       if test "X$skipped_export" != "X:" &&
+          len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+          test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         :
+       else
+         # The command line is too long to link in one step, link piecewise.
+         $echo "creating reloadable object files..."
+
+         # Save the value of $output and $libobjs because we want to
+         # use them later.  If we have whole_archive_flag_spec, we
+         # want to use save_libobjs as it was before
+         # whole_archive_flag_spec was expanded, because we can't
+         # assume the linker understands whole_archive_flag_spec.
+         # This may have to be revisited, in case too many
+         # convenience libraries get linked in and end up exceeding
+         # the spec.
+         if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+         fi
+         save_output=$output
+         output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+         # Clear the reloadable object creation command queue and
+         # initialize k to one.
+         test_cmds=
+         concat_cmds=
+         objlist=
+         delfiles=
+         last_robj=
+         k=1
+         output=$output_objdir/$output_la-${k}.$objext
+         # Loop over the list of objects to be linked.
+         for obj in $save_libobjs
+         do
+           eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+           if test "X$objlist" = X ||
+              { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+                test "$len" -le "$max_cmd_len"; }; then
+             objlist="$objlist $obj"
+           else
+             # The command $test_cmds is almost too long, add a
+             # command to the queue.
+             if test "$k" -eq 1 ; then
+               # The first file doesn't have a previous command to add.
+               eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+             else
+               # All subsequent reloadable object files will link in
+               # the last one created.
+               eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+             fi
+             last_robj=$output_objdir/$output_la-${k}.$objext
+             k=`expr $k + 1`
+             output=$output_objdir/$output_la-${k}.$objext
+             objlist=$obj
+             len=1
+           fi
+         done
+         # Handle the remaining objects by creating one last
+         # reloadable object file.  All subsequent reloadable object
+         # files will link in the last one created.
+         test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+         eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+         if ${skipped_export-false}; then
+           $show "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $run $rm $export_symbols
+           libobjs=$output
+           # Append the command to create the export file.
+           eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+          fi
+
+         # Set up a command to remove the reloadable object files
+         # after they are used.
+         i=0
+         while test "$i" -lt "$k"
+         do
+           i=`expr $i + 1`
+           delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+         done
+
+         $echo "creating a temporary reloadable object file: $output"
+
+         # Loop through the commands generated above and execute them.
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $concat_cmds; do
+           IFS="$save_ifs"
+           $show "$cmd"
+           $run eval "$cmd" || exit $?
+         done
+         IFS="$save_ifs"
+
+         libobjs=$output
+         # Restore the value of output.
+         output=$save_output
+
+         if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+         fi
+         # Expand the library linking commands again to reset the
+         # value of $libobjs for piecewise linking.
+
+         # Do each of the archive commands.
+         if test "$module" = yes && test -n "$module_cmds" ; then
+           if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+             cmds=$module_expsym_cmds
+           else
+             cmds=$module_cmds
+           fi
+         else
+         if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+           cmds=$archive_expsym_cmds
+         else
+           cmds=$archive_cmds
+           fi
+         fi
+
+         # Append the command to remove the reloadable object files
+         # to the just-reset $cmds.
+         eval cmds=\"\$cmds~\$rm $delfiles\"
+       fi
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         eval cmd=\"$cmd\"
+         $show "$cmd"
+         $run eval "$cmd" || {
+           lt_exit=$?
+
+           # Restore the uninstalled library and exit
+           if test "$mode" = relink; then
+             $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+           fi
+
+           exit $lt_exit
+         }
+       done
+       IFS="$save_ifs"
+
+       # Restore the uninstalled library and exit
+       if test "$mode" = relink; then
+         $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+         if test -n "$convenience"; then
+           if test -z "$whole_archive_flag_spec"; then
+             $show "${rm}r $gentop"
+             $run ${rm}r "$gentop"
+           fi
+         fi
+
+         exit $EXIT_SUCCESS
+       fi
+
+       # Create links to the real library.
+       for linkname in $linknames; do
+         if test "$realname" != "$linkname"; then
+           $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+           $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+         fi
+       done
+
+       # If -module or -export-dynamic was specified, set the dlname.
+       if test "$module" = yes || test "$export_dynamic" = yes; then
+         # On all known operating systems, these are identical.
+         dlname="$soname"
+       fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+      fi
+
+      case $output in
+      *.lo)
+       if test -n "$objs$old_deplibs"; then
+         $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+         exit $EXIT_FAILURE
+       fi
+       libobj="$output"
+       obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+       ;;
+      *)
+       libobj=
+       obj="$output"
+       ;;
+      esac
+
+      # Delete the old objects.
+      $run $rm $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+       if test -n "$whole_archive_flag_spec"; then
+         eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+         reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+       else
+         gentop="$output_objdir/${obj}x"
+         generated="$generated $gentop"
+
+         func_extract_archives $gentop $convenience
+         reload_conv_objs="$reload_objs $func_extract_archives_result"
+       fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      cmds=$reload_cmds
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       eval cmd=\"$cmd\"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       # Create an invalid libtool object if no PIC, so that we don't
+       # accidentally link it into a program.
+       # $show "echo timestamp > $libobj"
+       # $run eval "echo timestamp > $libobj" || exit $?
+       exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+       # Only do commands if we really have different PIC objects.
+       reload_objs="$libobjs $reload_conv_objs"
+       output="$libobj"
+       cmds=$reload_cmds
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         eval cmd=\"$cmd\"
+         $show "$cmd"
+         $run eval "$cmd" || exit $?
+       done
+       IFS="$save_ifs"
+      fi
+
+      if test -n "$gentop"; then
+       $show "${rm}r $gentop"
+       $run ${rm}r $gentop
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+       *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+      esac
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+      fi
+
+      if test "$preload" = yes; then
+       if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+          test "$dlopen_self_static" = unknown; then
+         $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+       fi
+      fi
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+       # On Rhapsody replace the C library is the System framework
+       compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+       finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+       ;;
+      esac
+
+      case $host in
+      *darwin*)
+        # Don't allow lazy linking, it breaks C++ global constructors
+        if test "$tagname" = CXX ; then
+        compile_command="$compile_command ${wl}-bind_at_load"
+        finalize_command="$finalize_command ${wl}-bind_at_load"
+        fi
+        ;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $compile_deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $compile_deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       for libdir in $rpath $xrpath; do
+         # This is the magic to use -rpath.
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$perm_rpath " in
+         *" $libdir "*) ;;
+         *) perm_rpath="$perm_rpath $libdir" ;;
+         esac
+       fi
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$libdir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$libdir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
+         ;;
+       esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$finalize_perm_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+       # Transform all the library objects into standard objects.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      dlsyms=
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       if test -n "$NM" && test -n "$global_symbol_pipe"; then
+         dlsyms="${outputname}S.c"
+       else
+         $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+       fi
+      fi
+
+      if test -n "$dlsyms"; then
+       case $dlsyms in
+       "") ;;
+       *.c)
+         # Discover the nlist of each of the dlfiles.
+         nlist="$output_objdir/${outputname}.nm"
+
+         $show "$rm $nlist ${nlist}S ${nlist}T"
+         $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+         # Parse the name list into a source file.
+         $show "creating $output_objdir/$dlsyms"
+
+         test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+         if test "$dlself" = yes; then
+           $show "generating symbol list for \`$output'"
+
+           test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+           # Add our own program objects to the symbol list.
+           progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+           for arg in $progfiles; do
+             $show "extracting global C symbols from \`$arg'"
+             $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+           done
+
+           if test -n "$exclude_expsyms"; then
+             $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           if test -n "$export_symbols_regex"; then
+             $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           # Prepare the list of exported symbols
+           if test -z "$export_symbols"; then
+             export_symbols="$output_objdir/$outputname.exp"
+             $run $rm $export_symbols
+             $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+              case $host in
+              *cygwin* | *mingw* )
+               $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+               $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
+           else
+             $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+             $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+             $run eval 'mv "$nlist"T "$nlist"'
+              case $host in
+              *cygwin* | *mingw* )
+               $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+               $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
+           fi
+         fi
+
+         for arg in $dlprefiles; do
+           $show "extracting global C symbols from \`$arg'"
+           name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+           $run eval '$echo ": $name " >> "$nlist"'
+           $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+         done
+
+         if test -z "$run"; then
+           # Make sure we have at least an empty file.
+           test -f "$nlist" || : > "$nlist"
+
+           if test -n "$exclude_expsyms"; then
+             $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+             $mv "$nlist"T "$nlist"
+           fi
+
+           # Try sorting and uniquifying the output.
+           if grep -v "^: " < "$nlist" |
+               if sort -k 3 </dev/null >/dev/null 2>&1; then
+                 sort -k 3
+               else
+                 sort +2
+               fi |
+               uniq > "$nlist"S; then
+             :
+           else
+             grep -v "^: " < "$nlist" > "$nlist"S
+           fi
+
+           if test -f "$nlist"S; then
+             eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+           else
+             $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+           fi
+
+           $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+           case $host in
+           *cygwin* | *mingw* )
+         $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs */
+struct {
+"
+             ;;
+           * )
+         $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+             ;;
+           esac
+
+
+         $echo >> "$output_objdir/$dlsyms" "\
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+           eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+           $echo >> "$output_objdir/$dlsyms" "\
+  {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+         fi
+
+         pic_flag_for_symtable=
+         case $host in
+         # compiling the symbol table file with pic_flag works around
+         # a FreeBSD bug that causes programs to crash when -lm is
+         # linked before any other PIC object.  But we must not use
+         # pic_flag when linking with -static.  The problem exists in
+         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+         *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+           esac;;
+         *-*-hpux*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag";;
+           esac
+         esac
+
+         # Now compile the dynamic symbol file.
+         $show "(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+         $run eval '(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+         # Clean up the generated files.
+         $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+         $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+         # Transform the symbol file into the correct name.
+          case $host in
+          *cygwin* | *mingw* )
+            if test -f "$output_objdir/${outputname}.def" ; then
+              compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+              finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            else
+              compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+              finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+             fi
+            ;;
+          * )
+            compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            ;;
+          esac
+         ;;
+       *)
+         $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+      else
+       # We keep going just in case the user didn't refer to
+       # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+       # really was required.
+
+       # Nullify the symbol file.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+      fi
+
+      if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+       # Replace the output file specification.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP`
+       link_command="$compile_command$compile_rpath"
+
+       # We have no uninstalled library dependencies, so finalize right now.
+       $show "$link_command"
+       $run eval "$link_command"
+       exit_status=$?
+
+       # Delete the generated files.
+       if test -n "$dlsyms"; then
+         $show "$rm $output_objdir/${outputname}S.${objext}"
+         $run $rm "$output_objdir/${outputname}S.${objext}"
+       fi
+
+       exit $exit_status
+      fi
+
+      if test -n "$shlibpath_var"; then
+       # We should set the shlibpath_var
+       rpath=
+       for dir in $temp_rpath; do
+         case $dir in
+         [\\/]* | [A-Za-z]:[\\/]*)
+           # Absolute path.
+           rpath="$rpath$dir:"
+           ;;
+         *)
+           # Relative path: add a thisdir entry.
+           rpath="$rpath\$thisdir/$dir:"
+           ;;
+         esac
+       done
+       temp_rpath="$rpath"
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+       if test -n "$perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+       if test -n "$finalize_perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $finalize_perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+      fi
+
+      if test "$no_install" = yes; then
+       # We don't need to create a wrapper script.
+       link_command="$compile_var$compile_command$compile_rpath"
+       # Replace the output file specification.
+       link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       # Delete the old output file.
+       $run $rm $output
+       # Link the executable and exit
+       $show "$link_command"
+       $run eval "$link_command" || exit $?
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+       # Fast installation is not supported
+       link_command="$compile_var$compile_command$compile_rpath"
+       relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+       $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+       $echo "$modename: \`$output' will be relinked during installation" 1>&2
+      else
+       if test "$fast_install" != no; then
+         link_command="$finalize_var$compile_command$finalize_rpath"
+         if test "$fast_install" = yes; then
+           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP`
+         else
+           # fast_install is set to needless
+           relink_command=
+         fi
+       else
+         link_command="$compile_var$compile_command$compile_rpath"
+         relink_command="$finalize_var$finalize_command$finalize_rpath"
+       fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      $show "$link_command"
+      $run eval "$link_command" || exit $?
+
+      # Now create the wrapper script.
+      $show "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+       # Preserve any variables that may affect compiler behavior
+       for var in $variables_saved_for_relink; do
+         if eval test -z \"\${$var+set}\"; then
+           relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+         elif eval var_value=\$$var; test -z "$var_value"; then
+           relink_command="$var=; export $var; $relink_command"
+         else
+           var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+           relink_command="$var=\"$var_value\"; export $var; $relink_command"
+         fi
+       done
+       relink_command="(cd `pwd`; $relink_command)"
+       relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+      fi
+
+      # Quote $echo for shipping.
+      if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+       case $progpath in
+       [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+       *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+       esac
+       qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+       qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if our run command is non-null.
+      if test -z "$run"; then
+       # win32 will think the script is a binary if it has
+       # a .exe suffix, so we strip it off here.
+       case $output in
+         *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+       esac
+       # test for cygwin because mv fails w/o .exe extensions
+       case $host in
+         *cygwin*)
+           exeext=.exe
+           outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+         *) exeext= ;;
+       esac
+       case $host in
+         *cygwin* | *mingw* )
+            output_name=`basename $output`
+            output_path=`dirname $output`
+            cwrappersource="$output_path/$objdir/lt-$output_name.c"
+            cwrapper="$output_path/$output_name.exe"
+            $rm $cwrappersource $cwrapper
+            trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+           cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "/bin/sh $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+           cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS.  */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int    check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  DEBUG("(main) argv[0]      : %s\n",argv[0]);
+  DEBUG("(main) program_name : %s\n",program_name);
+  newargz = XMALLOC(char *, argc+2);
+EOF
+
+            cat >> $cwrappersource <<EOF
+  newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+            cat >> $cwrappersource <<"EOF"
+  newargz[1] = find_executable(argv[0]);
+  if (newargz[1] == NULL)
+    lt_fatal("Couldn't find %s", argv[0]);
+  DEBUG("(main) found exe at : %s\n",newargz[1]);
+  /* we know the script has the same name, without the .exe */
+  /* so make sure newargz[1] doesn't end in .exe */
+  strendzap(newargz[1],".exe");
+  for (i = 1; i < argc; i++)
+    newargz[i+1] = xstrdup(argv[i]);
+  newargz[argc+1] = NULL;
+
+  for (i=0; i<argc+1; i++)
+  {
+    DEBUG("(main) newargz[%d]   : %s\n",i,newargz[i]);
+    ;
+  }
+
+EOF
+
+            case $host_os in
+              mingw*)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",(char const **)newargz);
+EOF
+              ;;
+              *)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",newargz);
+EOF
+              ;;
+            esac
+
+            cat >> $cwrappersource <<"EOF"
+  return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+  void * p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable(const char * path)
+{
+  struct stat st;
+
+  DEBUG("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0) &&
+      (
+        /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+       ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+       ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+       ((st.st_mode & S_IXUSR) == S_IXUSR))
+      )
+    return 1;
+  else
+    return 0;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+  int has_slash = 0;
+  const char* p;
+  const char* p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char* concat_name;
+
+  DEBUG("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+  {
+    concat_name = xstrdup (wrapper);
+    if (check_executable(concat_name))
+      return concat_name;
+    XFREE(concat_name);
+  }
+  else
+  {
+#endif
+    if (IS_DIR_SEPARATOR (wrapper[0]))
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable(concat_name))
+        return concat_name;
+      XFREE(concat_name);
+    }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+    {
+      has_slash = 1;
+      break;
+    }
+  if (!has_slash)
+  {
+    /* no slashes; search PATH */
+    const char* path = getenv ("PATH");
+    if (path != NULL)
+    {
+      for (p = path; *p; p = p_next)
+      {
+        const char* q;
+        size_t p_len;
+        for (q = p; *q; q++)
+          if (IS_PATH_SEPARATOR(*q))
+            break;
+        p_len = q - p;
+        p_next = (*q == '\0' ? q : q + 1);
+        if (p_len == 0)
+        {
+          /* empty path: current directory */
+          if (getcwd (tmp, LT_PATHMAX) == NULL)
+            lt_fatal ("getcwd failed");
+          tmp_len = strlen(tmp);
+          concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, tmp, tmp_len);
+          concat_name[tmp_len] = '/';
+          strcpy (concat_name + tmp_len + 1, wrapper);
+        }
+        else
+        {
+          concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, p, p_len);
+          concat_name[p_len] = '/';
+          strcpy (concat_name + p_len + 1, wrapper);
+        }
+        if (check_executable(concat_name))
+          return concat_name;
+        XFREE(concat_name);
+      }
+    }
+    /* not found in PATH; assume curdir */
+  }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen(tmp);
+  concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable(concat_name))
+    return concat_name;
+  XFREE(concat_name);
+  return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert(str != NULL);
+  assert(pat != NULL);
+
+  len = strlen(str);
+  patlen = strlen(pat);
+
+  if (patlen <= len)
+  {
+    str += len - patlen;
+    if (strcmp(str, pat) == 0)
+      *str = '\0';
+  }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+          const char * message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+EOF
+          # we should really use a build-platform specific compiler
+          # here, but OTOH, the wrappers (shell script and this C one)
+          # are only useful if you want to execute the "real" binary.
+          # Since the "real" binary is built for $host, then this
+          # wrapper might as well be built for $host, too.
+          $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+          ;;
+        esac
+        $rm $output
+        trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+       $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variable:
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$echo are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    echo=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$echo will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+       $echo >> $output "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+       if test "$fast_install" = yes; then
+         $echo >> $output "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" || \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $mkdir \"\$progdir\"
+    else
+      $rm \"\$progdir/\$file\"
+    fi"
+
+         $echo >> $output "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+       $echo \"\$relink_command_output\" >&2
+       $rm \"\$progdir/\$file\"
+       exit $EXIT_FAILURE
+      fi
+    fi
+
+    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $rm \"\$progdir/\$program\";
+      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $rm \"\$progdir/\$file\"
+  fi"
+       else
+         $echo >> $output "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+       fi
+
+       $echo >> $output "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+       # Export our shlibpath_var if we have one.
+       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+         $echo >> $output "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+       fi
+
+       # fixup the dll searchpath if we need to.
+       if test -n "$dllsearchpath"; then
+         $echo >> $output "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+       fi
+
+       $echo >> $output "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+       case $host in
+       # Backslashes separate directories on plain windows
+       *-*-mingw | *-*-os2*)
+         $echo >> $output "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+         ;;
+
+       *)
+         $echo >> $output "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+         ;;
+       esac
+       $echo >> $output "\
+      \$echo \"\$0: cannot exec \$program \$*\"
+      exit $EXIT_FAILURE
+    fi
+  else
+    # The program doesn't exist.
+    \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$echo \"This script is just a wrapper for \$program.\" 1>&2
+    $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit $EXIT_FAILURE
+  fi
+fi\
+"
+       chmod +x $output
+      fi
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+       oldobjs="$libobjs_save"
+       addlibs="$convenience"
+       build_libtool_libs=no
+      else
+       if test "$build_libtool_libs" = module; then
+         oldobjs="$libobjs_save"
+         build_libtool_libs=no
+       else
+         oldobjs="$old_deplibs $non_pic_objects"
+       fi
+       addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+       gentop="$output_objdir/${outputname}x"
+       generated="$generated $gentop"
+
+       func_extract_archives $gentop $addlibs
+       oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       cmds=$old_archive_from_new_cmds
+      else
+       # POSIX demands no paths to be encoded in archives.  We have
+       # to avoid creating archives with duplicate basenames if we
+       # might have to extract them afterwards, e.g., when creating a
+       # static archive out of a convenience library, or when linking
+       # the entirety of a libtool archive into another (currently
+       # not supported by libtool).
+       if (for obj in $oldobjs
+           do
+             $echo "X$obj" | $Xsed -e 's%^.*/%%'
+           done | sort | sort -uc >/dev/null 2>&1); then
+         :
+       else
+         $echo "copying selected object files to avoid basename conflicts..."
+
+         if test -z "$gentop"; then
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           $show "${rm}r $gentop"
+           $run ${rm}r "$gentop"
+           $show "$mkdir $gentop"
+           $run $mkdir "$gentop"
+           exit_status=$?
+           if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+             exit $exit_status
+           fi
+         fi
+
+         save_oldobjs=$oldobjs
+         oldobjs=
+         counter=1
+         for obj in $save_oldobjs
+         do
+           objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+           case " $oldobjs " in
+           " ") oldobjs=$obj ;;
+           *[\ /]"$objbase "*)
+             while :; do
+               # Make sure we don't pick an alternate name that also
+               # overlaps.
+               newobj=lt$counter-$objbase
+               counter=`expr $counter + 1`
+               case " $oldobjs " in
+               *[\ /]"$newobj "*) ;;
+               *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+               esac
+             done
+             $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+             $run ln "$obj" "$gentop/$newobj" ||
+             $run cp "$obj" "$gentop/$newobj"
+             oldobjs="$oldobjs $gentop/$newobj"
+             ;;
+           *) oldobjs="$oldobjs $obj" ;;
+           esac
+         done
+       fi
+
+       eval cmds=\"$old_archive_cmds\"
+
+       if len=`expr "X$cmds" : ".*"` &&
+            test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         cmds=$old_archive_cmds
+       else
+         # the command line is too long to link in one step, link in parts
+         $echo "using piecewise archive linking..."
+         save_RANLIB=$RANLIB
+         RANLIB=:
+         objlist=
+         concat_cmds=
+         save_oldobjs=$oldobjs
+
+         # Is there a better way of finding the last object in the list?
+         for obj in $save_oldobjs
+         do
+           last_oldobj=$obj
+         done
+         for obj in $save_oldobjs
+         do
+           oldobjs="$objlist $obj"
+           objlist="$objlist $obj"
+           eval test_cmds=\"$old_archive_cmds\"
+           if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+              test "$len" -le "$max_cmd_len"; then
+             :
+           else
+             # the above command should be used before it gets too long
+             oldobjs=$objlist
+             if test "$obj" = "$last_oldobj" ; then
+               RANLIB=$save_RANLIB
+             fi
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+             objlist=
+           fi
+         done
+         RANLIB=$save_RANLIB
+         oldobjs=$objlist
+         if test "X$oldobjs" = "X" ; then
+           eval cmds=\"\$concat_cmds\"
+         else
+           eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+         fi
+       fi
+      fi
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+        eval cmd=\"$cmd\"
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$generated"; then
+      $show "${rm}r$generated"
+      $run ${rm}r$generated
+    fi
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      $show "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+       if eval test -z \"\${$var+set}\"; then
+         relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+       elif eval var_value=\$$var; test -z "$var_value"; then
+         relink_command="$var=; export $var; $relink_command"
+       else
+         var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+         relink_command="$var=\"$var_value\"; export $var; $relink_command"
+       fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+      if test "$hardcode_automatic" = yes ; then
+       relink_command=
+      fi
+
+
+      # Only create the output if not a dry run.
+      if test -z "$run"; then
+       for installed in no yes; do
+         if test "$installed" = yes; then
+           if test -z "$install_libdir"; then
+             break
+           fi
+           output="$output_objdir/$outputname"i
+           # Replace all uninstalled libtool libraries with the installed ones
+           newdependency_libs=
+           for deplib in $dependency_libs; do
+             case $deplib in
+             *.la)
+               name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+               if test -z "$libdir"; then
+                 $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+                 exit $EXIT_FAILURE
+               fi
+               newdependency_libs="$newdependency_libs $libdir/$name"
+               ;;
+             *) newdependency_libs="$newdependency_libs $deplib" ;;
+             esac
+           done
+           dependency_libs="$newdependency_libs"
+           newdlfiles=
+           for lib in $dlfiles; do
+             name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+             eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+             if test -z "$libdir"; then
+               $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+               exit $EXIT_FAILURE
+             fi
+             newdlfiles="$newdlfiles $libdir/$name"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+             eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+             if test -z "$libdir"; then
+               $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+               exit $EXIT_FAILURE
+             fi
+             newdlprefiles="$newdlprefiles $libdir/$name"
+           done
+           dlprefiles="$newdlprefiles"
+         else
+           newdlfiles=
+           for lib in $dlfiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             newdlfiles="$newdlfiles $abs"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             newdlprefiles="$newdlprefiles $abs"
+           done
+           dlprefiles="$newdlprefiles"
+         fi
+         $rm $output
+         # place dlname in correct position for cygwin
+         tdlname=$dlname
+         case $host,$output,$installed,$module,$dlname in
+           *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+         esac
+         $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+         if test "$installed" = no && test "$need_relink" = yes; then
+           $echo >> $output "\
+relink_command=\"$relink_command\""
+         fi
+       done
+      fi
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+      $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool install mode
+  install)
+    modename="$modename: install"
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $echo "X$nonopt" | grep shtool > /dev/null; then
+      # Aesthetically quote it.
+      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$arg "
+      arg="$1"
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+    case $arg in
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*|"")
+      arg="\"$arg\""
+      ;;
+    esac
+    install_prog="$install_prog$arg"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+       files="$files $dest"
+       dest=$arg
+       continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f) 
+       case " $install_prog " in
+       *[\\\ /]cp\ *) ;;
+       *) prev=$arg ;;
+       esac
+       ;;
+      -g | -m | -o) prev=$arg ;;
+      -s)
+       stripme=" -s"
+       continue
+       ;;
+      -*)
+       ;;
+      *)
+       # If the previous option needed an argument, then skip it.
+       if test -n "$prev"; then
+         prev=
+       else
+         dest=$arg
+         continue
+       fi
+       ;;
+      esac
+
+      # Aesthetically quote the argument.
+      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$install_prog $arg"
+    done
+
+    if test -z "$install_prog"; then
+      $echo "$modename: you must specify an install program" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prev' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+       $echo "$modename: no file or destination specified" 1>&2
+      else
+       $echo "$modename: you must specify a destination" 1>&2
+      fi
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Strip any trailing slash from the destination.
+    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$destdir" = "X$dest" && destdir=.
+      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files
+      if test "$#" -gt 2; then
+       $echo "$modename: \`$dest' is not a directory" 1>&2
+       $echo "$help" 1>&2
+       exit $EXIT_FAILURE
+      fi
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+       case $file in
+       *.lo) ;;
+       *)
+         $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+       # Do the static libraries later.
+       staticlibs="$staticlibs $file"
+       ;;
+
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       library_names=
+       old_library=
+       relink_command=
+       # If there is no directory component, then add one.
+       case $file in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Add the libdir to current_libdirs if it is the destination.
+       if test "X$destdir" = "X$libdir"; then
+         case "$current_libdirs " in
+         *" $libdir "*) ;;
+         *) current_libdirs="$current_libdirs $libdir" ;;
+         esac
+       else
+         # Note the libdir as a future libdir.
+         case "$future_libdirs " in
+         *" $libdir "*) ;;
+         *) future_libdirs="$future_libdirs $libdir" ;;
+         esac
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+       test "X$dir" = "X$file/" && dir=
+       dir="$dir$objdir"
+
+       if test -n "$relink_command"; then
+         # Determine the prefix the user has applied to our future dir.
+         inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+         # Don't allow the user to place us outside of our expected
+         # location b/c this prevents finding dependent libraries that
+         # are installed to the same prefix.
+         # At present, this check doesn't affect windows .dll's that
+         # are installed into $libdir/../bin (currently, that works fine)
+         # but it's something to keep an eye on.
+         if test "$inst_prefix_dir" = "$destdir"; then
+           $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+           exit $EXIT_FAILURE
+         fi
+
+         if test -n "$inst_prefix_dir"; then
+           # Stick the inst_prefix_dir data into the link command.
+           relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP`
+         else
+           relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
+         fi
+
+         $echo "$modename: warning: relinking \`$file'" 1>&2
+         $show "$relink_command"
+         if $run eval "$relink_command"; then :
+         else
+           $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+           exit $EXIT_FAILURE
+         fi
+       fi
+
+       # See the names of the shared library.
+       set dummy $library_names
+       if test -n "$2"; then
+         realname="$2"
+         shift
+         shift
+
+         srcname="$realname"
+         test -n "$relink_command" && srcname="$realname"T
+
+         # Install the shared library and build the symlinks.
+         $show "$install_prog $dir/$srcname $destdir/$realname"
+         $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+         if test -n "$stripme" && test -n "$striplib"; then
+           $show "$striplib $destdir/$realname"
+           $run eval "$striplib $destdir/$realname" || exit $?
+         fi
+
+         if test "$#" -gt 0; then
+           # Delete the old symlinks, and create new ones.
+           # Try `ln -sf' first, because the `ln' binary might depend on
+           # the symlink we replace!  Solaris /bin/ln does not understand -f,
+           # so we also need to try rm && ln -s.
+           for linkname
+           do
+             if test "$linkname" != "$realname"; then
+                $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+                $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+             fi
+           done
+         fi
+
+         # Do each command in the postinstall commands.
+         lib="$destdir/$realname"
+         cmds=$postinstall_cmds
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           eval cmd=\"$cmd\"
+           $show "$cmd"
+           $run eval "$cmd" || {
+             lt_exit=$?
+
+             # Restore the uninstalled library and exit
+             if test "$mode" = relink; then
+               $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+             fi
+
+             exit $lt_exit
+           }
+         done
+         IFS="$save_ifs"
+       fi
+
+       # Install the pseudo-library for information purposes.
+       name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+       instname="$dir/$name"i
+       $show "$install_prog $instname $destdir/$name"
+       $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+       # Maybe install the static library, too.
+       test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+       ;;
+
+      *.lo)
+       # Install (i.e. copy) a libtool object.
+
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # Deduce the name of the destination old-style object file.
+       case $destfile in
+       *.lo)
+         staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+         ;;
+       *.$objext)
+         staticdest="$destfile"
+         destfile=
+         ;;
+       *)
+         $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       # Install the libtool object if requested.
+       if test -n "$destfile"; then
+         $show "$install_prog $file $destfile"
+         $run eval "$install_prog $file $destfile" || exit $?
+       fi
+
+       # Install the old object if enabled.
+       if test "$build_old_libs" = yes; then
+         # Deduce the name of the old-style object file.
+         staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+         $show "$install_prog $staticobj $staticdest"
+         $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+       fi
+       exit $EXIT_SUCCESS
+       ;;
+
+      *)
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # If the file is missing, and there is a .exe on the end, strip it
+       # because it is most likely a libtool script we actually want to
+       # install
+       stripped_ext=""
+       case $file in
+         *.exe)
+           if test ! -f "$file"; then
+             file=`$echo $file|${SED} 's,.exe$,,'`
+             stripped_ext=".exe"
+           fi
+           ;;
+       esac
+
+       # Do a test to see if this is really a libtool program.
+       case $host in
+       *cygwin*|*mingw*)
+           wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+           ;;
+       *)
+           wrapper=$file
+           ;;
+       esac
+       if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+         notinst_deplibs=
+         relink_command=
+
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
+         # If there is no directory component, then add one.
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
+         esac
+
+         # Check the variables that should have been set.
+         if test -z "$notinst_deplibs"; then
+           $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+
+         finalize=yes
+         for lib in $notinst_deplibs; do
+           # Check to see that each library is installed.
+           libdir=
+           if test -f "$lib"; then
+             # If there is no directory component, then add one.
+             case $lib in
+             */* | *\\*) . $lib ;;
+             *) . ./$lib ;;
+             esac
+           fi
+           libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+           if test -n "$libdir" && test ! -f "$libfile"; then
+             $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+             finalize=no
+           fi
+         done
+
+         relink_command=
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
+         # If there is no directory component, then add one.
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
+         esac
+
+         outputname=
+         if test "$fast_install" = no && test -n "$relink_command"; then
+           if test "$finalize" = yes && test -z "$run"; then
+             tmpdir=`func_mktempdir`
+             file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+             outputname="$tmpdir/$file"
+             # Replace the output file specification.
+             relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP`
+
+             $show "$relink_command"
+             if $run eval "$relink_command"; then :
+             else
+               $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+               ${rm}r "$tmpdir"
+               continue
+             fi
+             file="$outputname"
+           else
+             $echo "$modename: warning: cannot relink \`$file'" 1>&2
+           fi
+         else
+           # Install the binary that we compiled earlier.
+           file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+         fi
+       fi
+
+       # remove .exe since cygwin /usr/bin/install will append another
+       # one anyway 
+       case $install_prog,$host in
+       */usr/bin/install*,*cygwin*)
+         case $file:$destfile in
+         *.exe:*.exe)
+           # this is ok
+           ;;
+         *.exe:*)
+           destfile=$destfile.exe
+           ;;
+         *:*.exe)
+           destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+           ;;
+         esac
+         ;;
+       esac
+       $show "$install_prog$stripme $file $destfile"
+       $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+       test -n "$outputname" && ${rm}r "$tmpdir"
+       ;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      $show "$install_prog $file $oldlib"
+      $run eval "$install_prog \$file \$oldlib" || exit $?
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+       $show "$old_striplib $oldlib"
+       $run eval "$old_striplib $oldlib" || exit $?
+      fi
+
+      # Do each command in the postinstall commands.
+      cmds=$old_postinstall_cmds
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       eval cmd=\"$cmd\"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$future_libdirs"; then
+      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+    fi
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      test -n "$run" && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+    ;;
+
+  # libtool finish mode
+  finish)
+    modename="$modename: finish"
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+       libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+       if test -n "$finish_cmds"; then
+         # Do each command in the finish commands.
+         cmds=$finish_cmds
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           eval cmd=\"$cmd\"
+           $show "$cmd"
+           $run eval "$cmd" || admincmds="$admincmds
+       $cmd"
+         done
+         IFS="$save_ifs"
+       fi
+       if test -n "$finish_eval"; then
+         # Do the single finish_eval.
+         eval cmds=\"$finish_eval\"
+         $run eval "$cmds" || admincmds="$admincmds
+       $cmds"
+       fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    test "$show" = : && exit $EXIT_SUCCESS
+
+    $echo "X----------------------------------------------------------------------" | $Xsed
+    $echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $echo "   $libdir"
+    done
+    $echo
+    $echo "If you ever happen to want to link against installed libraries"
+    $echo "in a given directory, LIBDIR, you must either use libtool, and"
+    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $echo "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $echo "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $echo
+    $echo "See any operating system documentation about shared libraries for"
+    $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    $echo "X----------------------------------------------------------------------" | $Xsed
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool execute mode
+  execute)
+    modename="$modename: execute"
+
+    # The first argument is the command name.
+    cmd="$nonopt"
+    if test -z "$cmd"; then
+      $echo "$modename: you must specify a COMMAND" 1>&2
+      $echo "$help"
+      exit $EXIT_FAILURE
+    fi
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      if test ! -f "$file"; then
+       $echo "$modename: \`$file' is not a file" 1>&2
+       $echo "$help" 1>&2
+       exit $EXIT_FAILURE
+      fi
+
+      dir=
+      case $file in
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # Read the libtool library.
+       dlname=
+       library_names=
+
+       # If there is no directory component, then add one.
+       case $file in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Skip this library if it cannot be dlopened.
+       if test -z "$dlname"; then
+         # Warn if it was a shared library.
+         test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+         continue
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+
+       if test -f "$dir/$objdir/$dlname"; then
+         dir="$dir/$objdir"
+       else
+         if test ! -f "$dir/$dlname"; then
+           $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+       fi
+       ;;
+
+      *.lo)
+       # Just add the directory containing the .lo file.
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+       ;;
+
+      *)
+       $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+       continue
+       ;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+       eval "$shlibpath_var=\"\$dir\""
+      else
+       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+       # Do a test to see if this is really a libtool program.
+       if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         # If there is no directory component, then add one.
+         case $file in
+         */* | *\\*) . $file ;;
+         *) . ./$file ;;
+         esac
+
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       fi
+       ;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+      args="$args \"$file\""
+    done
+
+    if test -z "$run"; then
+      if test -n "$shlibpath_var"; then
+       # Export the shlibpath_var.
+       eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+       eval "if test \"\${save_$lt_var+set}\" = set; then
+               $lt_var=\$save_$lt_var; export $lt_var
+             fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+       eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+       $echo "export $shlibpath_var"
+      fi
+      $echo "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+    ;;
+
+  # libtool clean and uninstall mode
+  clean | uninstall)
+    modename="$modename: $mode"
+    rm="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) rm="$rm $arg"; rmforce=yes ;;
+      -*) rm="$rm $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    if test -z "$rm"; then
+      $echo "$modename: you must specify an RM program" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$dir" = "X$file"; then
+       dir=.
+       objdir="$origobjdir"
+      else
+       objdir="$dir/$origobjdir"
+      fi
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+       case " $rmdirs " in
+         *" $objdir "*) ;;
+         *) rmdirs="$rmdirs $objdir" ;;
+       esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if (test -L "$file") >/dev/null 2>&1 \
+       || (test -h "$file") >/dev/null 2>&1 \
+       || test -f "$file"; then
+       :
+      elif test -d "$file"; then
+       exit_status=1
+       continue
+      elif test "$rmforce" = yes; then
+       continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+       # Possibly a libtool archive, so verify it.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         . $dir/$name
+
+         # Delete the libtool libraries and symlinks.
+         for n in $library_names; do
+           rmfiles="$rmfiles $objdir/$n"
+         done
+         test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+         case "$mode" in
+         clean)
+           case "  $library_names " in
+           # "  " in the beginning catches empty $dlname
+           *" $dlname "*) ;;
+           *) rmfiles="$rmfiles $objdir/$dlname" ;;
+           esac
+            test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+           ;;
+         uninstall)
+           if test -n "$library_names"; then
+             # Do each command in the postuninstall commands.
+             cmds=$postuninstall_cmds
+             save_ifs="$IFS"; IFS='~'
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd"
+               if test "$?" -ne 0 && test "$rmforce" != yes; then
+                 exit_status=1
+               fi
+             done
+             IFS="$save_ifs"
+           fi
+
+           if test -n "$old_library"; then
+             # Do each command in the old_postuninstall commands.
+             cmds=$old_postuninstall_cmds
+             save_ifs="$IFS"; IFS='~'
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd"
+               if test "$?" -ne 0 && test "$rmforce" != yes; then
+                 exit_status=1
+               fi
+             done
+             IFS="$save_ifs"
+           fi
+           # FIXME: should reinstall the best remaining shared library.
+           ;;
+         esac
+       fi
+       ;;
+
+      *.lo)
+       # Possibly a libtool object, so verify it.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+         # Read the .lo file
+         . $dir/$name
+
+         # Add PIC object to the list of files to remove.
+         if test -n "$pic_object" \
+            && test "$pic_object" != none; then
+           rmfiles="$rmfiles $dir/$pic_object"
+         fi
+
+         # Add non-PIC object to the list of files to remove.
+         if test -n "$non_pic_object" \
+            && test "$non_pic_object" != none; then
+           rmfiles="$rmfiles $dir/$non_pic_object"
+         fi
+       fi
+       ;;
+
+      *)
+       if test "$mode" = clean ; then
+         noexename=$name
+         case $file in
+         *.exe)
+           file=`$echo $file|${SED} 's,.exe$,,'`
+           noexename=`$echo $name|${SED} 's,.exe$,,'`
+           # $file with .exe has already been added to rmfiles,
+           # add $file without .exe
+           rmfiles="$rmfiles $file"
+           ;;
+         esac
+         # Do a test to see if this is a libtool program.
+         if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+           relink_command=
+           . $dir/$noexename
+
+           # note $name still contains .exe if it was in $file originally
+           # as does the version of $file that was added into $rmfiles
+           rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+           if test "$fast_install" = yes && test -n "$relink_command"; then
+             rmfiles="$rmfiles $objdir/lt-$name"
+           fi
+           if test "X$noexename" != "X$name" ; then
+             rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+           fi
+         fi
+       fi
+       ;;
+      esac
+      $show "$rm $rmfiles"
+      $run $rm $rmfiles || exit_status=1
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+       $show "rmdir $dir"
+       $run rmdir $dir >/dev/null 2>&1
+      fi
+    done
+
+    exit $exit_status
+    ;;
+
+  "")
+    $echo "$modename: you must specify a MODE" 1>&2
+    $echo "$generic_help" 1>&2
+    exit $EXIT_FAILURE
+    ;;
+  esac
+
+  if test -z "$exec_cmd"; then
+    $echo "$modename: invalid operation mode \`$mode'" 1>&2
+    $echo "$generic_help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+  eval exec $exec_cmd
+  exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+    --config          show all configuration variables
+    --debug           enable verbose shell tracing
+-n, --dry-run         display commands without modifying any files
+    --features        display basic configuration information and exit
+    --finish          same as \`--mode=finish'
+    --help            display this help message and exit
+    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
+    --quiet           same as \`--silent'
+    --silent          don't print informational messages
+    --tag=TAG         use configuration variables from tag TAG
+    --version         print version information
+
+MODE must be one of the following:
+
+      clean           remove files from the build directory
+      compile         compile a source file into a libtool object
+      execute         automatically set library path, then run a program
+      finish          complete the installation of libtool libraries
+      install         install libraries or executables
+      link            create a library or an executable
+      uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+  exit $EXIT_SUCCESS
+  ;;
+
+clean)
+  $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+compile)
+  $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -static           always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+  ;;
+
+execute)
+  $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+  ;;
+
+finish)
+  $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+  ;;
+
+install)
+  $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+  ;;
+
+link)
+  $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+  ;;
+
+uninstall)
+  $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+*)
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$help" 1>&2
+  exit $EXIT_FAILURE
+  ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/dist/nvi/dist/m4/gtk.m4 b/dist/nvi/dist/m4/gtk.m4
new file mode 100644 (file)
index 0000000..b8cf402
--- /dev/null
@@ -0,0 +1,194 @@
+# Configure paths for GTK+
+# Owen Taylor     97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl 
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[  --with-gtk-prefix=PFX   Prefix where GTK is installed (optional)],
+            gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[  --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+            gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [  --disable-gtktest       Do not try to compile and run a test GTK program],
+                   , enable_gtktest=yes)
+
+  for module in . $4
+  do
+      case "$module" in
+         gthread) 
+             gtk_config_args="$gtk_config_args gthread"
+         ;;
+      esac
+  done
+
+  if test x$gtk_config_exec_prefix != x ; then
+     gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+     fi
+  fi
+  if test x$gtk_config_prefix != x ; then
+     gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+     fi
+  fi
+
+  AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+  min_gtk_version=ifelse([$1], ,0.99.7,$1)
+  AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+  no_gtk=""
+  if test "$GTK_CONFIG" = "no" ; then
+    no_gtk=yes
+  else
+    GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+    GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+    gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gtktest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GTK_CFLAGS"
+      LIBS="$GTK_LIBS $LIBS"
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+      rm -f conf.gtktest
+      AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtktest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtk_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtk_version");
+     exit(1);
+   }
+
+  if ((gtk_major_version != $gtk_config_major_version) ||
+      (gtk_minor_version != $gtk_config_minor_version) ||
+      (gtk_micro_version != $gtk_config_micro_version))
+    {
+      printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", 
+             $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+             gtk_major_version, gtk_minor_version, gtk_micro_version);
+      printf ("*** was found! If gtk-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+      printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+  else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+          (gtk_minor_version != GTK_MINOR_VERSION) ||
+           (gtk_micro_version != GTK_MICRO_VERSION))
+    {
+      printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+            GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+            gtk_major_version, gtk_minor_version, gtk_micro_version);
+    }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+  else
+    {
+      if ((gtk_major_version > major) ||
+        ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+        ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+               gtk_major_version, gtk_minor_version, gtk_micro_version);
+        printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+              major, minor, micro);
+        printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtk" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GTK_CONFIG" = "no" ; then
+       echo "*** The gtk-config script installed by GTK could not be found"
+       echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTK_CONFIG environment variable to the"
+       echo "*** full path to gtk-config."
+     else
+       if test -f conf.gtktest ; then
+        :
+       else
+          echo "*** Could not run GTK test program, checking why..."
+          CFLAGS="$CFLAGS $GTK_CFLAGS"
+          LIBS="$LIBS $GTK_LIBS"
+          AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+],      [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK or finding the wrong"
+          echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+         echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+          echo "***"
+          echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+          echo "*** came with the system with the command"
+          echo "***"
+          echo "***    rpm --erase --nodeps gtk gtk-devel" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+          echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTK_CFLAGS=""
+     GTK_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+  rm -f conf.gtktest
+])
diff --git a/dist/nvi/dist/missing b/dist/nvi/dist/missing
new file mode 100644 (file)
index 0000000..0a7fb5a
--- /dev/null
@@ -0,0 +1,283 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing 0.3 - GNU automake"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f y.tab.h ]; then
+       echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+        you modified a dependency of a manual page.  You may need the
+        \`Help2man' package in order for those modifications to take
+        effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+       file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+    fi
+    if [ -f "$file" ]; then
+       touch $file
+    else
+       test -z "$file" || exec >$file
+       echo ".ab help2man is required to generate this page"
+       exit 1
+    fi
+    ;;
+
+  makeinfo)
+    if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+       # We have makeinfo, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  tar)
+    shift
+    if test -n "$run"; then
+      echo 1>&2 "ERROR: \`tar' requires --run"
+      exit 1
+    fi
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar ${1+"$@"} && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar ${1+"$@"} && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+       case "$firstarg" in
+       *o*)
+           firstarg=`echo "$firstarg" | sed s/o//`
+           tar "$firstarg" ${1+"$@"} && exit 0
+           ;;
+       esac
+       case "$firstarg" in
+       *h*)
+           firstarg=`echo "$firstarg" | sed s/h//`
+           tar "$firstarg" ${1+"$@"} && exit 0
+           ;;
+       esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/dist/nvi/dist/mkinstalldirs b/dist/nvi/dist/mkinstalldirs
new file mode 100644 (file)
index 0000000..f35df97
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# Id: mkinstalldirs,v 8.3 2001/08/27 19:52:59 skimo Exp
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+         errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/dist/nvi/dist/pathnames.h.in b/dist/nvi/dist/pathnames.h.in
new file mode 100644 (file)
index 0000000..6ca0a05
--- /dev/null
@@ -0,0 +1,49 @@
+/* Id: pathnames.h.in,v 8.5 2000/04/21 21:26:21 skimo Exp (Berkeley) Date: 2000/04/21 21:26:21 */
+
+#ifndef        _PATH_BSHELL
+#define        _PATH_BSHELL    "@vi_cv_path_shell@"
+#endif
+
+#ifndef        _PATH_DB3
+#define        _PATH_DB3       "@vi_cv_path_db3@"
+#endif
+
+#ifndef        _PATH_EXRC
+#define        _PATH_EXRC      ".exrc"
+#endif
+
+#ifndef        _PATH_MSGCAT
+#define        _PATH_MSGCAT    "./"
+#endif
+
+#ifndef        _PATH_NEXRC
+#define        _PATH_NEXRC     ".nexrc"
+#endif
+
+#ifndef        _PATH_PRESERVE
+#define        _PATH_PRESERVE  "@vi_cv_path_preserve@"
+#endif
+
+#ifndef _PATH_SYSV_PTY
+#define        _PATH_SYSV_PTY  "/dev/ptmx"
+#endif
+
+#ifndef        _PATH_SENDMAIL
+#define        _PATH_SENDMAIL  "@vi_cv_path_sendmail@"
+#endif
+
+#ifndef        _PATH_SYSEXRC
+#define        _PATH_SYSEXRC   "/etc/vi.exrc"
+#endif
+
+#ifndef        _PATH_TAGS
+#define        _PATH_TAGS      "tags"
+#endif
+
+#ifndef        _PATH_TMP
+#define        _PATH_TMP       "/tmp"
+#endif
+
+#ifndef        _PATH_TTY
+#define        _PATH_TTY       "/dev/tty"
+#endif
diff --git a/dist/nvi/dist/port.h.in b/dist/nvi/dist/port.h.in
new file mode 100644 (file)
index 0000000..b1d05d1
--- /dev/null
@@ -0,0 +1,199 @@
+/* Id: port.h.in,v 8.15 2001/01/01 20:26:48 skimo Exp (Berkeley) Date: 2001/01/01 20:26:48 */
+
+/*
+ * Declare the basic types, if they aren't already declared.  Named and
+ * some system's db.h files protect them with __BIT_TYPES_DEFINED__.
+ */
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+@u_int8_decl@
+@int16_decl@
+@u_int16_decl@
+@int32_decl@
+@u_int32_decl@
+#endif
+
+@u_char_decl@
+@u_short_decl@
+@u_int_decl@
+@u_long_decl@
+
+/*
+ * XXX
+ * Handle function prototypes.  This steps on name space that vi doesn't
+ * control, but all of the other solutions are worse.
+ */
+#undef __P
+#if defined(__STDC__) || defined(__cplusplus)
+#define        __P(protos)     protos          /* ANSI C prototypes */
+#else
+#define        __P(protos)     ()              /* K&R C preprocessor */
+#endif
+
+/*
+ * XXX
+ * Some versions of System V changed the number of arguments to gettimeofday
+ * without changing the name.
+ */
+#ifdef HAVE_BROKEN_GETTIMEOFDAY
+#define        gettimeofday(tv, tz)    gettimeofday(tv)
+#endif
+
+/* 
+ * XXX
+ * If we don't have mmap, we fake it with read and write, but we'll
+ * still need the header information.
+ */
+#ifndef HAVE_SYS_MMAN_H
+#define        MAP_SHARED      1               /* share changes */
+#define        MAP_PRIVATE     2               /* changes are private */
+#define        PROT_READ       0x1             /* pages can be read */
+#define        PROT_WRITE      0x2             /* pages can be written */
+#define        PROT_EXEC       0x4             /* pages can be executed */
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 names for file descriptors.
+ */
+#ifndef STDERR_FILENO
+#define STDIN_FILENO   0               /* ANSI C #defines */
+#define STDOUT_FILENO  1
+#define STDERR_FILENO  2
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 names for seek settings.
+ */
+#ifndef SEEK_END
+#define        SEEK_SET        0               /* POSIX 1003.1 seek values */
+#define        SEEK_CUR        1
+#define        SEEK_END        2
+#endif
+
+/*
+ * Hack _POSIX_VDISABLE to \377 since Ultrix doesn't honor _POSIX_VDISABLE
+ * (treats it as ^@).  The symptom is that the ^@ keystroke immediately
+ * drops core.
+ */
+#ifdef HAVE_BROKEN_VDISABLE
+#undef _POSIX_VDISABLE
+#define        _POSIX_VDISABLE ((unsigned char)'\377')
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 tty disabling character.
+ */
+#ifndef _POSIX_VDISABLE
+#define        _POSIX_VDISABLE 0               /* Some systems used 0. */
+#endif
+
+/*
+ * XXX
+ * 4.4BSD extension to only set the software termios bits.
+ */
+#ifndef        TCSASOFT                        /* 4.4BSD extension. */
+#define        TCSASOFT        0
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 maximum path length.
+ */
+#ifndef MAXPATHLEN
+#ifdef PATH_MAX
+#define        MAXPATHLEN      PATH_MAX
+#else
+#define        MAXPATHLEN      1024
+#endif
+#endif
+
+/*
+ * XXX
+ * MIN, MAX, historically in <sys/param.h>
+ */
+#ifndef        MAX
+#define        MAX(_a,_b)      ((_a)<(_b)?(_b):(_a))
+#endif
+#ifndef        MIN
+#define        MIN(_a,_b)      ((_a)<(_b)?(_a):(_b))
+#endif
+
+/*
+ * XXX
+ * "DB" isn't always portable, and we want the private information.
+ */
+#define DB      L__DB
+#undef pgno_t                  /* IRIX has its own version. */
+#define        pgno_t  L__db_pgno_t
+
+/*
+ * XXX
+ * 4.4BSD extension to provide lock values in the open(2) call.
+ */
+#ifndef O_EXLOCK
+#define        O_EXLOCK        0
+#endif
+
+#ifndef O_SHLOCK
+#define        O_SHLOCK        0
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 bad file format errno.
+ */
+#ifndef EFTYPE
+#define        EFTYPE          EINVAL
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.2 RE length limit.
+ */
+#ifndef        _POSIX2_RE_DUP_MAX
+#define        _POSIX2_RE_DUP_MAX      255
+#endif
+
+/*
+ * XXX
+ * 4.4BSD extension to determine if a program dropped core from the exit
+ * status.
+ */
+#ifndef        WCOREDUMP
+#define        WCOREDUMP(a)    0
+#endif
+
+/*
+ * XXX
+ * Endian-ness of the machine.
+ */
+#if !defined(LITTLE_ENDIAN)
+#define        LITTLE_ENDIAN   1234
+#endif
+#if !defined(BIG_ENDIAN)
+#define        BIG_ENDIAN      4321
+#endif
+#if !defined(BYTE_ORDER)
+#if WORDS_BIGENDIAN == 1
+#define        BYTE_ORDER      BIG_ENDIAN
+#else
+#define        BYTE_ORDER      LITTLE_ENDIAN
+#endif
+#endif
+
+#ifndef HAVE_MEMCPY
+#define memcpy memmove
+#endif
+
+#ifdef NEED_FPRINTF_PROTO
+extern  int     fprintf( FILE *, const char *, ... );
+#endif
+
+#ifdef HAVE_PTHREAD
+#define VI_DB_THREAD DB_THREAD
+#else
+#define VI_DB_THREAD 0
+#endif
diff --git a/dist/nvi/dist/recover.in b/dist/nvi/dist/recover.in
new file mode 100644 (file)
index 0000000..8a5eaa7
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/sh -
+#
+#      Id: recover.in,v 8.9 2001/08/30 13:59:23 skimo Exp (Berkeley) Date: 2001/08/30 13:59:23
+#
+# Script to recover nvi edit sessions.
+
+RECDIR="@vi_cv_path_preserve@"
+SENDMAIL="@vi_cv_path_sendmail@"
+
+echo 'Recovering nvi editor sessions.'
+
+# Check editor backup files.
+vibackup=`echo $RECDIR/vi.*`
+if [ "$vibackup" != "$RECDIR/vi.*" ]; then
+       for i in $vibackup; do
+               # Only test files that are readable.
+               if test ! -r $i; then
+                       continue
+               fi
+
+               INUSE="@INUSE@"
+               if test "$INUSE" && $INUSE; then
+                       continue
+               fi
+
+               # Unmodified nvi editor backup files either have the
+               # execute bit set or are zero length.  Delete them.
+               if test -x $i -o ! -s $i; then
+                       rm $i
+               fi
+       done
+fi
+
+# It is possible to get incomplete recovery files, if the editor crashes
+# at the right time.
+virecovery=`echo $RECDIR/recover.*`
+if [ "$virecovery" != "$RECDIR/recover.*" ]; then
+       for i in $virecovery; do
+               # Only test files that are readable.
+               if test ! -r $i; then
+                       continue
+               fi
+
+               INUSE="@INUSE@"
+               if test "$INUSE" && $INUSE; then
+                       continue
+               fi
+
+               # Delete any recovery files that are zero length, corrupted,
+               # or that have no corresponding backup file.  Else send mail
+               # to the user.
+               recfile=`awk '/^X-vi-recover-path:/{print $2}' < $i`
+               if test -n "$recfile" -a -s "$recfile"; then
+                       $SENDMAIL -t < $i
+               else
+                       rm $i
+               fi
+       done
+fi
diff --git a/dist/nvi/dist/script b/dist/nvi/dist/script
new file mode 100644 (file)
index 0000000..7bb2b4f
--- /dev/null
@@ -0,0 +1,41 @@
+# setup
+# setenv VERSION 1.79
+setenv VERSION tk
+setenv S /usr/src/nvi
+
+# Make sure everything's checked in.
+cd $S && allout
+
+# Increment the version numbers and dates.
+setenv X version.h
+cd $S/ex && sco $X && echo "go to $VERSION" | sccs delget $X
+setenv X README
+cd $S && sco $X && vi $X && echo "go to $VERSION" | sccs delget $X
+
+# Build the distribution.
+cd $S/dist && sh ./distrib
+cd $S/catalog && make clean all check && rm dump __ck1 __ck2 && \
+    chmod 444 english* *.check
+
+# Build a version.
+cd $S && rm -rf build.local && mkdir build.local && cd build.local && \
+    ~bostic/bin/viconf && (make |& tee mklog)
+what vi | gzip > ../ARCHIVE/history/$VERSION.gz
+chmod 444 ../ARCHIVE/history/$VERSION.gz
+
+# build the documents
+cd $S/build.local && make cleandocs docs
+
+# Clean up the tree.
+cd $S && mv -i {ARCHIVE,TODO,build.local} SCCS/
+find . \! -path '*SCCS*' -type d \! -perm 775
+find . \! -path '*SCCS*' \( -name '*.rej' -o -name '*.orig' \)
+find . \! -path '*SCCS*' -type f \( -perm -200 -o -perm -2 -o -perm -20 \)
+chown -R bin.wsrc .
+
+# Create the release.
+setenv T /var/spool/ftp/pub
+cd $S/.. && mv -i nvi nvi-$VERSION
+tar cFFf - nvi-$VERSION | gzip --best > $T/nvi-$VERSION.tar.gz
+chmod 444 $T/nvi-$VERSION.tar.gz && mv -i nvi-$VERSION nvi
+cd $S && mv -i SCCS/{ARCHIVE,TODO,build.local} .
diff --git a/dist/nvi/dist/spell.ok b/dist/nvi/dist/spell.ok
new file mode 100644 (file)
index 0000000..fc103f4
--- /dev/null
@@ -0,0 +1,58 @@
+ADDCPPFLAGS
+ADDLDFLAGS
+ADDLIBS
+CPPFLAGS
+FreeBSD
+LDFLAGS
+LIBS
+Lite
+NVI
+NVI'S
+NetBSD
+Nvi
+POSIX
+Perl
+README
+Tcl
+Tk
+asnvi
+asvi
+autoconf
+bindir
+cd
+contrib
+csh
+datadir
+datafiles
+db
+distclean
+env
+filesystem
+foo
+gcc
+ksh
+lcurses
+ldb
+lm
+lperl
+ltcl
+ltermcap
+ltermlib
+ltk
+mandir
+mkdir
+ncurses
+nex
+nvi
+nview
+perl
+perlinterp
+setenv
+sh
+tcl
+tclinterp
+tcsh
+terminfo
+tknvi
+usr
+vi
diff --git a/dist/nvi/dist/stamp-h.in b/dist/nvi/dist/stamp-h.in
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/dist/nvi/docs/README b/dist/nvi/docs/README
new file mode 100644 (file)
index 0000000..3399dbe
--- /dev/null
@@ -0,0 +1,26 @@
+# Id: README,v 8.1 1997/04/13 10:38:45 bostic Exp (Berkeley) Date: 1997/04/13 10:38:45
+
+[USD stands for "User's Supplementary Documents".]
+
+edit/   Roff source for "Edit: A tutorial".  This document was USD:14 in
+       the 4.3BSD manuals, but was not distributed with 4.4BSD.
+
+exref/  Roff source for "Ex Reference Manual -- Version 3.7".  This
+       document was USD:16 in the 4.3BSD manuals, and USD tabbed 12 in
+       the 4.4BSD manuals.
+
+vi.man/ Roff source for a UNIX manual page for nex/nvi.  An updated version
+       of the 4.4BSD manual page.
+
+vi.ref/ Roff source for the nex/nvi reference document.  An updated version
+       of the 4.4BSD document, USD tabbed 13.
+
+vitut/  Roff source for "An Introduction to Display Editing with Vi".  This
+       document was USD:15 in the 4.3BSD manuals, but was not distributed
+       with 4.4BSD.  It includes the historic "Vi Quick Reference" card.
+
+PostScript preformatted versions of the nex/nvi reference manual and
+manual page are in the files named with a ".ps" suffix, in their
+respective source directories.  Flat text preformatted versions of the
+nex/nvi reference manual and manual page are in the files named with a
+".txt" suffix, in their respective source directories.
diff --git a/dist/nvi/docs/edit/Makefile b/dist/nvi/docs/edit/Makefile
new file mode 100644 (file)
index 0000000..803c7de
--- /dev/null
@@ -0,0 +1,20 @@
+# Id: Makefile,v 8.6 2001/01/28 15:50:07 skimo Exp (Berkeley) Date: 2001/01/28 15:50:07
+
+ROFF=  groff
+TBL=   tbl
+
+all: edittut.ps ../html/edittut.html
+
+../html/%.html: %.ms
+       test -d ../html || mkdir ../html
+       ${TBL} $< | ${ROFF} -ms -Thtml | \
+           sed 's/<img src="$<.*png">//' > $@
+       rm -f "$<"*png
+       chmod 444 $@
+
+%.ps: %.ms
+       ${TBL} $< | ${ROFF} -ms > $@
+       chmod 444 $@
+
+clean:
+       rm -f edittut.ps ../html/edittut.html
diff --git a/dist/nvi/docs/edit/edittut.ms b/dist/nvi/docs/edit/edittut.ms
new file mode 100644 (file)
index 0000000..cada8b8
--- /dev/null
@@ -0,0 +1,2254 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: edittut.ms,v 8.3 1996/08/18 11:36:05 bostic Exp (Berkeley) Date: 1996/08/18 11:36:05
+.\"
+.ll 6.5i
+.nr LL 6.5i
+.EH 'USD:11-%''Edit:  A Tutorial'
+.OH 'Edit:  A Tutorial''USD:11-%'
+.LP
+.ds u \s-2UNIX\s0
+.ND
+.sp 4
+.ce
+\f3\s+2Edit:  A Tutorial\s0\f1
+.sp
+.ce 3
+.I
+Ricki Blau
+.sp
+James Joyce
+.R
+.sp
+.ce 3
+Computing Services
+University of California
+Berkeley, California 94720
+.sp 3
+.ce
+.I
+ABSTRACT
+.R
+.sp
+.LP
+This narrative introduction to the use of the text editor
+.I edit
+assumes no prior familiarity with computers or with text editing.
+Its aim is to lead the beginning \s-2UNIX\(dg\s+2 user through the
+.FS
+\(dgUNIX is a trademark of Bell Laboratories.
+.FE
+fundamental steps of writing and revising a file of text.
+Edit,
+a version of the text editor
+.I ex,
+was designed to provide an informative environment
+for new and casual users.
+.PP
+We welcome comments and suggestions about this tutorial
+and the \s-2UNIX\s+2 documentation in general.
+.sp .5v
+September 1981
+.bp
+.ll 6.5i
+.nr LL 6.5i
+.nr LT 6.5i
+.ds u \s-2UNIX\s0
+.ce
+\s+2\f3Contents\f1\s0
+.LP
+.nf
+Introduction\ \ \ 3
+.sp
+Session 1\ \ 4
+.in +.5i
+Making contact with \s-2UNIX\s+2\ \ \ 4
+Logging in\ \ 4
+Asking for \fIedit\fR\ \ \ 4
+The ``Command not found'' message\ \ \ 5
+A summary\ \ 5
+Entering text\ \ \ 5
+Messages from \fIedit\fR\ \ \ 5
+Text input mode\ \ \ 6
+Making corrections\ \ \ 6
+Writing text to disk\ \ \ 7
+Signing off\ \ 7
+.in -.5i
+.sp
+Session 2\ \ \ 8
+.in +.5i
+Adding more text to the file\ \ \ 8
+Interrupt\ \ \ 8
+Making corrections\ \ \ 8
+Listing what's in the buffer (p)\ \ \ 9
+Finding things in the buffer\ \ \ 9
+The current line\ \ \ 10
+Numbering lines (nu)\ \ \ 10
+Substitute command (s)\ \ \ 10
+Another way to list what's in the buffer (z)\ \ \ 11
+Saving the modified text\ \ \ 12
+.in -.5i
+.sp
+Session 3\ \ \ 13
+.in +.5i
+Bringing text into the buffer (e)\ \ \ 13
+Moving text in the buffer (m)\ \ \ 13
+Copying lines (copy)\ \ \ 14
+Deleting lines (d)\ \ \ 14
+A word or two of caution\ \ \ 15
+Undo (u) to the rescue\ \ \ 15
+More about the dot (.) and buffer end ($)\ \ \ 16
+Moving around in the buffer (+ and \-)\ \ \ 16
+Changing lines (c)\ \ \ 17
+.in -.5i
+.sp
+Session 4\ \ \ 18
+.in +.5i
+Making commands global (g)\ \ \ 18
+More about searching and substituting\ \ \ 19
+Special characters\ \ \ 19
+Issuing \s-2UNIX\s+2 commands from the editor\ \ \ 20
+Filenames and file manipulation\ \ \ 20
+The file (f) command\ \ \ 20
+Reading additional files (r)\ \ \ 21
+Writing parts of the buffer\ \ \ 21
+Recovering files\ \ \ 21
+Other recovery techniques\ \ \ 21
+Further reading and other information\ \ \ 22
+Using \fIex\fR\ \ \ 22
+.in -.5i
+.sp
+Index\ \ \ 23
+.bp
+.SH
+.ce
+\s+2Introduction\s0
+.PP
+Text editing using a terminal connected to a computer
+allows you to create, modify, and print text
+easily.
+A
+.I
+text editor
+.R
+is a program
+that assists you
+as you create and modify text.
+The text editor you will learn here is named
+.I edit.
+Creating text using edit is as easy as typing it
+on an electric typewriter.
+Modifying text involves telling the text editor 
+what you want to add, change, or delete.
+You can review your text
+by typing a command
+to print the file contents
+as they are currently.
+Another program (which we do not discuss in this
+document), a text formatter,
+rearranges your text
+for you into ``finished form.''
+.PP
+These lessons assume no prior familiarity with computers
+or with text editing.
+They consist of a series of text editing sessions
+which lead you through the fundamental steps
+of creating and revising text.
+After scanning each lesson and before beginning the next,
+you should try the examples at a terminal to get a feeling
+for the actual process of text editing.
+If you set aside some time for experimentation,
+you will soon become familiar with using the
+computer to write and modify text.
+In addition to the actual use of the text editor,
+other features of \s-2UNIX\s0 will be very important to your work.
+You can begin to
+learn about these other features by
+reading one of the other tutorials
+that provide a general introduction to the system.
+You will be ready to proceed with this lesson as soon as
+you are familiar with (1) your terminal and its special keys,
+(2) how to login,
+(3) and the ways of correcting typing errors.
+Let's first define some terms:
+.sp .5
+.IP program 12
+A set of instructions, given to the computer,
+describing the sequence of steps the computer performs
+in order to accomplish a specific task.
+The task must be specific,
+such as balancing your checkbook
+or editing your text.
+A general task,
+such as working for world peace,
+is something we can all do,
+but not something we can currently write programs to do.
+.IP UNIX
+\s-2UNIX\s0 is a special type of program,
+called an operating system, that supervises the machinery
+and all other programs comprising the total
+computer system.
+.IP edit
+.I edit
+is the name of the \s-2UNIX\s0 text editor you will be learning to use,
+and is a program that aids you in writing or revising text.
+Edit was designed for beginning users,
+and is a simplified version of an editor named
+.I ex.
+.IP file
+Each \s-2UNIX\s0 account is allotted
+space for the permanent storage of information,
+such as programs, data or text.
+A file is a logical unit of data,
+for example, an essay, a program,
+or a chapter from a book,
+which is stored on a computer system.
+Once you create a file,
+it is kept until you instruct the system to remove it.
+You may create a file during one \s-2UNIX\s0 session,
+end the session,
+and return to use it at a later time.
+Files contain anything you choose to write and store in them.
+The sizes of files vary to suit your needs;
+one file might hold only a single number,
+yet another might contain
+a very long document or program.
+The only way to save
+information from one session to the next is to store it in a file,
+which you will learn in Session 1.
+.IP filename
+Filenames are used to distinguish one file from another,
+serving the same purpose as the labels of manila
+folders in a file cabinet.
+In order to write or access information in a file,
+you use the name of that file in a \s-2UNIX\s0 command,
+and the system will automatically locate the file.
+.IP disk
+Files are stored on an input/output device called a disk,
+which looks something like a stack of phonograph records.
+Each surface is coated with a material similar to that
+on magnetic recording tape,
+and information is recorded on it.
+.IP buffer
+A temporary work space, made available to the user
+for the duration of a session of text editing
+and used for creating and modifying
+the text file.
+We can think of the buffer as a blackboard that is
+erased after each class, where each session with the editor
+is a class.
+.bp
+.SH
+.ce 1
+\s+2Session 1\s0
+.sp 1
+.SH
+Making contact with \s-1UNIX\s0
+.PP
+To use the editor you must first make contact with the computer
+by logging in to \s-2UNIX\s0.
+We'll quickly review the standard \s-2UNIX\s0 login procedure
+for the two ways you can make contact:
+on a terminal that is directly linked to the computer,
+or over a telephone line where the computer answers your call.
+.SH
+Directly-linked terminals
+.PP
+Turn on your terminal and press the \s-1RETURN\s0 key.
+You are now ready to login.
+.SH
+Dial-up terminals
+.PP
+If your terminal connects with the computer over a telephone line,
+turn on the terminal, dial the system access number,
+and, when you hear a high-pitched tone, place the 
+telephone handset in the acoustic coupler, if you are using one.
+You are now ready to login.
+.SH
+Logging in
+.PP
+The message inviting you to login is:
+.DS I 1i
+login:
+.DE
+.LP
+Type your login name, which identifies you to \s-2UNIX\s0,
+on the same line as the login message,
+and press \s-2RETURN\s+2.
+If the terminal you are using
+has both upper and lower case,
+.B
+be sure you enter your login name in lower case;
+.R
+otherwise \s-2UNIX\s0 assumes your terminal
+has only upper case and will not recognize lower case
+letters you may type.
+\s-2UNIX\s0 types ``login:'' and you reply
+with your login name, for example ``susan'':
+.DS I 1i
+login: \fBsusan\fR \fI(and press the \s-2RETURN\s0 key)\fR
+.DE
+(In the examples, input you would type appears in
+.B "bold face"
+to distinguish it from the responses from \s-2UNIX\s0.)
+.PP
+\s-2UNIX\s0 will next respond with a request for a password
+as an additional precaution to prevent
+unauthorized people from using your account.
+The password will not appear when you type it,
+to prevent others from seeing it.
+The message is:
+.DS I 1i
+Password:    \fI(type your password and press \s-2RETURN\s+2)\fR
+.DE
+If any of the information you gave during the login
+sequence was mistyped or incorrect,
+\s-2UNIX\s0 will respond with
+.DS I 1i
+Login incorrect.
+.if t .sp .2v
+.if n .sp 1
+login:
+.DE
+in which case you should start the login process anew.
+Assuming that you have successfully
+logged in, \s-2UNIX\s0
+will print the message of the day and eventually will present
+you with a % at the beginning of a fresh line.
+The % is the \s-2UNIX\s0 prompt symbol
+which tells you that \s-2UNIX\s0 is ready to accept a command.
+.bd I 3
+.SH
+Asking for \fIedit\fP
+.fl
+.bd I
+.PP
+You are ready to tell \s-2UNIX\s0 that you
+want to work with edit, the text editor.
+Now is a convenient time to choose
+a name for the file of text you are about to create.
+To begin your editing session,
+type
+.B edit
+followed by a space and then the filename
+you have selected; for example, ``text''.
+After that,
+press the \s-2RETURN\s0 key and wait for edit's response:
+.DS I 1i
+% \fBedit text\fP    \fI(followed by a \s-2RETURN\s+2)\fR
+"text" No such file or directory
+:
+.DE
+If you typed the command correctly,
+you will now be in communication with edit.
+Edit has set aside a buffer for use as
+a temporary working space during your current editing session.
+Since ``text'' is a new file we are about to create
+the editor was unable to find that file, which it
+confirms by saying:
+.DS I 1i
+"text" No such file or directory
+.DE
+On the next line appears edit's prompt ``:'',
+announcing that you are in \f2command mode\f1 and
+edit expects a command from you.
+You may now begin to create the new file.
+.SH
+The ``Command not found'' message
+.PP
+If you misspelled edit by typing, say, ``editor'',
+this might appear:
+.DS I 1i
+% \fBeditor\fP
+editor: Command not found
+%
+.DE
+Your mistake in calling edit ``editor'' was
+treated by \s-2UNIX\s0 as a request
+for a program named ``editor''.
+Since there is no program
+named ``editor'',
+\s-2UNIX\s0 reported that the program was ``not found''.
+A new % indicates that \s-2UNIX\s0 is ready for another command,
+and you may then enter the correct command.
+.SH
+A summary
+.PP
+Your exchange with \s-2UNIX\s0 as you logged in and made contact with edit
+should look something like this:
+.DS I 1i
+login: \fBsusan\fP
+Password:
+\&... A Message of General Interest ...
+% \fBedit text\fP
+"text" No such file or directory
+:
+.DE
+.SH
+Entering text
+.PP
+You may now begin entering text into the buffer.
+This is done by \fIappending\fP (or adding) text to whatever
+is currently in the buffer.
+Since there is nothing in the buffer at the moment,
+you are appending text to nothing;
+in effect, 
+since you are adding text to nothing
+you are creating text.
+Most edit commands have two equivalent forms:
+a word that suggests what the command does,
+and a shorter abbreviation of that word.
+Many beginners find the full command names
+easier to remember at first,
+but once you are familiar with editing you may
+prefer to type the shorter abbreviations.
+The command to input text is ``append''.
+(It may be abbreviated ``a''.)
+Type
+.B append
+and press the \s-2RETURN\s0 key.
+.DS I 1i
+% \fBedit text
+\fR:\|\fBappend
+.R
+.DE
+.SH
+.bd I 3
+Messages from
+.I edit
+.fl
+.bd I
+.PP
+If you make a mistake in entering a command and
+type something that edit does not recognize,
+edit will respond with a message
+intended to help you diagnose your error.
+For example, if you misspell the command to input text by typing,
+perhaps, ``add'' instead of ``append'' or ``a'',
+you will receive this message:
+.DS I 1i
+:\|\fBadd\fR
+add: Not an editor command
+:
+.DE
+When you receive a diagnostic message,
+check what you typed in order to determine what
+part of your command confused edit.
+The message above means that edit
+was unable to recognize your mistyped command
+and, therefore, did not execute it.
+Instead, a new ``:''
+appeared to let you know that
+edit is again ready to execute a command.
+.SH
+Text input mode
+.PP
+By giving the command ``append'' (or using the abbreviation ``a''),
+you entered
+.I
+text input mode,
+.R
+also known as
+.I
+append mode.
+.R
+When you enter text input mode,
+edit stops sending you a prompt.
+You will not receive any prompts
+or error messages
+while in text input mode.
+You can enter
+pretty much anything you want on the lines.
+The lines are transmitted one by one to the buffer
+and held there during the editing session.
+You may append as much text as you want, and
+.I
+when you wish to stop entering text lines you should
+type a period as the only character on the line
+and press the \s-2RETURN\s0 key.
+.R
+When you type the period and press \s-2RETURN\s0,
+you signal that you want to stop appending text,
+and edit responds by allowing
+you to exit text input mode and reenter command mode.
+Edit will again
+prompt you for a command by printing ``:''.
+.PP
+Leaving append mode does not destroy the text in
+the buffer.
+You have to leave append
+mode to do any of the other kinds of editing,
+such as changing, adding, or printing text.
+If you type a period as the first character and
+type any other character on the same line,
+edit will believe you want to remain in append mode
+and will not let you out.
+As this can be very frustrating, 
+be sure to type
+.B only
+the period and the \s-2RETURN\s0 key.
+.PP
+This is a good place to learn an important
+lesson about computers and text:  a blank space is
+a character as far as a computer is concerned.  
+If you so much as type a period followed by a blank
+(that is, type a period and then the space bar on the keyboard),
+you will remain in append mode with the last line of text
+being:
+.DS I 1i
+.B
+.ps +2
+\&.
+.ps -2
+.R
+.DE
+Let's say that you enter the lines 
+(try to type
+.B exactly
+what you see, including ``thiss''):
+.DS I 1i
+.B
+This is some sample text.
+And thiss is some more text.
+Text editing is strange, but nice.
+\&.
+.R
+.DE
+The last line is the period followed by a \s-2RETURN\s0
+that gets you out of append mode.  
+.SH
+Making corrections
+.PP
+If you have read a general introduction to \s-2UNIX\s0,
+you will recall that it is possible to erase individual
+letters that you have typed.
+This is done by typing the designated erase character
+as many times as there are characters
+you want to erase.
+.PP
+The usual erase character varies from place to place and 
+user to user.  Often it
+is the backspace (control-H),
+so you can correct typing errors
+in the line you are typing
+by holding down the \s-1CTRL\s+1 key
+and typing the ``H'' key.  (Sometimes it is the DEL key.)
+If you type the erase character
+you will notice
+that the terminal backspaces in the line you are on.
+You can backspace over your error,
+and then type what you want to be the rest of the line.
+.PP
+If you make a bad start
+in a line
+and would like to begin again,
+you can either backspace to the beginning of the line
+or you can use the at-sign ``@'' to erase everything on the line:
+.DS I 1i
+.B
+Text edtiing is strange, but@
+Text editing is strange, but nice.
+.R
+.fl
+.bd S
+.DE
+When you type the at-sign (@), you erase
+the entire line typed so far
+and are given a fresh line to type on.
+You may immediately begin to retype the line.
+This, unfortunately, does not work after you type the
+line and press \s-2RETURN\s+2.  
+To make corrections in lines that have been completed,
+it is necessary to use the editing commands
+covered in the next sessions.
+.SH
+Writing text to disk
+.PP
+You are now ready to edit the text.  One common operation
+is to write the text to disk as a file for safekeeping
+after the session is over.
+This is the only way to save information from one session to the next,
+since the editor's buffer is temporary and will last only until the
+end of the editing session.
+Learning how to write a file to disk is second in
+importance only to entering the text.
+To write the contents of the buffer to a disk
+file, use the command ``write''
+(or its abbreviation ``w''):
+.DS I 1i
+:\|\fBwrite
+.R
+.DE
+Edit will copy the contents of the buffer to a disk file.
+If the file does not yet exist,
+a new file will be created automatically
+and the presence of a ``[New file]'' will be noted.
+The newly-created file will be given the name specified when
+you entered the editor, in this case ``text''.
+To confirm that the disk file has been successfully written,
+edit will repeat the filename and give
+the number of lines and the total
+number of characters in the file.
+The buffer remains unchanged by the ``write'' command.
+All of the lines that were written to disk will still be
+in the buffer,
+should you want to modify or add to them.
+.PP
+Edit must have a name for the file to be written.
+If you forgot to indicate the name of the file
+when you began to edit,
+edit will print in response to your write command:
+.DS I 1i
+No current filename
+.DE
+If this happens, you can specify the filename in a new write command:
+.DS I 1i
+:\|\fBwrite text
+.R
+.DE
+After the ``write'' (or ``w''), type a space and then the name of the file.
+.SH
+Signing off
+.PP
+We have done enough for this first lesson on using the
+\s-2UNIX\s0 text editor, and are ready to quit the session with edit.
+To do this we type ``quit'' (or ``q'') and press \s-2RETURN\s+2:
+.DS I 1i
+:\|\fBwrite
+.R
+"text" [New file]  3 lines, 90 characters
+:\|\fBquit\fR
+%
+.DE
+The % is from \s-2UNIX\s0 to tell you that your session with edit is
+over and you may command \s-2UNIX\s0 further.
+Since we want
+to end the entire session at the terminal, we also need to
+exit from \s-2UNIX\s0.
+In response to the \s-2UNIX\s0 prompt of ``\|%\|''
+type the command
+.DS I 1i
+%\|\fBlogout\fR
+.DE
+This will end your session with \s-2UNIX\s0, and will ready the
+terminal for the next user.
+It is always important to type \fBlogout\fR at the end of a session
+to make absolutely sure no one
+could accidentally stumble into your abandoned 
+session and thus gain access to your files,
+tempting even the most honest of souls.
+.sp 1
+.PP
+This is the end of the first session on \s-2UNIX\s0 text editing.
+.bp
+.TL
+Session 2
+.sp
+.PP
+Login with \s-2UNIX\s0 as in the first session:
+.DS I 1i
+login: \fBsusan\fP  \fI(carriage return)\fR
+Password:       \fI(give password and carriage return)\fR
+.if t .sp .2v
+.if n .sp 1
+\&... A Message of General Interest ...
+% 
+.DE
+When you indicate you want to edit,
+you can specify the name of the file you worked on last time.
+This will
+start edit working, and it will fetch the contents of the
+file into the buffer, so that you can resume editing the same file.
+When edit has copied the file into the buffer, it
+will repeat its name and tell
+you the number of lines and characters it contains.
+Thus,
+.DS I 1i
+.B
+% edit text
+.R
+"text" 3 lines, 90 characters
+:
+.DE
+means you asked edit to fetch
+the file named ``text'' for editing,
+causing it to copy the
+90 characters of text into the buffer.
+Edit awaits
+your further instructions,
+and indicates this by its prompt character, the colon (:).
+In this session, we will append more text to our file,
+print the contents of the buffer, and learn to change the text of a line.
+.SH
+Adding more text to the file
+.PP
+If you want to add more to the end of your
+text you may do so by using the append command to enter text input mode.
+When ``append'' is the first command
+of your editing session,
+the lines you enter
+are placed at the end of the buffer.
+Here we'll use the abbreviation for the append command, ``a'':
+.DS I 1i
+:\|\fBa
+This is text added in Session 2.
+It doesn't mean much here, but
+it does illustrate the editor.
+\|\fB\s+2\&.\s-2
+.R
+.DE
+You may recall that once you enter append mode
+using the ``a'' (or ``append'') command,
+you need to type a line containing only a period (.)
+to exit append mode.
+.SH
+Interrupt
+.PP
+Should you press the \s-2RUB\s+2 key (sometimes labelled \s-2DELETE\s+2)
+while working with edit,
+it will send this message to you:
+.DS I 1i
+Interrupt
+:
+.DE
+Any command that edit might be executing
+is terminated by rub or delete,
+causing edit to prompt you for a new command.
+If you are appending text at the time,
+you will exit from append mode
+and be expected to give another command.
+The line of text you were typing
+when the append command was interrupted
+will not be entered into the buffer.
+.SH
+Making corrections
+.PP
+If while typing the line you hit an incorrect key,
+recall that
+you may delete the incorrect character
+or cancel the entire line of input by erasing in the usual way.
+Refer either
+to the last few pages of Session 1
+if you need to review
+the procedures for making a correction.
+The most important idea to remember is that
+erasing a character or cancelling a line must be done
+before you press the \s-2RETURN\s+2 key.
+.SH
+Listing what's in the buffer (p)
+.PP
+Having appended text to what you wrote in Session 1,
+you might want to see all the lines in the buffer.
+To print the contents of the buffer, type the command:
+.DS I 1i
+:\|\fB1,$p
+.R
+.DE
+The ``1''\(dg
+.FS
+\(dgThe numeral ``one'' is the top left-most key,
+and should not be confused with the letter ``el''.
+.FE
+stands for line 1 of the buffer,
+the ``$'' is a special symbol designating the last line
+of the buffer,
+and ``p'' (or \fBprint\fR) is the command to print from line 1
+to the end of the buffer.
+The command ``1,$p'' gives you:
+.DS I 1i
+This is some sample text.
+And thiss is some more text.
+Text editing is strange, but nice.
+This is text added in Session 2.
+It doesn't mean much here, but
+it does illustrate the editor.
+.DE
+Occasionally, you may accidentally
+type a character that can't be printed,
+which can be done by striking a key
+while the \s-2CTRL\s0 key is pressed.
+In printing lines, edit uses a special notation to
+show the existence of non-printing characters.
+Suppose you had introduced the non-printing character ``control-A''
+into the word ``illustrate''
+by accidently pressing the \s-2CTRL\s0 key while
+typing ``a''.
+This can happen on many terminals
+because the \s-2CTRL\s+2 key and the ``A'' key
+are beside each other.
+If your finger presses between the two keys,
+control-A results.
+When asked to print the contents of the buffer,
+edit would display
+.DS I 1i
+it does illustr^Ate the editor.
+.DE
+To represent the control-A, edit shows ``^A''.
+The sequence ``^'' followed by a capital
+letter stands for the one character
+entered by holding down the \s-2CTRL\s0 key and typing the letter
+which appears after the ``^''.
+We'll soon discuss the commands that can be used
+to correct this typing error.
+.PP
+In looking over the text we see that
+``this'' is typed as ``thiss'' in the second line,
+a deliberate error so we can learn to make corrections.
+Let's correct the spelling.
+.SH
+Finding things in the buffer
+.PP
+In order to change something in the buffer we first need to
+find it.
+We can find ``thiss'' in the text we have
+entered by looking at a listing
+of the lines.
+Physically speaking, we search the lines
+of text looking for ``thiss'' and stop searching when
+we have found it.
+The way to tell edit to search for something
+is to type it inside slash marks:
+.DS I 1i
+:\|\fB/thiss/
+.R
+.DE
+By typing
+.B /thiss/
+and pressing \s-1RETURN\s0,
+you instruct edit to search for ``thiss''.
+If you ask edit to look for a pattern of characters
+which it cannot find in the buffer,
+it will respond ``Pattern not found''.
+When edit finds
+the characters ``thiss'', it will print the line of text
+for your inspection:
+.DS I 1i
+And thiss is some more text.
+.DE
+Edit is now positioned in the buffer at the
+line it just printed,
+ready to make a change in the line.
+.bp
+.SH
+The current line
+.PP
+Edit keeps track of the line in the buffer where it is located
+at all times during an editing session.
+In general, the line that has been most recently
+printed, entered, or changed
+is the current location in the buffer.
+The editor is prepared to make changes
+at the current location in the buffer,
+unless you direct it to another location.
+.PP
+In particular,
+when you bring a file into the buffer,
+you will be located at the last line in the file,
+where the editor left off copying the lines
+from the file to the buffer.
+If your first editing command is ``append'',
+the lines you enter are added
+to the end of the file,
+after the current line \(em
+the last line in the file.
+.PP
+You can refer to your current location in the buffer by the
+symbol
+period (.) usually known by the name ``dot''.
+If you type ``.'' and carriage
+return you will be instructing edit to print the current line:
+.DS I 1i
+:\|\fB\s+2\&.\s-2
+.R
+And thiss is some more text.
+.DE
+.PP
+If you want to know the number of the current line,
+you can type
+.B \&.=
+and press \s-2RETURN\s+2,
+and edit will respond with the line number:
+.DS I 1i
+:\|\fB\s+2.\s-2=
+.R
+2
+.DE
+If you type the number of any line and press \s-2RETURN\s+2,
+edit will position you at that line and
+print its contents:
+.DS I 1i
+:\|\fB2
+.R
+And thiss is some more text.
+.DE
+You should experiment with these commands
+to gain experience in using them to make changes.
+.SH
+Numbering lines (nu)
+.PP
+The
+.B
+number (nu)
+.R
+command is similar to print,
+giving both the number and the text of each printed line.
+To see the number and the text of the current line type
+.DS I 1i
+:\|\fBnu
+.R
+\0\0\0\0\02\0\0And thiss is some more text.
+.DE
+Note that the shortest abbreviation for the number command is
+``nu'' (and not ``n'', which is used for a different command).
+You may specify a range of lines
+to be listed by the number command in the same way that lines
+are specified for print.
+For example, \f31,$nu\f1 lists all lines in the buffer with their
+corresponding line numbers.
+.SH
+Substitute command (s)
+.PP
+Now that you have found the misspelled word, 
+you can change it from ``thiss'' to ``this''.
+As far as edit is concerned,
+changing things is a matter of
+substituting one thing for another.
+As
+.I a
+stood for
+.I append,
+so
+.I s
+stands for
+.I substitute.
+We will use the abbreviation ``s'' to reduce the chance
+of mistyping the substitute command.
+This command will instruct edit to make the change:
+.DS I 1i
+\f32s/thiss/this/\f1
+.DE
+We first indicate the line to be changed, line 2,
+and then
+type an ``s'' to indicate we want
+edit to make a substitution.
+Inside the first set of slashes
+are the characters that we want to change,
+followed by the characters to replace them,
+and then a closing slash mark.
+To summarize:
+.DS I 1i
+2s/ \fIwhat is to be changed\fR / \fIwhat to change it to \fR/
+.DE
+If edit finds an exact match of the characters to be
+changed it will make the change
+.B only
+in the first occurrence of the characters.
+If it does not find the characters
+to be changed, it will respond:
+.DS I 1i
+Substitute pattern match failed
+.DE
+indicating that your instructions could not be carried out.
+When edit does find the characters that you want to change,
+it will make the substitution and automatically print
+the changed line, so that you can check that the correct substitution
+was made.
+In the example,
+.DS I 1i
+:\|\fB2s/thiss/this/
+.R
+And this is some more text.
+.DE
+line 2 (and line 2 only) will be searched for the characters
+``thiss'', and when the first exact match is found, ``thiss''
+will be changed to ``this''.
+Strictly speaking, it was not necessary above to
+specify  the number of the line to be changed.
+In
+.DS I 1i
+:\|\fBs/thiss/this/
+.R
+.DE
+edit will assume that we mean to change
+the line where we are currently located (``.'').
+In this case,
+the command without a line number would have produced the same result
+because we were already located
+at the line we wished to change.
+.PP
+For another illustration of the substitute command,
+let us choose the line:
+.DS I 1i
+Text editing is strange, but nice.
+.DE
+You can make this line a bit more positive
+by taking out the characters ``strange, but\ '' so the line 
+reads:
+.DS I 1i
+Text editing is nice.
+.DE
+A command that will first position edit at the desired line
+and then make the substitution is:
+.DS I 1i
+:\|\fB/strange/s/strange, but //
+.R
+.DE
+.LP
+What we have done here is combine our search with
+our substitution.
+Such combinations are perfectly legal,
+and speed up editing quite a bit
+once you get used to them.
+That is, you do not necessarily have to use
+line numbers to identify a line to edit.
+Instead, you may identify the line you want to change
+by asking edit to search for a specified pattern of letters
+that occurs in that line.
+The parts of the above command are:
+.in +1i
+.TS
+l l.
+\fB/strange/\fP        tells edit to find the characters ``strange'' in the text
+\fBs\fP        tells edit to make a substitution
+\fB/strange, but //\fP substitutes nothing at all for the characters ``strange, but ''
+.TE
+.in -1i
+.PP
+You should note the space after ``but'' in ``/strange, but /''. 
+If you do not indicate that the space is to be taken out,
+your line will read:
+.DS I 1i
+.if t Text editing is   nice.
+.if n Text editing is  nice.
+.DE
+which looks a little funny   
+because of the extra space between ``is'' and ``nice''.
+Again, we realize from this that a blank space
+is a real character to a computer, and in editing text
+we need to be aware of spaces
+within a line just as we would be aware of an ``a'' or 
+a ``4''.
+.SH
+Another way to list what's in the buffer (z)
+.PP
+Although the print command is useful for looking at specific lines
+in the buffer,
+other commands may be more convenient for
+viewing large sections of text.
+You can ask to see a screen full of text at a time
+by using the command
+.B z.
+If you type
+.DS I 1i
+:\|\fB1z
+.R
+.DE
+edit will start with line 1 and continue printing lines,
+stopping either when the screen of
+your terminal is full
+or when the last line in the buffer has been printed.
+If you want to read the next segment of text, type the command
+.DS I 1i
+:\|\fBz
+.DE
+If no starting line number is given for the z command,
+printing will start at the ``current'' line, in this case the
+last line printed.
+Viewing lines in the buffer one screen full at a time
+is known as \fIpaging\fR.
+Paging can also be used to print
+a section of text on a hard-copy terminal.
+.SH
+Saving the modified text
+.PP
+This seems to be a good place to pause in our work,
+and so we should end the second session.
+If you (in haste) type ``q'' to quit the session
+your dialogue with edit will be:
+.DS I 1i
+:\|\fBq
+.R
+No write since last change (:quit! overrides)
+:
+.DE
+This is edit's warning that you have not written
+the modified contents of the buffer to disk.
+You run the risk of losing the work you did
+during the editing session since you typed the latest write
+command.
+Because in this lesson we have not written
+to disk at all, everything we have done
+would have been lost
+if edit had obeyed the \fBq\fR command.
+If you did not want to save the work done during
+this editing session, you would have to type ``q!''
+or (``quit!'')
+to confirm that you indeed wanted to end the session
+immediately,
+leaving the file as it was
+after the most recent ``write'' command.
+However,
+since you want to save what
+you have edited, you need to type:
+.DS I 1i
+:\|\fBw
+.R
+"text" 6 lines, 171 characters
+.DE
+and then follow with the commands to quit and logout:
+.DS I 1i
+:\|\fBq
+% \fBlogout\fR
+.DE
+and hang up the phone or turn off the terminal when
+\s-2UNIX\s0 asks for a name.
+Terminals connected to the port selector
+will stop after the logout command,
+and pressing keys on the keyboard will do nothing.
+.sp 1
+.PP
+This is the end of the second session on \s-2UNIX\s0 text editing.
+.bp
+.TL
+Session 3
+.SH
+Bringing text into the buffer (e)
+.PP
+Login to \s-2UNIX\s0 and make contact with edit.  
+You should try to login without
+looking at the notes, but if you must
+then by all means do.
+.PP
+Did you remember to give the name of the file
+you wanted to edit?
+That is, did you type
+.DS I 1i
+% \fBedit text\fR
+.DE
+or simply
+.DS I 1i
+% \fBedit\fR
+.DE
+Both ways get you in contact with edit, but the first way
+will bring a copy of the file named ``text'' into
+the buffer.  
+If you did forget to tell edit the name of your file,
+you can get it into the buffer by
+typing:
+.DS I 1i
+:\|\fBe text
+.R
+"text" 6 lines, 171 characters
+.DE
+The command
+.B edit,
+which may be abbreviated \fBe\fR,
+tells edit that you want
+to erase anything that might already be in 
+the buffer and bring a copy of the file ``text'' into the buffer
+for editing.
+You may also use the edit (e) command to change files in
+the middle of an editing session,
+or to give edit the name of a new file that you want to create.
+Because the edit command clears the buffer,
+you will receive a warning if you try to edit a new file without
+having saved a copy of the old file.
+This gives you a chance to write the contents of the buffer to disk
+before editing the next file.
+.SH
+Moving text in the buffer (m)
+.PP
+Edit allows you to move lines of text
+from one location in the buffer to another
+by means of the
+.B move
+(\fBm\fR) command.
+The first two examples are for illustration only,
+though after you have read this Session
+you are welcome to return to them for practice.
+The command
+.DS I 1i
+:\|\fB2,4m$
+.R
+.DE
+directs edit to move lines 2, 3, and 4
+to the end of the buffer ($).  
+The format for the move command is that you specify
+the first line to be moved, the last line to be moved,
+the move command ``m'', and the line after which
+the moved text is to be placed.
+So,
+.DS I 1i
+:\|\fB1,3m6
+.R
+.DE
+would instruct edit to move lines 1 through 3 (inclusive) 
+to a location after line 6 in the buffer.
+To move only one line, say, line 4,
+to a location in the buffer after line 5, 
+the command would be ``4m5''.
+.PP
+Let's move some text using the command:
+.DS I 1i
+:\|\fB5,$m1
+.R
+2 lines moved
+it does illustrate the editor.
+.DE
+After executing a command that moves more than one line of the buffer,
+edit tells how many lines were affected by the move
+and prints the last moved line for your inspection.
+If you want to see more than just the last line,
+you can then
+use the print (p), z, or number (nu) command to view more text.
+The buffer should now contain:
+.DS I 1i
+This is some sample text.
+It doesn't mean much here, but
+it does illustrate the editor.
+And this is some more text.
+Text editing is nice.
+This is text added in Session 2.
+.DE
+You can restore the original order by typing:
+.DS I 1i
+:\|\fB4,$m1
+.R
+.DE
+or, combining context searching and the move command:
+.DS I 1i
+:\|\fB/And this is some/,/This is text/m/This is some sample/
+.R
+.DE
+(Do not type both examples here!)
+The problem with combining context searching
+with the move command 
+is that your chance of making a typing error
+in such a long command is greater than
+if you type line numbers.
+.SH
+Copying lines (copy)
+.PP
+The
+.B copy
+command
+is used to make a second copy of specified lines,
+leaving the original lines where they were.
+Copy
+has the same format as the move command, for example:
+.DS I 1i
+:\|\fB2,5copy $
+.R
+.DE
+makes a copy of lines 2 through 5,
+placing the added lines after the buffer's end ($).
+Experiment with the copy command
+so that you can become familiar with how it works.
+Note that the shortest abbreviation for copy is
+\f3co\f1 (and
+not the letter ``c'', which has another meaning).
+.SH
+Deleting lines (d)
+.PP
+Suppose you want to delete 
+the line
+.DS I 1i
+This is text added in Session 2.
+.DE
+from the buffer.
+If you know the number of the line to be deleted,
+you can type
+that number followed by
+\fBdelete\fR or \fBd\fR.
+This example deletes line 4,
+which is ``This is text added in Session 2.''
+if you typed the commands
+suggested so far.
+.DS I 1i
+:\|\fB4d
+.R
+It doesn't mean much here, but
+.DE
+Here ``4'' is the number of the line to be deleted,
+and ``delete'' or ``d'' is the command to delete the line.
+After executing the delete command,
+edit prints the line that has become the current line (``.'').
+.PP
+If you do not happen to know the line number
+you can search for the line and then delete it using this
+sequence of commands:
+.DS I 1i
+:\|\fB/added in Session 2./
+.R
+This is text added in Session 2.
+:\|\fBd
+.R
+It doesn't mean much here, but
+.DE
+The ``/added in Session 2./''
+asks edit to locate and print
+the line containing the indicated text,
+starting its search at the current line
+and moving line by line
+until it finds the text.
+Once you are sure that you have correctly specified the line
+you want to delete,
+you can enter the delete (d) command.
+In this case it is not necessary to
+specify a line number before the ``d''.
+If no line number is given,
+edit deletes the current line (``.''),
+that is, the line found by our search.
+After the deletion, your buffer should contain:
+.DS I 1i
+This is some sample text.
+And this is some more text.
+Text editing is nice.
+It doesn't mean much here, but
+it does illustrate the editor.
+And this is some more text.
+Text editing is nice.
+This is text added in Session 2.
+It doesn't mean much here, but
+.DE
+To delete both lines 2 and 3:
+.DS I 1i
+And this is some more text.
+Text editing is nice.
+.DE
+you type
+.DS I 1i
+:\|\f32,3d\f1
+2 lines deleted
+.DE
+which specifies the range of lines from 2 to 3,
+and the operation on those lines \(em ``d'' for delete.
+If you delete more than one line
+you will receive a message
+telling you the number of lines deleted,
+as indicated in the example above.
+.PP
+The previous example assumes that you know the line numbers for
+the lines to be deleted.
+If you do not you might combine the search command
+with the delete command:
+.DS I 1i
+:\|\fB/And this is some/,/Text editing is nice./d
+.R
+.DE
+.SH
+A word or two of caution
+.PP
+In using the search function to locate lines to
+be deleted you should be
+.B
+absolutely sure
+.R
+the characters you give as the basis for the search
+will take edit to the line you want deleted.
+Edit will search for the first
+occurrence of the characters starting from where
+you last edited \-
+that is, from the line you see printed if you type dot (.).
+.PP
+A search based on too few
+characters may result in the wrong lines being deleted,
+which edit will do as easily as if you had meant it.
+For this reason, it is usually safer
+to specify the search and then delete in two separate steps,
+at least until you become familiar enough with using the editor
+that you understand how best to specify searches.
+For a beginner it is not a bad idea to double-check
+each command before pressing \s-2RETURN\s+2 to send the command on its way.
+.SH
+Undo (u) to the rescue
+.PP
+The
+.B
+undo (u)
+.R
+command has the ability to
+reverse the effects of the last command that changed the buffer.
+To undo the previous command, type
+``u'' or ``undo''.
+Undo can rescue
+the contents of the buffer from many an unfortunate mistake.
+However, its powers are not unlimited,
+so it is still wise to be reasonably
+careful about the commands you give.
+.PP
+It is possible to undo only commands which
+have the power to change the buffer \(em for example,
+delete, append, move, copy, substitute, and even undo itself.
+The commands write (w) and edit (e), which interact with disk files,
+cannot be undone, nor can commands that do not change
+the buffer, such as print.
+Most importantly,
+the
+.B only
+command that can be reversed by undo
+is the
+last ``undo-able'' command you typed.
+You can use control-H and @ to change
+commands while you are typing them,
+and undo to reverse the effect of the commands
+after you have typed them and pressed \s-2RETURN\s+2.
+.PP
+To illustrate,
+let's issue an undo command.
+Recall that the last buffer-changing command we gave deleted
+the lines formerly numbered 2 and 3.
+Typing undo at this moment will reverse the effects
+of the deletion, causing those two lines to be
+replaced in the buffer.
+.DS I 1i
+:\|\fBu
+.R
+2 more lines in file after undo
+And this is some more text.
+.DE
+Here again, edit informs you if the command affects more
+than one line,
+and prints
+the text of the line which is now ``dot'' (the current line).
+.SH
+More about the dot (.) and buffer end ($)
+.PP
+The function assumed by the symbol dot depends on its context.
+It can be used:
+.IP
+1.  to exit from append mode; we type dot (and only a dot) on
+a line and press \s-2RETURN\s+2;
+.IP
+2.  to refer to the line we are at in the buffer.
+.LP
+Dot can also be combined with the equal sign to get
+the number of the line currently being edited:
+.DS I 1i
+:\|\fB\&.=
+.R
+.DE
+If we type ``\fB.\fR='' we are asking for the number of the line,
+and if we type ``\fB.\fR'' we are asking for the text of the line.
+.PP
+In this editing session and the last, we used the dollar
+sign to indicate the end of the buffer
+in commands such as print, copy, and move.
+The dollar sign as a command asks edit to print the last
+line in the buffer.
+If the dollar sign is combined with the equal sign (\f3$=\f1)
+edit will print the line number corresponding to the
+last line in the buffer.
+.PP
+``\fB.\fR'' and ``$'', then, represent line numbers.
+Whenever appropriate, these symbols can be used in
+place of line numbers in commands.
+For example
+.DS I 1i
+:\|\fB\s+2.\s-2,$d
+.R
+.DE
+instructs edit to delete all lines from the current line (\fB.\fR)
+to the end of the buffer.
+.SH
+Moving around in the buffer  (+ and \-)
+.PP
+When you are editing
+you often want
+to go back and re-read a previous line.
+You could specify a context search for a line you want to
+read if you remember some of its text,
+but if you simply want to see what was written a few, say 3, lines
+ago, you can type
+.DS I 1i
+\-3p
+.DE
+This tells edit to move back to a position 3 lines
+before the current line (.)
+and print that line.
+You can move forward in the buffer similarly:
+.DS I 1i
++2p
+.DE
+instructs edit to print the line that is 2
+ahead of your current position.
+.PP
+You may use ``+'' and ``\-'' in any command where edit
+accepts line numbers.
+Line numbers specified with ``+'' or ``\-''
+can be combined to print a range of lines.
+The command
+.DS I 1i
+:\|\fB\-1,+2copy$
+.R
+.DE
+makes a copy of 4 lines:  the current line, the line before it,
+and the two after it.
+The copied lines will be placed after the last line
+in the buffer ($),
+and the original lines referred to by ``\-1'' and ``+2''
+remain where they are.
+.PP
+Try typing only ``\-''; you will move back one line just as
+if you had typed ``\-1p''.
+Typing the command ``+'' works similarly.
+You might also try typing a few plus or minus signs in a row
+(such as ``+++'') to see edit's response.
+Typing \s-2RETURN\s+2 alone on a line is the equivalent
+of typing ``+1p''; it will move you one line ahead in the buffer
+and print that line.
+.PP
+If you are at the last line of the buffer and try
+to move further ahead, perhaps by typing a ``+'' or
+a carriage return alone on the line,
+edit will remind you that you are at the end of the buffer:
+.sp
+.nf
+.ti 1i
+At end-of-file
+.br
+or
+.ti 1i
+Not that many lines in buffer
+.fi
+.LP
+Similarly, if you try to move to a position before the first line,
+edit will print one of these messages:
+.sp
+.nf
+.ti 1i
+Nonzero address required on this command
+.br
+or
+.ti 1i
+Negative address \- first buffer line is 1
+.fi
+.LP
+The number associated with a buffer line is the line's ``address'',
+in that it can be used to locate the line.
+.SH
+Changing lines (c)
+.PP
+You can also delete certain lines and
+insert new text in their place.
+This can be accomplished easily with the
+.B "change (c)"
+command.
+The change command instructs edit to delete specified lines
+and then switch to text input mode to
+accept the text that will replace them.
+Let's say you want to change the first two lines in the buffer:
+.DS I 1i
+This is some sample text.
+And this is some more text.
+.DE
+to read
+.DS I 1i
+This text was created with the \s-2UNIX\s0 text editor.
+.DE
+To do so, you type:
+.DS I 1i
+:\|\fB1,2c
+.R
+2 lines changed
+.B
+This text was created with the \s-2UNIX\s0 text editor.
+\s+2\&.\s-2
+.R
+:
+.DE
+In the command
+.B 1,2c
+we specify that we want to change
+the range of lines beginning with 1 and ending with 2
+by giving line numbers as with the print command.
+These lines will be deleted.
+After you type \s-2RETURN\s+2 to end the change command,
+edit notifies you if more than one line will be changed
+and places you in text input mode.
+Any text typed on the following lines will be inserted into
+the position where lines were deleted by the change command.
+.B
+You will remain in text input mode until you exit in the usual way,
+by typing a period alone on a line.
+.R
+Note that the number of lines added to the buffer need not be
+the same as the number of lines deleted.
+.sp 1
+.PP
+This is the end of the third session on text editing with \s-2UNIX\s0.
+.bp
+.SH
+.ce 1
+\s+2Session 4\s0
+.sp
+.PP
+This lesson covers several topics, starting with
+commands that apply throughout the buffer,
+characters with special meanings,
+and how to issue \s-2UNIX\s0 commands while in the editor.
+The next topics deal with files:
+more on reading and writing,
+and methods of recovering files lost in a crash.
+The final section suggests sources of further information.
+.SH
+Making commands global (g)
+.PP
+One disadvantage to the commands we have used for
+searching or substituting is that if you
+have a number of instances of a word to change 
+it appears that you have to type the command 
+repeatedly, once for
+each time the change needs to be made.
+Edit, however, provides a way to make commands
+apply to the entire contents of the buffer \-
+the
+.B
+global (g)
+.R
+command.
+.PP
+To print all lines
+containing a certain sequence of characters
+(say, ``text'')
+the command is:
+.DS I 1i
+:\|\fBg/text/p
+.R
+.DE
+The ``g'' instructs edit to
+make a global search for all lines
+in the buffer containing the characters  ``text''.
+The ``p'' prints the lines found.
+.PP
+To issue a global command, start by typing a ``g'' and then a search
+pattern identifying
+the lines to be affected.
+Then, on the same line, type the command to be
+executed for the identified lines.
+Global substitutions are frequently useful.
+For example,
+to change all instances of the word ``text'' to the word ``material''
+the command would be a combination of the global search and the
+substitute command:
+.DS I 1i
+:\|\fBg/text/s/text/material/g
+.R
+.DE
+Note the ``g'' at the end of the global command,
+which instructs edit to change
+each and every instance of ``text'' to ``material''.
+If you do not type the ``g'' at the end of the command
+only the
+.I first
+instance of ``text'' \fIin each line\fR will be changed
+(the normal result of the substitute command).
+The ``g'' at the end of the command is independent of the ``g''
+at the beginning.
+You may give a command such as:
+.DS I 1i
+:\|\fB5s/text/material/g
+.R
+.DE
+to change every instance of ``text'' in line 5 alone.
+Further, neither command will change ``text'' to ``material''
+if ``Text'' begins with a capital rather than a lower-case
+.I t.
+.PP
+Edit does not automatically print the lines modified by a
+global command.
+If you want the lines to be printed, type a ``p''
+at the end of the global command:
+.DS I 1i
+:\|\fBg/text/s/text/material/gp
+.R
+.DE
+You should be careful
+about using the global command in combination with any other \-
+in essence, be sure of what you are telling edit to do
+to the entire buffer.
+For example,
+.DS I 1i
+:\|\fBg/ /d
+.R
+72 less lines in file after global
+.DE
+will delete every line containing a blank anywhere in it.
+This could adversely affect
+your document, since most lines have spaces between words
+and thus would be deleted.
+After executing the global command,
+edit will print a warning if the command added or deleted more than one line.
+Fortunately, the undo command can reverse
+the effects of a global command.
+You should experiment with the global command
+on a small file of text to see what it can do for you.
+.SH
+More about searching and substituting
+.PP
+In using slashes to identify a character string
+that we want to search for or change,
+we have always specified the exact characters.
+There is a less tedious way to
+repeat the same string of characters.
+To change ``text'' to ``texts'' we may type either
+.DS I 1i
+:\|\fB/text/s/text/texts/
+.R
+.DE
+as we have done in the past,
+or a somewhat abbreviated command:
+.DS I 1i
+:\|\fB/text/s//texts/
+.R
+.DE
+In this example, the characters to be changed
+are not specified \-
+there are no characters, not even a space,
+between the two slash marks
+that indicate what is to be changed.
+This lack of characters between the slashes
+is taken by the editor to mean
+``use the characters we last searched for as the characters to be changed.''
+.PP
+Similarly, the last context search may be repeated
+by typing a pair of slashes with nothing between them:
+.DS I 1i
+:\|\fB/does/
+.R
+It doesn't mean much here, but
+:\|\fB//
+.R
+it does illustrate the editor.
+.DE
+(You should note that the search command found the characters ``does''
+in the word ``doesn't'' in the first search request.)
+Because no characters are specified for the second search,
+the editor scans the buffer for the next occurrence of the
+characters ``does''.
+.PP
+Edit normally searches forward through the buffer,
+wrapping around from the end of the buffer to the beginning,
+until the specified character string is found.
+If you want to search in the reverse direction,
+use question marks (?) instead of slashes
+to surround the characters you are searching for.
+.PP
+It is also possible
+to repeat the last substitution
+without having to retype the entire command.
+An ampersand (&) used as a command
+repeats the most recent substitute command,
+using the same search and replacement patterns.
+After altering the current line by typing
+.DS I 1i
+:\|\fBs/text/texts/
+.R
+.DE
+you type
+.DS I 1i
+:\|\fB/text/&
+.R
+.DE
+or simply
+.DS I 1i
+:\|\fB//&
+.R
+.DE
+to make the same change on the next line in the buffer
+containing the characters ``text''.
+.SH
+Special characters
+.PP
+Two characters have special meanings when
+used in specifying searches:  ``$'' and ``^''.
+``$'' is taken by the editor to mean ``end of the line''
+and is used to identify strings
+that occur at the end of a line.
+.DS I 1i
+:\|\fBg/text.$/s//material./p
+.R
+.DE
+tells the editor to search for all lines ending in ``text.''
+(and nothing else, not even a blank space),
+to change each final ``text.'' to ``material.'',
+and print the changed lines.
+.PP
+The symbol ``^'' indicates the beginning of a line.
+Thus,
+.DS I 1i
+:\|\fBs/^/1. /
+.R
+.DE
+instructs the editor to insert ``1.'' and a space at the beginning
+of the current line.
+.PP
+The characters ``$'' and ``^'' have special meanings only in the context
+of searching.
+At other times, they are ordinary characters.
+If you ever need to search for a character that has a special meaning,
+you must indicate that the
+character is to lose temporarily
+its special significance by typing another special character,
+the backslash (\\), before it.
+.DS I 1i
+:\|\fBs/\\\\\&$/dollar/
+.R
+.DE
+looks for the character ``$'' in the current
+line and replaces it by the word ``dollar''.
+Were it not for the backslash, the ``$'' would have represented
+``the end of the line'' in your search
+rather than the character ``$''.
+The backslash retains its special significance
+unless it is preceded by another backslash.
+.SH
+Issuing \s-2UNIX\s0 commands from the editor
+.PP
+After creating several files with the editor,
+you may want to delete files
+no longer useful to you or ask for a list of your files.
+Removing and listing files are not functions of the editor,
+and so they require the use of \s-2UNIX\s0 system commands
+(also referred to as ``shell'' commands, as
+``shell'' is the name of the program that processes \s-2UNIX\s0 commands).
+You do not need to quit the editor to execute a \s-2UNIX\s0 command
+as long as you indicate that it
+is to be sent to the shell for execution.
+To use the \s-2UNIX\s0 command
+.B rm
+to remove the file named ``junk'' type:
+.DS I 1i
+:\|\fB!rm junk
+.R
+!
+:
+.DE
+The exclamation mark (!)
+indicates that the rest of the line is to be processed as a shell command.
+If the buffer contents have not been written since the last change,
+a warning will be printed before the command is executed:
+.DS I 1i
+[No write since last change]
+.DE
+The editor prints a ``!'' when the command is completed.
+Other tutorials describe useful features of the system,
+of which an editor is only one part.
+.SH
+Filenames and file manipulation
+.PP
+Throughout each editing session,
+edit keeps track of the name of the file being edited as the
+.I "current filename."
+Edit remembers as the current filename the name given
+when you entered the editor.
+The current filename changes whenever the edit (e) command
+is used to specify a new file.
+Once edit has recorded a current filename,
+it inserts that name into any command where a filename has been omitted.
+If a write command does not specify a file,
+edit, as we have seen, supplies the current filename.
+If you are editing a file named ``draft3'' having 283 lines in it,
+you can have the editor write onto a different file
+by including its name in the write command:
+.DS I 1i
+:\fB\|w chapter3
+.R
+"chapter3" [new file] 283 lines, 8698 characters
+.DE
+The current filename remembered by the editor
+.I
+will not be changed as a result of the write command.
+.R
+Thus, if the next write command
+does not specify a name,
+edit will write onto the current file (``draft3'')
+and not onto the file ``chapter3''.
+.SH
+The file (f) command
+.PP
+To ask for the current filename, type
+.B file
+(or
+.B f ).
+In response, the editor provides current information about the buffer,
+including the filename, your current position, the number of
+lines in the buffer,
+and the percent of the distance through the file
+your current location is.
+.DS I 1i
+:\|\fBf
+.R
+"text" [Modified] line 3 of 4 --75%--
+.DE
+.\"The expression ``[Edited]'' indicates that the buffer contains
+.\"either the editor's copy of the existing file ``text''
+.\"or a file which you are just now creating.
+If the contents of the buffer have changed
+since the last time the file was written,
+the editor will tell you that the file has been ``[Modified]''.
+After you save the changes by writing onto a disk file,
+the buffer will no longer be considered modified:
+.DS I 1i
+:\|\fBw
+.R
+"text" 4 lines, 88 characters
+:\|\fBf
+.R
+"text" line 3 of 4 --75%--
+.DE
+.SH
+Reading additional files (r)
+.PP
+The
+\f3read (r)\f1 command allows you to add the contents of a file
+to the buffer
+at a specified location,
+essentially copying new lines
+between two existing lines.
+To use it, specify the line after which the new text will be placed,
+the \f3read (r)\f1 command,
+and then the name of the file.
+If you have a file named ``example'', the command
+.DS I 1i
+:\|\fB$r example
+.R
+"example" 18 lines, 473 characters
+.DE
+reads the file ``example''
+and adds it to the buffer after the last line.
+The current filename is not changed by the read command.
+.SH
+Writing parts of the buffer
+.PP
+The
+.B
+write (w)
+.R
+command can write all or part of the buffer
+to a file you specify.
+We are already familiar with
+writing the entire contents of the
+buffer to a disk file.
+To write only part of the buffer onto a file,
+indicate the beginning and ending lines before the write command,
+for example
+.DS I 1i
+:\|\fB45,$w ending
+.R
+.DE
+Here all lines from 45 through the end of the buffer
+are written onto the file named
+.I ending.
+The lines remain in the buffer
+as part of the document you are editing,
+and you may continue to edit the entire buffer.
+Your original file is unaffected
+by your command to write part of the buffer
+to another file.
+Edit still remembers whether you have saved changes to the buffer
+in your original file or not.
+.SH
+Recovering files
+.PP
+Although it does not happen very often,
+there are times \s-2UNIX\s+2 stops working
+because of some malfunction.
+This situation is known as a \fIcrash\fR.
+Under most circumstances,
+edit's crash recovery feature
+is able to save work to within a few lines of changes
+before a crash (or an accidental phone hang up).
+If you lose the contents of an editing buffer in a system crash,
+you will normally receive mail when you login that gives
+the name of the recovered file.
+To recover the file,
+enter the editor and type the command
+.B recover
+(\fBrec\fR),
+followed by the name of the lost file.
+For example,
+to recover the buffer for an edit session
+involving the file ``chap6'', the command is:
+.DS I 1i
+.R
+:\|\fBrecover chap6
+.R
+.DE
+Recover is sometimes unable to save the entire buffer successfully,
+so always check the contents of the saved buffer carefully
+before writing it back onto the original file.
+For best results,
+write the buffer to a new file temporarily
+so you can examine it without risk to the original file.
+Unfortunately,
+you cannot use the recover command
+to retrieve a file you removed
+using the shell command \f3rm\f1.
+.SH
+Other recovery techniques
+.PP
+If something goes wrong when you are using the editor,
+it may be possible to save your work by using the command
+.B preserve
+(\fBpre\fR),
+which saves the buffer as if the system had crashed.
+If you are writing a file and you get the message
+``Quota exceeded'', you have tried to use more disk storage
+than is allotted to your account.
+.I
+Proceed with caution
+.R
+because it is likely that only a part
+of the editor's buffer is now present in the file you tried to write.
+In this case you should use the shell escape from the editor (!)
+to remove some files you don't need and try to write
+the file again.
+If this is not possible and you cannot find someone to help you,
+enter the command
+.DS I 1i
+:\|\fBpreserve
+.R
+.DE
+and wait for the reply,
+.DS I 1i
+File preserved.
+.DE
+If you do not receive this reply,
+seek help immediately.
+Do not simply leave the editor.
+If you do, the buffer will be lost, 
+and you may not be able to save your file.
+If the reply is ``File preserved.''
+you can leave the editor
+(or logout)
+to remedy the situation.
+After a preserve, you can use the recover command
+once the problem has been corrected,
+or the \fB\-r\fR option of the edit command
+if you leave the editor and want to return.
+.PP
+If you make an undesirable change to the buffer
+and type a write command before discovering your mistake,
+the modified version will replace any previous version of the file.
+Should you ever lose a good version of a document in this way,
+do not panic and leave the editor.
+As long as you stay in the editor,
+the contents of the buffer remain accessible.
+Depending on the nature of the problem,
+it may be possible
+to restore the buffer to a more complete
+state with the undo command.
+After fixing the damaged buffer, you can again write the file
+to disk.
+.SH
+Further reading and other information
+.PP
+Edit is an editor designed for beginning and casual users.
+It is actually a version of a more powerful editor called
+.I ex.
+These lessons are intended to introduce you to the editor
+and its more commonly-used commands.
+We have not covered all of the editor's commands,
+but a selection of commands
+that should be sufficient to accomplish most of your editing tasks.
+You can find out more about the editor in the
+.I
+Ex Reference Manual,
+.R
+which is applicable to both
+.I ex
+and
+.I edit.
+One way to become familiar with the manual is to begin by reading
+the description of commands that you already know.
+.bd I 3
+.SH
+Using
+.I ex
+.fl
+.bd I
+.PP
+As you become more experienced with using the editor,
+you may still find that edit continues to meet your needs.
+However, should you become interested in using 
+.I ex,
+it is easy to switch.
+To begin an editing session with 
+.I ex,
+use the name
+.B ex
+in your command instead of
+.B edit.
+.PP
+Edit commands also work in 
+.I ex,
+but the editing environment is somewhat different.
+You should be aware of a few differences
+between 
+.I ex
+and 
+.I edit.
+In edit, only the characters ``^'', ``$'', and ``\\'' have
+special meanings in searching the buffer
+or indicating characters to be changed by a substitute command.
+Several additional characters have special
+meanings in ex, as described in the
+.I
+Ex Reference Manual.
+.R
+Another feature of the edit environment prevents users from
+accidently entering two alternative modes of editing,
+.I open
+and
+.I visual,
+in which
+the editor behaves quite differently from normal command mode.
+If you are using ex and you encounter strange behavior,
+you may have accidently entered open mode by typing ``o''.
+Type the \s-2ESC\s0 key and then a ``Q''
+to get out of open or visual mode and back into
+the regular editor command mode.
+The document
+.I
+An Introduction to Display Editing with Vi\|\|
+.R
+provide full details of visual mode.
+.bp
+.SH
+.ce 1
+\s+2Index\s0
+.LP
+.sp 2
+.2C
+.nf
+addressing, \fIsee\fR line numbers
+ampersand, 20
+append mode, 6-7
+append (a) command, 6, 7, 9
+``At end of file'' (message), 18
+backslash (\\), 21
+buffer, 3
+caret (^), 10, 20
+change (c) command, 18
+command mode, 5-6
+``Command not found'' (message), 6
+context search, 10-12, 19-21
+control characters (``^'' notation), 10
+control-H, 7
+copy (co) command, 15
+corrections, 7, 16
+current filename, 21
+current line (\|.\|), 11, 17
+delete (d) command, 15-16
+dial-up, 5
+disk, 3
+documentation, 3, 23
+dollar ($), 10, 11, 17, 20-21
+dot (\f3\|.\|\f1) 11, 17
+edit (text editor), 3, 5, 23
+edit (e) command, 5, 9, 14
+editing commands:
+.in +.25i
+append (a), 6, 7, 9
+change (c), 18
+copy (co), 15
+delete (d), 15-16
+edit (text editor), 3, 5, 23
+edit (e), 5, 9, 14
+file (f), 21-22
+global (g), 19
+move (m), 14-15
+number (nu), 11
+preserve (pre), 22-23
+print (p), 10
+quit (q), 8, 13
+read (r), 22
+recover (rec), 22, 23
+substitute (s), 11-12, 19, 20
+undo (u), 16-17, 23
+write (w), 8, 13, 21, 22
+z, 12-13
+! (shell escape), 21
+$=, 17
++, 17
+\-, 17
+//, 12, 20
+??, 20
+\&., 11, 17
+\&.=, 11, 17
+.in -.25i
+entering text, 3, 6-7
+erasing
+.in +.25i
+characters (^H), 7
+lines (@), 7
+.in -.25i
+error corrections, 7, 16
+ex (text editor), 23
+\fIEx Reference Manual\fR, 23
+exclamation (!), 21
+file, 3
+file (f) command, 21-22
+file recovery, 22-23
+filename, 3, 21
+global (g) command, 19
+input mode, 6-7
+Interrupt (message), 9
+line numbers, \fIsee also\fR current line
+.in +.25i
+dollar sign ($), 10, 11, 17
+dot (\|.\|), 11, 17
+relative (+ and \-), 17
+.in -.25i
+list, 10
+logging in, 4-6
+logging out, 8
+``Login incorrect'' (message), 5
+minus (\-), 17
+move (m) command, 14-15
+``Negative address\(emfirst buffer line is 1'' (message), 18
+``No current filename'' (message), 8
+``No such file or directory'' (message), 5, 6
+``No write since last change'' (message), 21
+non-printing characters, 10
+``Nonzero address required'' (message), 18
+``Not an editor command'' (message), 6
+``Not that many lines in buffer'' (message), 18
+number (nu) command, 11
+password, 5
+period (\|.\|), 11, 17
+plus (+), 17
+preserve (pre) command, 22-23
+print (p) command, 10
+program, 3
+prompts
+.in .25i
+% (\s-2UNIX\s0), 5
+: (edit), 5, 6, 7
+\0 (append), 7
+.in -.25i
+question (?), 20
+quit (q) command, 8, 13
+read (r) command, 22
+recover (rec) command, 22, 23
+recovery, \fIsee\fR\| file recovery
+references, 3, 23
+remove (rm) command, 21, 22
+reverse command effects (undo), 16-17, 23
+searching, 10-12, 19-21
+shell, 21
+shell escape (!), 21
+slash (/), 11-12, 20
+special characters (^, $, \\), 10, 11, 17, 20-21
+substitute (s) command, 11-12, 19, 20
+terminals, 4-5
+text input mode, 7
+undo (u) command, 16-17, 23
+\s-1UNIX\s0, 3
+write (w) command, 8, 13, 21, 22
+z command, 12-13
+
diff --git a/dist/nvi/docs/exref/Makefile b/dist/nvi/docs/exref/Makefile
new file mode 100644 (file)
index 0000000..61bc7a8
--- /dev/null
@@ -0,0 +1,33 @@
+# Id: Makefile,v 8.10 2001/01/28 15:50:07 skimo Exp (Berkeley) Date: 2001/01/28 15:50:07
+
+ROFF=  groff
+TBL=   tbl
+
+ALL= exref.ps summary.ps ../html/exref.html ../html/ex-summary.html
+
+all: $(ALL)
+
+../html/exref.html: ex.rm
+       test -d ../html || mkdir ../html
+       ${TBL} $< | ${ROFF} -ms -Thtml | \
+           sed 's/<img src="$<.*png">//' > $@
+       rm -f "$<"*png
+       chmod 444 $@
+
+../html/ex-summary.html: ex.summary
+       test -d ../html || mkdir ../html
+       ${TBL} $< | ${ROFF} -ms -Thtml | \
+           sed 's/<img src="$<.*png">//' > $@
+       rm -f "$<"*png
+       chmod 444 $@
+
+exref.ps: ex.rm
+       ${TBL} $< | ${ROFF} -ms > $@
+       chmod 444 $@
+
+summary.ps: ex.summary
+       ${TBL} $< | ${ROFF} -ms > $@
+       chmod 444 $@
+
+clean:
+       rm -f $(ALL)
diff --git a/dist/nvi/docs/exref/ex.rm b/dist/nvi/docs/exref/ex.rm
new file mode 100644 (file)
index 0000000..37703f3
--- /dev/null
@@ -0,0 +1,2187 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: ex.rm,v 8.5 1996/08/18 11:36:16 bostic Exp (Berkeley) Date: 1996/08/18 11:36:16
+.\"
+.nr LL 6.5i
+.nr FL 6.5i
+.EH 'USD:12-%''Ex Reference Manual'
+.OH 'Ex Reference Manual''USD:12-%'
+.nr )P 0
+.de ZP
+.nr pd \\n()P
+.nr )P 0
+.if \\n(.$=0 .IP
+.if \\n(.$=1 .IP "\\$1"
+.if \\n(.$>=2 .IP "\\$1" "\\$2"
+.nr )P \\n(pd
+.rm pd
+..
+.de LC
+.br
+.sp .1i
+.ne 4
+.LP
+.ta 4.0i
+..
+.bd S B 3
+.\".RP
+.TL
+Ex Reference Manual
+.br
+Version 3.7
+.AU
+William Joy
+.AU
+Mark Horton
+.AI
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, Ca.  94720
+.AB
+.I Ex
+a line oriented text editor, which supports both command and display
+oriented editing.
+This reference manual describes the command oriented part of
+.I ex;
+the display editing features of
+.I ex
+are described in
+.I "An Introduction to Display Editing with Vi."
+Other documents about the editor include the introduction
+.I "Edit: A tutorial",
+the
+.I "Ex/edit Command Summary",
+and a
+.I "Vi Quick Reference"
+card.
+.AE
+.NH 1
+Starting ex
+.PP
+.FS
+The financial support of an \s-2IBM\s0 Graduate Fellowship and the National
+Science Foundation under grants MCS74-07644-A03 and MCS78-07291 is gratefully
+acknowledged.
+.FE
+Each instance of the editor has a set of options,
+which can be set to tailor it to your liking.
+The command
+.I edit
+invokes a version of
+.I ex
+designed for more casual or beginning
+users by changing the default settings of some of these options.
+To simplify the description which follows we
+assume the default settings of the options.
+.PP
+When invoked,
+.I ex
+determines the terminal type from the \s-2TERM\s0 variable in the environment.
+It there is a \s-2TERMCAP\s0 variable in the environment, and the type
+of the terminal described there matches the \s-2TERM\s0 variable,
+then that description
+is used.  Also if the \s-2TERMCAP\s0 variable contains a pathname (beginning
+with a \fB/\fR) then the editor will seek the description of the terminal
+in that file (rather than the default /etc/termcap).
+If there is a variable \s-2EXINIT\s0 in the environment, then the editor
+will execute the commands in that variable,
+otherwise if there is a file
+.I \&.exrc
+in your \s-2HOME\s0 directory
+.I ex
+reads commands from that file, simulating a
+.I source
+command.
+Option setting commands placed in
+\s-2EXINIT\s0 or
+.I \&.exrc
+will be executed before each editor session.
+.PP
+A command to enter
+.I ex
+has the following prototype:\(dg
+.FS
+\(dg Brackets `[' `]' surround optional parameters here.
+.FE
+.DS
+\fBex\fP [ \fB\-\fP ] [ \fB\-v\fP ] [ \fB\-t\fP \fItag\fP ] [ \fB\-r\fP ] [ \fB\-l\fP ] [ \fB\-w\fP\fIn\fP ] [ \fB\-x\fP ] [ \fB\-R\fP ] [ \fB+\fP\fIcommand\fP ] name ...
+.DE
+The most common case edits a single file with no options, i.e.:
+.DS
+\fBex\fR name
+.DE
+The
+.B \-
+command line option
+option suppresses all interactive-user feedback
+and is useful in processing editor scripts in command files.
+The
+.B \-v
+option is equivalent to using
+.I vi
+rather than
+.I ex.
+The
+.B \-t
+option is equivalent to an initial
+.I tag
+command, editing the file containing the
+.I tag
+and positioning the editor at its definition.
+The
+.B \-r
+option is used in recovering after an editor or system crash,
+retrieving the last saved version of the named file or,
+if no file is specified,
+typing a list of saved files.
+The
+.B \-l
+option sets up for editing \s-2LISP\s0, setting the
+.I showmatch
+and
+.I lisp
+options.
+The
+.B \-w
+option sets the default window size to
+.I n,
+and is useful on dialups to start in small windows.
+The
+.B \-x
+option causes
+.I ex
+to prompt for a
+.I key ,
+which is used to encrypt and decrypt the contents of the file,
+which should already be encrypted using the same key,
+see
+.I crypt (1).
+The
+.B \-R
+option sets the
+.I readonly
+option at the start.
+.I Name
+arguments indicate files to be edited.
+An argument of the form
+\fB+\fIcommand\fR
+indicates that the editor should begin by executing the specified command.
+If
+.I command
+is omitted, then it defaults to ``$'', positioning the editor at the last
+line of the first file initially.  Other useful commands here are scanning
+patterns of the form ``/pat'' or line numbers, e.g. ``+100'' starting
+at line 100.
+.NH 1
+File manipulation
+.NH 2
+Current file
+.PP
+.I Ex
+is normally editing the contents of a single file,
+whose name is recorded in the
+.I current
+file name.
+.I Ex
+performs all editing actions in a buffer
+(actually a temporary file)
+into which the text of the file is initially read.
+Changes made to the buffer have no effect on the file being
+edited unless and until the buffer contents are written out to the
+file with a
+.I write
+command.
+After the buffer contents are written,
+the previous contents of the written file are no longer accessible.
+When a file is edited,
+its name becomes the current file name,
+and its contents are read into the buffer.
+.PP
+The current file is almost always considered to be
+.I edited.
+This means that the contents of the buffer are logically
+connected with the current file name,
+so that writing the current buffer contents onto that file,
+even if it exists,
+is a reasonable action.
+If the current file is not 
+.I edited
+then
+.I ex
+will not normally write on it if it already exists.*
+.FS
+* The
+.I file
+command will say ``[Not edited]'' if the current file is not considered
+edited.
+.FE
+.NH 2
+Alternate file
+.PP
+Each time a new value is given to the current file name,
+the previous current file name is saved as the
+.I alternate
+file name.
+Similarly if a file is mentioned but does not become the current file,
+it is saved as the alternate file name.
+.NH 2
+Filename expansion
+.PP
+Filenames within the editor may be specified using the normal
+shell expansion conventions.
+In addition,
+the character `%' in filenames is replaced by the
+.I current
+file name and the character
+`#' by the
+.I alternate
+file name.\(dg
+.FS
+\(dg This makes it easy to deal alternately with
+two files and eliminates the need for retyping the
+name supplied on an
+.I edit
+command after a 
+.I "No write since last change"
+diagnostic is received.
+.FE
+.NH 2
+Multiple files and named buffers
+.PP
+If more than one file is given on the command line,
+then the first file is edited as described above.
+The remaining arguments are placed with the first file in the
+.I "argument list."
+The current argument list may be displayed with the
+.I args
+command.
+The next file in the argument list may be edited with the
+.I next
+command.
+The argument list may also be respecified by specifying
+a list of names to the
+.I next
+command.
+These names are expanded,
+the resulting list of names becomes the new argument list,
+and
+.I ex
+edits the first file on the list.
+.PP
+For saving blocks of text while editing, and especially when editing
+more than one file,
+.I ex
+has a group of named buffers.
+These are similar to the normal buffer, except that only a limited number
+of operations are available on them.
+The buffers have names
+.I a
+through
+.I z.\(dd
+.FS
+\(dd It is also possible to refer to
+.I A
+through
+.I Z;
+the upper case buffers are the same as the lower but commands
+append to named buffers rather than replacing
+if upper case names are used.
+.FE
+.NH 2
+Read only
+.PP
+It is possible to use
+.I ex
+in
+.I "read only"
+mode to look at files that you have no intention of modifying.
+This mode protects you from accidently overwriting the file.
+Read only mode is on when the
+.I readonly
+option is set.
+It can be turned on with the
+.B \-R
+command line option,
+by the
+.I view
+command line invocation,
+or by setting the
+.I readonly
+option.
+It can be cleared by setting
+.I noreadonly .
+It is possible to write, even while in read only mode, by indicating
+that you really know what you are doing.
+You can write to a different file, or can use the ! form of write,
+even while in read only mode.
+.NH 1
+Exceptional Conditions
+.NH 2
+Errors and interrupts
+.PP
+When errors occur
+.I ex
+(optionally) rings the terminal bell and, in any case, prints an error
+diagnostic.  If the primary input is from a file, editor processing
+will terminate.  If an interrupt signal is received,
+.I ex
+prints ``Interrupt'' and returns to its command level.  If the primary
+input is a file, then
+.I ex
+will exit when this occurs.
+.NH 2
+Recovering from hangups and crashes
+.PP
+If a hangup signal is received and the buffer has been modified since
+it was last written out, or if the system crashes, either the editor
+(in the first case) or the system (after it reboots in the second) will
+attempt to preserve the buffer.  The next time you log in you should be
+able to recover the work you were doing, losing at most a few lines of
+changes from the last point before the hangup or editor crash.  To
+recover a file you can use the
+.B \-r
+option.  If you were editing the file
+.I resume,
+then you should change
+to the directory where you were when the crash occurred, giving the command
+.DS
+\fBex \-r\fP\fI resume\fP
+.DE
+After checking that the retrieved file is indeed ok, you can
+.I write
+it over the previous contents of that file.
+.PP
+You will normally get mail from the system telling you when a file has
+been saved after a crash.  The command
+.DS
+\fBex\fP \-\fBr\fP
+.DE
+will print a list of the files which have been saved for you.
+(In the case of a hangup,
+the file will not appear in the list,
+although it can be recovered.)
+.NH 1
+Editing modes
+.PP
+.I Ex
+has five distinct modes.  The primary mode is
+.I command
+mode.  Commands are entered in command mode when a `:' prompt is
+present, and are executed each time a complete line is sent.  In
+.I "text input"
+mode
+.I ex
+gathers input lines and places them in the file.  The
+.I append,
+.I insert,
+and
+.I change
+commands use text input mode.
+No prompt is printed when you are in text input mode.
+This mode is left by typing a `.' alone at the beginning of a line, and
+.I command
+mode resumes.
+.PP
+The last three modes are
+.I open
+and
+.I visual
+modes, entered by the commands of the same name, and, within open and
+visual modes
+.I "text insertion"
+mode.
+.I Open
+and
+.I visual
+modes allow local editing operations to be performed on the text in the
+file.  The
+.I open
+command displays one line at a time on any terminal while
+.I visual
+works on \s-2CRT\s0 terminals with random positioning cursors, using the
+screen as a (single) window for file editing changes.
+These modes are described (only) in
+.I "An Introduction to Display Editing with Vi."
+.NH 
+Command structure
+.PP
+Most command names are English words,
+and initial prefixes of the words are acceptable abbreviations.
+The ambiguity of abbreviations is resolved in favor of the more commonly
+used commands.*
+.FS
+* As an example, the command 
+.I substitute
+can be abbreviated `s'
+while the shortest available abbreviation for the 
+.I set
+command is `se'.
+.FE
+.NH 2
+Command parameters
+.PP
+Most commands accept prefix addresses specifying the lines in the file
+upon which they are to have effect.
+The forms of these addresses will be discussed below.
+A number of commands also may take a trailing
+.I count
+specifying the number of lines to be involved in the command.\(dg
+.FS
+\(dg Counts are rounded down if necessary.
+.FE
+Thus the command ``10p'' will print the tenth line in the buffer while
+``delete 5'' will delete five lines from the buffer,
+starting with the current line.
+.PP
+Some commands take other information or parameters,
+this information always being given after the command name.\(dd
+.FS
+\(dd Examples would be option names in a
+.I set
+command i.e. ``set number'',
+a file name in an
+.I edit
+command,
+a regular expression in a
+.I substitute
+command,
+or a target address for a
+.I copy
+command, i.e. ``1,5 copy 25''.
+.FE
+.NH 2
+Command variants
+.PP
+A number of commands have two distinct variants.
+The variant form of the command is invoked by placing an
+`!' immediately after the command name.
+Some of the default variants may be controlled by options;
+in this case, the `!' serves to toggle the default.
+.NH 2
+Flags after commands
+.PP
+The characters `#', `p' and `l' may be placed after many commands.**
+.FS
+**
+A `p' or `l' must be preceded by a blank or tab
+except in the single special case `dp'.
+.FE
+In this case, the command abbreviated by these characters
+is executed after the command completes.
+Since
+.I ex
+normally prints the new current line after each change, `p' is rarely necessary.
+Any number of `+' or `\-' characters may also be given with these flags.
+If they appear, the specified offset is applied to the current line
+value before the printing command is executed.
+.NH 2
+Comments
+.PP
+It is possible to give editor commands which are ignored.
+This is useful when making complex editor scripts
+for which comments are desired.
+The comment character is the double quote: ".
+Any command line beginning with " is ignored.
+Comments beginning with " may also be placed at the ends
+of commands, except in cases where they could be confused as part
+of text (shell escapes and the substitute and map commands).
+.NH 2
+Multiple commands per line
+.PP
+More than one command may be placed on a line by separating each pair
+of commands by a `|' character.
+However the
+.I global
+commands,
+comments,
+and the shell escape `!'
+must be the last command on a line, as they are not terminated by a `|'.
+.NH 2
+Reporting large changes
+.PP
+Most commands which change the contents of the editor buffer give
+feedback if the scope of the change exceeds a threshold given by the
+.I report
+option.
+This feedback helps to detect undesirably large changes so that they may
+be quickly and easily reversed with an
+.I undo.
+After commands with more global effect such as
+.I global
+or
+.I visual,
+you will be informed if the net change in the number of lines
+in the buffer during this command exceeds this threshold.
+.NH 1
+Command addressing
+.NH 2
+Addressing primitives
+.IP \fB.\fR 20
+The current line.
+Most commands leave the current line as the last line which they affect.
+The default address for most commands is the current line,
+thus `\fB.\fR' is rarely used alone as an address.
+.IP \fIn\fR 20
+The \fIn\fRth line in the editor's buffer, lines being numbered
+sequentially from 1.
+.IP \fB$\fR 20
+The last line in the buffer.
+.IP \fB%\fR 20
+An abbreviation for ``1,$'', the entire buffer.
+.IP \fI+n\fR\ \fI\-n\fR 20
+An offset relative to the current buffer line.\(dg
+.FS
+\(dg
+The forms `.+3' `+3' and `+++' are all equivalent;
+if the current line is line 100 they all address line 103.
+.FE
+.IP \fB/\fIpat\fR\fB/\fR\ \fB?\fIpat\fR\fB?\fR 20
+Scan forward and backward respectively for a line containing \fIpat\fR, a
+regular expression (as defined below).  The scans normally wrap around the end
+of the buffer.
+If all that is desired is to print the next line containing \fIpat\fR, then
+the trailing \fB/\fR or \fB?\fR may be omitted.
+If \fIpat\fP is omitted or explicitly empty, then the last
+regular expression specified is located.\(dd
+.FS
+\(dd The forms \fB\e/\fP and \fB\e?\fP scan
+using the last regular expression used in a scan; after a substitute
+\fB//\fP and \fB??\fP would scan using the substitute's regular expression.
+.FE
+.IP \fB\(aa\(aa\fP\ \fB\(aa\fP\fIx\fP 20
+Before each non-relative motion of the current line `\fB.\fP',
+the previous current line is marked with a tag, subsequently referred to as
+`\(aa\(aa'.
+This makes it easy to refer or return to this previous context.
+Marks may also be established by the
+.I mark
+command, using single lower case letters
+.I x
+and the marked lines referred to as
+`\(aa\fIx\fR'.
+.NH 2
+Combining addressing primitives
+.PP
+Addresses to commands consist of a series of addressing primitives,
+separated by `,' or `;'.
+Such address lists are evaluated left-to-right.
+When addresses are separated by `;' the current line `\fB.\fR'
+is set to the value of the previous addressing expression
+before the next address is interpreted.
+If more addresses are given than the command requires,
+then all but the last one or two are ignored.
+If the command takes two addresses, the first addressed line must
+precede the second in the buffer.\(dg
+.FS
+\(dg Null address specifications are permitted in a list of addresses,
+the default in this case is the current line `.';
+thus `,100' is equivalent to `\fB.\fR,100'.
+It is an error to give a prefix address to a command which expects none.
+.FE
+.NH 1
+Command descriptions
+.PP
+The following form is a prototype for all
+.I ex
+commands:
+.DS
+\fIaddress\fR \fBcommand\fR \fI! parameters count flags\fR
+.DE
+All parts are optional; the degenerate case is the empty command which prints
+the next line in the file.  For sanity with use from within
+.I visual
+mode,
+.I ex
+ignores a ``:'' preceding any command.
+.PP
+In the following command descriptions, the
+default addresses are shown in parentheses,
+which are
+.I not,
+however,
+part of the command.
+.LC
+\fBabbreviate\fR \fIword rhs\fP        abbr: \fBab\fP
+.ZP
+Add the named abbreviation to the current list.
+When in input mode in visual, if
+.I word
+is typed as a complete word, it will be changed to
+.I rhs .
+.LC
+( \fB.\fR ) \fBappend\fR       abbr: \fBa\fR
+.br
+\fItext\fR
+.br
+\&\fB.\fR
+.ZP
+Reads the input text and places it after the specified line.
+After the command, `\fB.\fR'
+addresses the last line input or the
+specified line if no lines were input.
+If address `0' is given,
+text is placed at the beginning of the buffer.
+.LC
+\fBa!\fR
+.br
+\fItext\fR
+.br
+\&\fB.\fR
+.ZP
+The variant flag to
+.I append
+toggles the setting for the
+.I autoindent
+option during the input of
+.I text.
+.LC
+\fBargs\fR
+.ZP
+The members of the argument list are printed, with the current argument
+delimited by `[' and `]'.
+.ig
+.PP
+\fBcd\fR \fIdirectory\fR
+.ZP
+The
+.I cd
+command is a synonym for
+.I chdir.
+..
+.LC
+( \fB.\fP , \fB.\fP ) \fBchange\fP \fIcount\fP abbr: \fBc\fP
+.br
+\fItext\fP
+.br
+\&\fB.\fP
+.ZP
+Replaces the specified lines with the input \fItext\fP.
+The current line becomes the last line input;
+if no lines were input it is left as for a
+\fIdelete\fP.
+.LC
+\fBc!\fP
+.br
+\fItext\fP
+.br
+\&\fB.\fP
+.ZP
+The variant toggles
+.I autoindent
+during the
+.I change.
+.ig
+.LC
+\fBchdir\fR \fIdirectory\fR
+.ZP
+The specified \fIdirectory\fR becomes the current directory.
+If no directory is specified, the current value of the
+.I home
+option is used as the target directory.
+After a
+.I chdir
+the current file is not considered to have been
+edited so that write restrictions on pre-existing files apply.
+..
+.LC
+( \fB.\fP , \fB.\fP )\|\fBcopy\fP \fIaddr\fP \fIflags\fP       abbr: \fBco\fP
+.ZP
+A
+.I copy
+of the specified lines is placed after
+.I addr,
+which may be `0'.
+The current line
+`\fB.\fR'
+addresses the last line of the copy.
+The command
+.I t
+is a synonym for
+.I copy.
+.LC
+( \fB.\fR , \fB.\fR )\|\fBdelete\fR \fIbuffer\fR \fIcount\fR \fIflags\fR       abbr: \fBd\fR
+.ZP
+Removes the specified lines from the buffer.
+The line after the last line deleted becomes the current line;
+if the lines deleted were originally at the end,
+the new last line becomes the current line.
+If a named
+.I buffer
+is specified by giving a letter,
+then the specified lines are saved in that buffer,
+or appended to it if an upper case letter is used.
+.LC
+\fBedit\fR \fIfile\fR  abbr: \fBe\fR
+.br
+\fBex\fR \fIfile\fR
+.ZP
+Used to begin an editing session on a new file.
+The editor
+first checks to see if the buffer has been modified since the last
+.I write
+command was issued.
+If it has been,
+a warning is issued and the
+command is aborted.
+The
+command otherwise deletes the entire contents of the editor buffer,
+makes the named file the current file and prints the new filename.
+After insuring that this file is sensible\(dg
+.FS
+\(dg I.e., that it is not a binary file such as a directory,
+a block or character special file other than
+.I /dev/tty,
+a terminal,
+or a binary or executable file
+(as indicated by the first word).
+.FE
+the editor reads the file into its buffer.
+.IP
+If the read of the file completes without error,
+the number of lines and characters read is typed.
+If there were any non-\s-2ASCII\s0 characters
+in the file they are stripped of their non-\s-2ASCII\s0
+high bits,
+and any null characters in the file are discarded.
+If none of these errors occurred, the file is considered
+.I edited.
+If the last line of the input file is missing the trailing
+newline character, it will be supplied and a complaint will be issued.
+This command leaves the current line `\fB.\fR' at the last line read.\(dd
+.FS
+\(dd If executed from within
+.I open
+or
+.I visual,
+the current line is initially the first line of the file.
+.FE
+.LC
+\fBe!\fR \fIfile\fR
+.ZP
+The variant form suppresses the complaint about modifications having
+been made and not written from the editor buffer, thus
+discarding all changes which have been made before editing the new file.
+.LC
+\fBe\fR \fB+\fIn\fR \fIfile\fR
+.ZP
+Causes the editor to begin at line
+.I n
+rather than at the last line;
+\fIn\fR may also be an editor command containing no spaces, e.g.: ``+/pat''.
+.LC
+\fBfile\fR     abbr: \fBf\fR
+.ZP
+Prints the current file name,
+whether it has been `[Modified]' since the last
+.I write 
+command,
+whether it is
+.I "read only" ,
+the current line,
+the number of lines in the buffer,
+and the percentage of the way through the buffer of the current line.*
+.FS
+* In the rare case that the current file is `[Not edited]' this is
+noted also; in this case you have to use the form \fBw!\fR to write to
+the file, since the editor is not sure that a \fBwrite\fR will not
+destroy a file unrelated to the current contents of the buffer.
+.FE
+.LC
+\fBfile\fR \fIfile\fR
+.ZP
+The current file name is changed to
+.I file
+which is considered 
+`[Not edited]'.
+.LC
+( 1 , $ ) \fBglobal\fR /\fIpat\|\fR/ \fIcmds\fR        abbr: \fBg\fR
+.ZP
+First marks each line among those specified which matches
+the given regular expression.
+Then the given command list is executed with `\fB.\fR' initially
+set to each marked line.
+.IP
+The command list consists of the remaining commands on the current
+input line and may continue to multiple lines by ending all but the
+last such line with a `\e'.
+If
+.I cmds
+(and possibly the trailing \fB/\fR delimiter) is omitted, each line matching
+.I pat
+is printed.
+.I Append,
+.I insert,
+and
+.I change
+commands and associated input are permitted;
+the `\fB.\fR' terminating input may be omitted if it would be on the
+last line of the command list.
+.I Open
+and
+.I visual
+commands are permitted in the command list and take input from the terminal.
+.IP
+The
+.I global
+command itself may not appear in
+.I cmds.
+The
+.I undo
+command is also not permitted there,
+as
+.I undo
+instead can be used to reverse the entire
+.I global
+command.
+The options
+.I autoprint
+and
+.I autoindent
+are inhibited during a
+.I global,
+(and possibly the trailing \fB/\fR delimiter) and the value of the
+.I report
+option is temporarily infinite,
+in deference to a \fIreport\fR for the entire global.
+Finally, the context mark `\'\'' is set to the value of
+`.' before the global command begins and is not changed during a global
+command,
+except perhaps by an
+.I open
+or
+.I visual
+within the
+.I global.
+.LC
+\fBg!\fR \fB/\fIpat\fB/\fR \fIcmds\fR  abbr: \fBv\fR
+.IP
+The variant form of \fIglobal\fR runs \fIcmds\fR at each line not matching
+\fIpat\fR.
+.LC
+( \fB.\fR )\|\fBinsert\fR      abbr: \fBi\fR
+.br
+\fItext\fR
+.br
+\&\fB.\fR
+.ZP
+Places the given text before the specified line.
+The current line is left at the last line input;
+if there were none input it is left at the line before the addressed line.
+This command differs from
+.I append
+only in the placement of text.
+.KS
+.LC
+\fBi!\fR
+.br
+\fItext\fR
+.br
+\&\fB.\fR
+.ZP
+The variant toggles
+.I autoindent
+during the
+.I insert.
+.KE
+.LC
+( \fB.\fR , \fB.\fR+1 ) \fBjoin\fR \fIcount\fR \fIflags\fR     abbr: \fBj\fR
+.ZP
+Places the text from a specified range of lines
+together on one line.
+White space is adjusted at each junction to provide at least
+one blank character, two if there was a `\fB.\fR' at the end of the line,
+or none if the first following character is a `)'.
+If there is already white space at the end of the line,
+then the white space at the start of the next line will be discarded.
+.LC
+\fBj!\fR
+.ZP
+The variant causes a simpler
+.I join
+with no white space processing; the characters in the lines are simply
+concatenated.
+.LC
+( \fB.\fR ) \fBk\fR \fIx\fR
+.ZP
+The
+.I k
+command is a synonym for
+.I mark.
+It does not require a blank or tab before the following letter.
+.LC
+( \fB.\fR , \fB.\fR ) \fBlist\fR \fIcount\fR \fIflags\fR
+.ZP
+Prints the specified lines in a more unambiguous way:
+tabs are printed as `^I'
+and the end of each line is marked with a trailing `$'.
+The current line is left at the last line printed.
+.LC
+\fBmap\fR \fIlhs\fR \fIrhs\fR
+.ZP
+The
+.I map
+command is used to define macros for use in
+.I visual
+mode.
+.I Lhs
+should be a single character, or the sequence ``#n'', for n a digit,
+referring to function key \fIn\fR.  When this character or function key
+is typed in
+.I visual
+mode, it will be as though the corresponding \fIrhs\fR had been typed.
+On terminals without function keys, you can type ``#n''.
+See section 6.9 of the ``Introduction to Display Editing with Vi''
+for more details.
+.LC
+( \fB.\fR ) \fBmark\fR \fIx\fR
+.ZP
+Gives the specified line mark
+.I x,
+a single lower case letter.
+The
+.I x
+must be preceded by a blank or a tab.
+The addressing form `\'x' then addresses this line.
+The current line is not affected by this command.
+.LC
+( \fB.\fR , \fB.\fR ) \fBmove\fR \fIaddr\fR    abbr: \fBm\fR
+.ZP
+The
+.I move
+command repositions the specified lines to be after
+.I addr .
+The first of the moved lines becomes the current line.
+.LC
+\fBnext\fR     abbr: \fBn\fR
+.ZP
+The next file from the command line argument list is edited.
+.LC
+\fBn!\fR
+.ZP
+The variant suppresses warnings about the modifications to the buffer not
+having been written out, discarding (irretrievably) any changes which may
+have been made.
+.LC
+\fBn\fR \fIfilelist\fR
+.br
+\fBn\fR \fB+\fIcommand\fR \fIfilelist\fR
+.ZP
+The specified
+.I filelist
+is expanded and the resulting list replaces the
+current argument list;
+the first file in the new list is then edited.
+If
+.I command
+is given (it must contain no spaces), then it is executed after editing the first such file.
+.LC
+( \fB.\fR , \fB.\fR ) \fBnumber\fR \fIcount\fR \fIflags\fR     abbr: \fB#\fR or \fBnu\fR
+.ZP
+Prints each specified line preceded by its buffer line
+number.
+The current line is left at the last line printed.
+.KS
+.LC
+( \fB.\fR ) \fBopen\fR \fIflags\fR     abbr: \fBo\fR
+.br
+( \fB.\fR ) \fBopen\fR /\fIpat\|\fR/ \fIflags\fR
+.ZP
+Enters intraline editing \fIopen\fR mode at each addressed line.
+If
+.I pat
+is given,
+then the cursor will be placed initially at the beginning of the
+string matched by the pattern.
+To exit this mode use Q.
+See
+.I "An Introduction to Display Editing with Vi"
+for more details.
+.KE
+.LC
+\fBpreserve\fR
+.ZP
+The current editor buffer is saved as though the system had just crashed.
+This command is for use only in emergencies when a
+.I write
+command has resulted in an error and you don't know how to save your work.
+After a
+.I preserve
+you should seek help.
+.LC
+( \fB.\fR , \fB.\fR )\|\fBprint\fR \fIcount\fR abbr: \fBp\fR or \fBP\fR
+.ZP
+Prints the specified lines
+with non-printing characters printed as control characters `^\fIx\fR\|';
+delete (octal 177) is represented as `^?'.
+The current line is left at the last line printed.
+.LC
+( \fB.\fR )\|\fBput\fR \fIbuffer\fR    abbr: \fBpu\fR
+.ZP
+Puts back
+previously
+.I deleted
+or
+.I yanked
+lines.
+Normally used with
+.I delete
+to effect movement of lines,
+or with
+.I yank
+to effect duplication of lines.
+If no
+.I buffer
+is specified, then the last
+.I deleted
+or
+.I yanked
+text is restored.*
+.FS
+* But no modifying commands may intervene between the
+.I delete
+or
+.I yank
+and the
+.I put,
+nor may lines be moved between files without using a named buffer.
+.FE
+By using a named buffer, text may be restored that was saved there at any
+previous time.
+.LC
+\fBquit\fR     abbr: \fBq\fR
+.ZP
+Causes 
+.I ex
+to terminate.
+No automatic write of the editor buffer to a file is performed.
+However,
+.I ex
+issues a warning message if the file has changed
+since the last
+.I write
+command was issued, and does not
+.I quit.\(dg
+.FS
+\(dg \fIEx\fR
+will also issue a diagnostic if there are more files in the argument
+list.
+.FE
+Normally, you will wish to save your changes, and you 
+should give a \fIwrite\fR command;
+if you wish to discard them, use the \fBq!\fR command variant.
+.LC
+\fBq!\fR
+.ZP
+Quits from the editor, discarding changes to the buffer without complaint.
+.LC
+( \fB.\fR ) \fBread\fR \fIfile\fR      abbr: \fBr\fR
+.ZP
+Places a copy of the text of the given file in the
+editing buffer after the specified line.
+If no 
+.I file
+is given the current file name is used.
+The current file name is not changed unless there is none in which
+case
+.I file
+becomes the current name.
+The sensibility restrictions for the 
+.I edit
+command apply here also.
+If the file buffer is empty and there is no current name then
+.I ex
+treats this as an
+.I edit
+command.
+.IP
+Address `0' is legal for this command and causes the file to be read at
+the beginning of the buffer.
+Statistics are given as for the 
+.I edit
+command when the 
+.I read
+successfully terminates.
+After a
+.I read
+the current line is the last line read.\(dd
+.FS
+\(dd Within
+.I open
+and
+.I visual
+the current line is set to the first line read rather than the last.
+.FE
+.LC
+( \fB.\fR ) \fBread\fR  \fB!\fR\fIcommand\fR
+.ZP
+Reads the output of the command
+.I command
+into the buffer after the specified line.
+This is not a variant form of the command, rather a read
+specifying a
+.I command
+rather than a 
+.I filename;
+a blank or tab before the \fB!\fR is mandatory.
+.LC
+\fBrecover \fIfile\fR
+.ZP
+Recovers
+.I file
+from the system save area.
+Used after a accidental hangup of the phone**
+.FS
+** The system saves a copy of the file you were editing only if you
+have made changes to the file.
+.FE
+or a system crash** or
+.I preserve
+command.
+Except when you use
+.I preserve
+you will be notified by mail when a file is saved.
+.LC
+\fBrewind\fR   abbr: \fBrew\fR
+.ZP
+The argument list is rewound, and the first file in the list is edited.
+.LC
+\fBrew!\fR
+.ZP
+Rewinds the argument list discarding any changes made to the current buffer.
+.LC
+\fBset\fR \fIparameter\fR
+.ZP
+With no arguments, prints those options whose values have been
+changed from their defaults;
+with parameter
+.I all
+it prints all of the option values.
+.IP
+Giving an option name followed by a `?'
+causes the current value of that option to be printed.
+The `?' is unnecessary unless the option is Boolean valued.
+Boolean options are given values either by the form
+`set \fIoption\fR' to turn them on or
+`set no\fIoption\fR' to turn them off;
+string and numeric options are assigned via the form
+`set \fIoption\fR=value'.
+.IP
+More than one parameter may be given to 
+.I set \|;
+they are interpreted left-to-right.
+.LC
+\fBshell\fR    abbr: \fBsh\fR
+.IP
+A new shell is created.
+When it terminates, editing resumes.
+.LC
+\fBsource\fR \fIfile\fR        abbr: \fBso\fR
+.IP
+Reads and executes commands from the specified file.
+.I Source
+commands may be nested.
+.LC
+( \fB.\fR , \fB.\fR ) \fBsubstitute\fR /\fIpat\fR\|/\fIrepl\fR\|/ \fIoptions\fR \fIcount\fR \fIflags\fR        abbr: \fBs\fR
+.IP
+On each specified line, the first instance of pattern
+.I pat
+is replaced by replacement pattern
+.I repl.
+If the
+.I global
+indicator option character `g'
+appears, then all instances are substituted;
+if the
+.I confirm
+indication character `c' appears,
+then before each substitution the line to be substituted
+is typed with the string to be substituted marked
+with `\(ua' characters.
+By typing an `y' one can cause the substitution to be performed,
+any other input causes no change to take place.
+After a
+.I substitute
+the current line is the last line substituted.
+.IP
+Lines may be split by substituting
+new-line characters into them.
+The newline in
+.I repl
+must be escaped by preceding it with a `\e'.
+Other metacharacters available in
+.I pat
+and
+.I repl
+are described below.
+.LC
+.B stop
+.ZP
+Suspends the editor, returning control to the top level shell.
+If
+.I autowrite
+is set and there are unsaved changes,
+a write is done first unless the form
+.B stop !
+is used.
+This commands is only available where supported by the teletype driver
+and operating system.
+.LC
+( \fB.\fR , \fB.\fR ) \fBsubstitute\fR \fIoptions\fR \fIcount\fR \fIflags\fR   abbr: \fBs\fR
+.ZP
+If
+.I pat
+and
+.I repl
+are omitted, then the last substitution is repeated.
+This is a synonym for the
+.B &
+command.
+.LC
+( \fB.\fR , \fB.\fR ) \fBt\fR \fIaddr\fR \fIflags\fR
+.ZP
+The
+.I t
+command is a synonym for 
+.I copy .
+.LC
+\fBta\fR \fItag\fR
+.ZP
+The focus of editing switches to the location of
+.I tag,
+switching to a different line in the current file where it is defined,
+or if necessary to another file.\(dd
+.FS
+\(dd If you have modified the current file before giving a
+.I tag
+command, you must write it out; giving another
+.I tag
+command, specifying no
+.I tag
+will reuse the previous tag.
+.FE
+.IP
+The tags file is normally created by a program such as
+.I ctags,
+and consists of a number of lines with three fields separated by blanks
+or tabs.  The first field gives the name of the tag,
+the second the name of the file where the tag resides, and the third
+gives an addressing form which can be used by the editor to find the tag;
+this field is usually a contextual scan using `/\fIpat\fR/' to be immune
+to minor changes in the file.  Such scans are always performed as if
+.I nomagic
+was set.
+.PP
+The tag names in the tags file must be sorted alphabetically.
+.LC
+\fBunabbreviate\fR \fIword\fP  abbr: \fBuna\fP
+.ZP
+Delete
+.I word
+from the list of abbreviations.
+.LC
+\fBundo\fR     abbr: \fBu\fR
+.ZP
+Reverses the changes made in the buffer by the last
+buffer editing command.
+Note that
+.I global
+commands are considered a single command for the purpose of 
+.I undo
+(as are
+.I open
+and
+.I visual.)
+Also, the commands
+.I write
+and
+.I edit
+which interact with the
+file system cannot be undone.
+.I Undo
+is its own inverse.
+.IP
+.I Undo
+always marks the previous value of the current line `\fB.\fR'
+as `\'\''.
+After an
+.I undo
+the current line is the first line restored
+or the line before the first line deleted if no lines were restored.
+For commands with more global effect
+such as
+.I global
+and
+.I visual
+the current line regains it's pre-command value after an
+.I undo.
+.LC
+\fBunmap\fR \fIlhs\fR
+.ZP
+The macro expansion associated by
+.I map
+for
+.I lhs
+is removed.
+.LC
+( 1 , $ ) \fBv\fR /\fIpat\fR\|/ \fIcmds\fR
+.ZP
+A synonym for the
+.I global
+command variant \fBg!\fR, running the specified \fIcmds\fR on each
+line which does not match \fIpat\fR.
+.LC
+\fBversion\fR  abbr: \fBve\fR
+.ZP
+Prints the current version number of the editor
+as well as the date the editor was last changed.
+.LC
+( \fB.\fR ) \fBvisual\fR \fItype\fR \fIcount\fR \fIflags\fR    abbr: \fBvi\fR
+.ZP
+Enters visual mode at the specified line.
+.I Type
+is optional and may be `\-' , `\(ua' or `\fB.\fR'
+as in the
+.I z
+command to specify the placement of the specified line on the screen.
+By default, if
+.I type
+is omitted, the specified line is placed as the first on the screen.
+A
+.I count
+specifies an initial window size; the default is the value of the option
+.I window.
+See the document
+.I "An Introduction to Display Editing with Vi"
+for more details.
+To exit this mode, type Q.
+.LC
+\fBvisual\fP file
+.br
+\fBvisual\fP +\fIn\fP file
+.ZP
+From visual mode,
+this command is the same as edit.
+.LC
+( 1 , $ ) \fBwrite\fR \fIfile\fR       abbr: \fBw\fR
+.ZP
+Writes changes made back to \fIfile\fR, printing the number of lines and
+characters written.
+Normally \fIfile\fR is omitted and the text goes back where it came from.
+If a \fIfile\fR is specified, then text will be written to that file.*
+.FS
+* The editor writes to a file only if it is
+the current file and is
+.I edited ,
+if the file does not exist,
+or if the file is actually a teletype,
+.I /dev/tty,
+.I /dev/null.
+Otherwise, you must give the variant form \fBw!\fR to force the write.
+.FE
+If the file does not exist it is created.
+The current file name is changed only if there is no current file
+name; the current line is never changed.
+.IP
+If an error occurs while writing the current and
+.I edited
+file, the editor
+considers that there has been ``No write since last change''
+even if the buffer had not previously been modified.
+.LC
+( 1 , $ ) \fBwrite>>\fR \fIfile\fR     abbr: \fBw>>\fR
+.ZP
+Writes the buffer contents at the end of
+an existing file.
+.IP
+.LC
+\fBw!\fR \fIname\fR
+.ZP
+Overrides the checking of the normal \fIwrite\fR command,
+and will write to any file which the system permits.
+.LC
+( 1 , $ ) \fBw\fR  \fB!\fR\fIcommand\fR
+.ZP
+Writes the specified lines into 
+.I command.
+Note the difference between \fBw!\fR which overrides checks and
+\fBw\ \ !\fR which writes to a command.
+.LC
+\fBwq\fR \fIname\fR
+.ZP
+Like a \fIwrite\fR and then a \fIquit\fR command.
+.LC
+\fBwq!\fR \fIname\fR
+.ZP
+The variant overrides checking on the sensibility of the
+.I write
+command, as \fBw!\fR does.
+.LC
+\fBxit\fP \fIname\fR
+.ZP
+If any changes have been made and not written, writes the buffer out.
+Then, in any case, quits.
+.LC
+( \fB.\fR , \fB.\fR )\|\fByank\fR \fIbuffer\fR \fIcount\fR     abbr: \fBya\fR
+.ZP
+Places the specified lines in the named
+.I buffer,
+for later retrieval via
+.I put.
+If no buffer name is specified, the lines go to a more volatile place;
+see the \fIput\fR command description.
+.LC
+( \fB.+1\fR ) \fBz\fR \fIcount\fR
+.ZP
+Print the next \fIcount\fR lines, default \fIwindow\fR.
+.LC
+( \fB.\fR ) \fBz\fR \fItype\fR \fIcount\fR
+.ZP
+Prints a window of text with the specified line at the top.
+If \fItype\fR is `\-' the line is placed at the bottom; a `\fB.\fR' causes
+the line to be placed in the center.*
+A count gives the number of lines to be displayed rather than
+double the number specified by the \fIscroll\fR option.
+On a \s-2CRT\s0 the screen is cleared before display begins unless a
+count which is less than the screen size is given.
+The current line is left at the last line printed.
+.FS
+* Forms `z=' and `z\(ua' also exist; `z=' places the current line in the
+center, surrounds it with lines of `\-' characters and leaves the current
+line at this line.  The form `z\(ua' prints the window before `z\-'
+would.  The characters `+', `\(ua' and `\-' may be repeated for cumulative
+effect.
+On some v2 editors, no
+.I type
+may be given.
+.FE
+.LC
+\fB!\fR \fIcommand\fR\fR
+.ZP
+The remainder of the line after the `!' character is sent to a shell
+to be executed.
+Within the text of
+.I command
+the characters 
+`%' and `#' are expanded as in filenames and the character
+`!' is replaced with the text of the previous command.
+Thus, in particular,
+`!!' repeats the last such shell escape.
+If any such expansion is performed, the expanded line will be echoed.
+The current line is unchanged by this command.
+.IP
+If there has been ``[No\ write]'' of the buffer contents since the last
+change to the editing buffer, then a diagnostic will be printed
+before the command is executed as a warning.
+A single `!' is printed when the command completes.
+.LC
+( \fIaddr\fR , \fIaddr\fR ) \fB!\fR \fIcommand\fR\fR
+.ZP
+Takes the specified address range and supplies it as
+standard input to
+.I command;
+the resulting output then replaces the input lines.
+.LC
+( $ ) \fB=\fR
+.ZP
+Prints the line number of the
+addressed line.
+The current line is unchanged.
+.KS
+.LC
+( \fB.\fR , \fB.\fR ) \fB>\fR \fIcount\fR \fIflags\fR
+.br
+( \fB.\fR , \fB.\fR ) \fB<\fR \fIcount\fR \fIflags\fR
+.IP
+Perform intelligent shifting on the specified lines;
+\fB<\fR shifts left and \fB>\fR shift right.
+The quantity of shift is determined by the
+.I shiftwidth
+option and the repetition of the specification character.
+Only white space (blanks and tabs) is shifted;
+no non-white characters are discarded in a left-shift.
+The current line becomes the last line which changed due to the
+shifting.
+.KE
+.LC
+\fB^D\fR
+.ZP
+An end-of-file from a terminal input scrolls through the file.
+The
+.I scroll
+option specifies the size of the scroll, normally a half screen of text.
+.LC
+( \fB.\fR+1 , \fB.\fR+1 )
+.br
+( \fB.\fR+1 , \fB.\fR+1 ) |
+.ZP
+An address alone causes the addressed lines to be printed.
+A blank line prints the next line in the file.
+.LC
+( \fB.\fR , \fB.\fR ) \fB&\fR \fIoptions\fR \fIcount\fR \fIflags\fR
+.ZP
+Repeats the previous
+.I substitute
+command.
+.LC
+( \fB.\fR , \fB.\fR ) \fB\s+2~\s0\fR \fIoptions\fR \fIcount\fR \fIflags\fR
+.ZP
+Replaces the previous regular expression with the previous
+replacement pattern from a substitution.
+.NH 1
+Regular expressions and substitute replacement patterns
+.NH 2
+Regular expressions
+.PP
+A regular expression specifies a set of strings of characters.
+A member of this set of strings is said to be
+.I matched
+by the regular expression.
+.I Ex
+remembers two previous regular expressions:
+the previous regular expression used in a
+.I substitute
+command
+and the previous regular expression used elsewhere
+(referred to as the previous \fIscanning\fR regular expression.)
+The previous regular expression
+can always be referred to by a null \fIre\fR, e.g. `//' or `??'.
+.NH 2
+Magic and nomagic
+.PP
+The regular expressions allowed by
+.I ex 
+are constructed in one of two ways depending on the setting of
+the
+.I magic
+option.
+The
+.I ex
+and
+.I vi
+default setting of
+.I magic
+gives quick access to a powerful set of regular expression
+metacharacters.
+The disadvantage of
+.I magic
+is that the user must remember that these metacharacters are
+.I magic
+and precede them with the character `\e'
+to use them as ``ordinary'' characters.
+With
+.I nomagic,
+the default for
+.I edit,
+regular expressions are much simpler,
+there being only two metacharacters.
+The power of the other metacharacters is still available by preceding
+the (now) ordinary character with a `\e'.
+Note that `\e' is thus always a metacharacter.
+.PP
+The remainder of the discussion of regular expressions assumes
+that
+that the setting of this option is
+.I magic.\(dg
+.FS
+\(dg To discern what is true with
+.I nomagic
+it suffices to remember that the only
+special characters in this case will be `\(ua' at the beginning
+of a regular expression,
+`$' at the end of a regular expression,
+and `\e'.
+With
+.I nomagic
+the characters `\s+2~\s0' and `&' also lose their special meanings
+related to the replacement pattern of a substitute.
+.FE
+.NH 2
+Basic regular expression summary
+.PP
+The following basic constructs are used to construct
+.I magic
+mode regular expressions.
+.IP \fIchar\fR 15
+An ordinary character matches itself.
+The characters `\(ua' at the beginning of a line,
+`$' at the end of line,
+`*' as any character other than the first,
+`.', `\e', `[', and `\s+2~\s0' are not ordinary characters and
+must be escaped (preceded) by `\e' to be treated as such.
+.IP \fB\(ua\fR
+At the beginning of a pattern
+forces the match to succeed only at the beginning of a line.
+.IP \fB$\fR
+At the end of a regular expression forces the match to
+succeed only at the end of the line.
+.IP \&\fB.\fR
+Matches any single character except
+the new-line character.
+.IP \fB\e<\fR
+Forces the match
+to occur only at the beginning of a ``variable'' or ``word'';
+that is, either at the beginning of a line, or just before
+a letter, digit, or underline and after a character not one of
+these.
+.IP \fB\e>\fR
+Similar to `\e<', but matching the end of a ``variable''
+or ``word'', i.e. either the end of the line or before character
+which is neither a letter, nor a digit, nor the underline character.
+.IP \fB[\fIstring\fR]\fR
+Matches any (single) character in the class defined by
+.I string.
+Most characters in
+.I string
+define themselves.
+A pair of characters separated by `\-' in
+.I string
+defines the set of characters collating between the specified lower and upper
+bounds, thus `[a\-z]' as a regular expression matches
+any (single) lower-case letter.
+If the first character of
+.I string
+is an `\(ua' then the construct
+matches those characters which it otherwise would not;
+thus `[\(uaa\-z]' matches anything but a lower-case letter (and of course a
+newline).
+To place any of the characters
+`\(ua', `[', or `\-' in
+.I string
+you must escape them with a preceding `\e'.
+.NH 2
+Combining regular expression primitives
+.PP
+The concatenation of two regular expressions matches the leftmost and
+then longest string
+which can be divided with the first piece matching the first regular
+expression and the second piece matching the second.
+Any of the (single character matching) regular expressions mentioned
+above may be followed by the character `*' to form a regular expression
+which matches any number of adjacent occurrences (including 0) of characters
+matched by the regular expression it follows.
+.PP
+The character `\s+2~\s0' may be used in a regular expression,
+and matches the text which defined the replacement part
+of the last
+.I substitute
+command.
+A regular expression may be enclosed between the sequences
+`\e(' and `\e)' with side effects in the
+.I substitute
+replacement patterns.
+.NH 2
+Substitute replacement patterns
+.PP
+The basic metacharacters for the replacement pattern are
+`&' and `~'; these are
+given as `\e&' and `\e~' when
+.I nomagic
+is set.
+Each instance of `&' is replaced by the characters
+which the regular expression matched.
+The metacharacter `~' stands, in the replacement pattern,
+for the defining text of the previous replacement pattern.
+.PP
+Other metasequences possible in the replacement pattern
+are always introduced by the escaping character `\e'.
+The sequence `\e\fIn\fR' is replaced by the text matched
+by the \fIn\fR-th regular subexpression enclosed between
+`\e(' and `\e)'.\(dg
+.FS
+\(dg When nested, parenthesized subexpressions are present,
+\fIn\fR is determined by counting occurrences of `\e(' starting from the left.
+.FE
+The sequences `\eu' and `\el' cause the immediately following character in
+the replacement to be converted to upper- or lower-case respectively
+if this character is a letter.
+The sequences `\eU' and `\eL' turn such conversion on, either until
+`\eE' or `\ee' is encountered, or until the end of the replacement pattern.
+.de LC
+.br
+.sp .1i
+.ne 4
+.LP
+.ta 3i
+..
+.NH 1
+Option descriptions
+.PP
+.LC
+\fBautoindent\fR, \fBai\fR     default: noai
+.ZP
+Can be used to ease the preparation of structured program text.
+At the beginning of each
+.I append ,
+.I change
+or
+.I insert
+command
+or when a new line is
+.I opened
+or created by an
+.I append ,
+.I change ,
+.I insert ,
+or
+.I substitute
+operation within
+.I open
+or
+.I visual
+mode,
+.I ex
+looks at the line being appended after,
+the first line changed
+or the line inserted before and calculates the amount of white space
+at the start of the line.
+It then aligns the cursor at the level of indentation so determined.
+.IP
+If the user then types lines of text in,
+they will continue to be justified at the displayed indenting level.
+If more white space is typed at the beginning of a line,
+the following line will start aligned with the first non-white character
+of the previous line.
+To back the cursor up to the preceding tab stop one can hit
+\fB^D\fR.
+The tab stops going backwards are defined at multiples of the
+.I shiftwidth
+option.
+You
+.I cannot
+backspace over the indent,
+except by sending an end-of-file with a \fB^D\fR.
+.IP
+Specially processed in this mode is a line with no characters added
+to it, which turns into a completely blank line (the white
+space provided for the
+.I autoindent
+is discarded.)
+Also specially processed in this mode are lines beginning with
+an `\(ua' and immediately followed by a \fB^D\fR.
+This causes the input to be repositioned at the beginning of the line,
+but retaining the previous indent for the next line.
+Similarly, a `0' followed by a \fB^D\fR
+repositions at the beginning but without
+retaining the previous indent.
+.IP
+.I Autoindent
+doesn't happen in
+.I global
+commands or when the input is not a terminal.
+.LC
+\fBautoprint\fR, \fBap\fR      default: ap
+.ZP
+Causes the current line to be printed after each
+.I delete ,
+.I copy ,
+.I join ,
+.I move ,
+.I substitute ,
+.I t ,
+.I undo
+or
+shift command.
+This has the same effect as supplying a trailing `p'
+to each such command.
+.I Autoprint
+is suppressed in globals,
+and only applies to the last of many commands on a line.
+.LC
+\fBautowrite\fR, \fBaw\fR      default: noaw
+.ZP
+Causes the contents of the buffer to be written to the current file
+if you have modified it and give a
+.I next,
+.I rewind,
+.I stop,
+.I tag,
+or
+.I !
+command, or a \fB^\(ua\fR (switch files) or \fB^]\fR (tag goto) command
+in
+.I visual.
+Note, that the
+.I edit
+and
+.I ex
+commands do
+.B not
+autowrite.
+In each case, there is an equivalent way of switching when autowrite
+is set to avoid the
+.I autowrite
+(\fIedit\fR
+for
+.I next ,
+.I rewind!
+for .I rewind ,
+.I stop!
+for
+.I stop ,
+.I tag!
+for
+.I tag ,
+.I shell
+for
+.I ! ,
+and
+\fB:e\ #\fR and a \fB:ta!\fR command from within
+.I visual).
+.LC
+\fBbeautify\fR, \fBbf\fR       default: nobeautify
+.ZP
+Causes all control characters except tab, newline and form-feed
+to be discarded from the input.
+A complaint is registered the first time a
+backspace character is discarded.
+.I Beautify
+does not apply to command input.
+.LC
+\fBdirectory\fR, \fBdir\fR     default: dir=/tmp
+.ZP
+Specifies the directory in which
+.I ex
+places its buffer file.
+If this directory in not
+writable, then the editor will exit abruptly when it fails to be
+able to create its buffer there.
+.LC
+\fBedcompatible\fR     default: noedcompatible
+.ZP
+Causes the presence of absence of
+.B g
+and
+.B c
+suffixes on substitute commands to be remembered, and to be toggled
+by repeating the suffices.  The suffix
+.B r
+makes the substitution be as in the
+.I ~
+command, instead of like
+.I &.
+.LC
+\fBerrorbells\fR, \fBeb\fR     default: noeb
+.ZP
+Error messages are preceded by a bell.*
+.FS
+* Bell ringing in
+.I open
+and
+.I visual
+on errors is not suppressed by setting
+.I noeb.
+.FE
+If possible the editor always places the error message in a standout mode of the
+terminal (such as inverse video) instead of ringing the bell.
+.LC
+\fBhardtabs\fR, \fBht\fR       default: ht=8
+.ZP
+Gives the boundaries on which terminal hardware tabs are set (or
+on which the system expands tabs).
+.LC
+\fBignorecase\fR, \fBic\fR     default: noic
+.ZP
+All upper case characters in the text are mapped to lower case in regular
+expression matching.
+In addition, all upper case characters in regular expressions are mapped
+to lower case except in character class specifications.
+.LC
+\fBlisp\fR     default: nolisp
+.ZP
+\fIAutoindent\fR indents appropriately for
+.I lisp
+code, and the \fB( ) { } [[\fR and \fB]]\fR commands in
+.I open
+and
+.I visual
+are modified to have meaning for \fIlisp\fR.
+.LC
+\fBlist\fR     default: nolist
+.ZP
+All printed lines will be displayed (more) unambiguously,
+showing tabs and end-of-lines as in the
+.I list
+command.
+.LC
+\fBmagic\fR    default: magic for \fIex\fR and \fIvi\fR\(dg
+.FS
+\(dg \fINomagic\fR for \fIedit\fR.
+.FE
+.ZP
+If
+.I nomagic
+is set, the number of regular expression metacharacters is greatly reduced,
+with only `\(ua' and `$' having special effects.
+In addition the metacharacters
+`~'
+and
+`&'
+of the replacement pattern are treated as normal characters.
+All the normal metacharacters may be made
+.I magic
+when
+.I nomagic
+is set by preceding them with a `\e'.
+.LC
+\fBmesg\fR     default: mesg
+.ZP
+Causes write permission to be turned off to the terminal
+while you are in visual mode, if
+.I nomesg
+is set.
+.LC
+\fBmodeline\fR default: nomodeline
+.ZP
+If
+.I modeline
+is set, then the first 5 lines and the last five lines of the file
+will be checked for ex command lines and the comands issued.
+To be recognized as a command line, the line must have the string
+.B ex:
+or
+.B vi:
+preceeded by a tab or a space.  This string may be anywhere in the
+line and anything after the 
+.I :
+is interpeted as editor commands.  This option defaults to off because
+of unexpected behavior when editting files such as
+.I /etc/passwd.
+.LC
+\fBnumber, nu\fR       default: nonumber
+.ZP
+Causes all output lines to be printed with their
+line numbers.
+In addition each input line will be prompted for by supplying the line number
+it will have.
+.LC
+\fBopen\fR     default: open
+.ZP
+If \fInoopen\fR, the commands
+.I open
+and
+.I visual
+are not permitted.
+This is set for
+.I edit
+to prevent confusion resulting from accidental entry to 
+open or visual mode.
+.LC
+\fBoptimize, opt\fR    default: optimize
+.ZP
+Throughput of text is expedited by setting the terminal
+to not do automatic carriage returns
+when printing more than one (logical) line of output,
+greatly speeding output on terminals without addressable
+cursors when text with leading white space is printed.
+.LC
+\fBparagraphs,\ para\fR        default: para=IPLPPPQPP\0LIbp
+.ZP
+Specifies the paragraphs for the \fB{\fR and \fB}\fR operations in
+.I open
+and 
+.I visual.
+The pairs of characters in the option's value are the names
+of the macros which start paragraphs.
+.LC
+\fBprompt\fR   default: prompt
+.ZP
+Command mode input is prompted for with a `:'.
+.LC
+\fBredraw\fR   default: noredraw
+.ZP
+The editor simulates (using great amounts of output), an intelligent
+terminal on a dumb terminal (e.g. during insertions in
+.I visual
+the characters to the right of the cursor position are refreshed
+as each input character is typed.)
+Useful only at very high speed.
+.LC
+\fBremap\fP    default: remap
+.ZP
+If on, macros are repeatedly tried until they are unchanged.
+For example, if
+.B o
+is mapped to
+.B O ,
+and
+.B O
+is mapped to
+.B I ,
+then if
+.I remap
+is set,
+.B o
+will map to
+.B I ,
+but if
+.I noremap
+is set, it will map to
+.B O .
+.LC
+\fBreport\fR   default: report=5\(dg
+.FS
+\(dg 2 for \fIedit\fR.
+.FE
+.ZP
+Specifies a threshold for feedback from commands.
+Any command which modifies more than the specified number of lines
+will provide feedback as to the scope of its changes.
+For commands such as
+.I global ,
+.I open ,
+.I undo ,
+and
+.I visual
+which have potentially more far reaching scope,
+the net change in the number of lines in the buffer is
+presented at the end of the command, subject to this same threshold.
+Thus notification is suppressed during a
+.I global
+command on the individual commands performed.
+.LC
+\fBscroll\fR   default: scroll=\(12 window
+.ZP
+Determines the number of logical lines scrolled when an end-of-file
+is received from a terminal input in command mode,
+and the number of lines printed by a command mode
+.I z
+command (double the value of
+.I scroll ).
+.LC
+\fBsections\fR default: sections=SHNHH\0HU
+.ZP
+Specifies the section macros for the \fB[[\fR and \fB]]\fR operations
+in
+.I open
+and
+.I visual.
+The pairs of characters in the options's value are the names
+of the macros which start paragraphs.
+.LC
+\fBshell\fR, \fBsh\fR  default: sh=/bin/sh
+.ZP
+Gives the path name of the shell forked for 
+the shell escape command `!', and by the
+.I shell
+command.
+The default is taken from SHELL in the environment, if present.
+.LC
+\fBshiftwidth\fR, \fBsw\fR     default: sw=8
+.ZP
+Gives the width a software tab stop,
+used in reverse tabbing with \fB^D\fR when using
+.I autoindent
+to append text,
+and by the shift commands.
+.LC
+\fBshowmatch, sm\fR    default: nosm
+.ZP
+In
+.I open
+and
+.I visual
+mode, when a \fB)\fR or \fB}\fR is typed, move the cursor to the matching
+\fB(\fR or \fB{\fR for one second if this matching character is on the
+screen.  Extremely useful with
+.I lisp.
+.LC
+\fBslowopen, slow\fR   terminal dependent
+.ZP
+Affects the display algorithm used in
+.I visual
+mode, holding off display updating during input of new text to improve
+throughput when the terminal in use is both slow and unintelligent.
+See
+.I "An Introduction to Display Editing with Vi"
+for more details.
+.LC
+\fBtabstop,\ ts\fR     default: ts=8
+.ZP
+The editor expands tabs in the input file to be on
+.I tabstop
+boundaries for the purposes of display.
+.LC
+\fBtaglength,\ tl\fR   default: tl=0
+.ZP
+Tags are not significant beyond this many characters.
+A value of zero (the default) means that all characters are significant.
+.LC
+\fBtags\fR     default: tags=tags /usr/lib/tags
+.ZP
+A path of files to be used as tag files for the
+.I tag
+command.
+A requested tag is searched for in the specified files, sequentially.
+By default, files called
+.B tags
+are searched for in the current directory and in /usr/lib
+(a master file for the entire system).
+.LC
+\fBterm\fR     from environment TERM
+.ZP
+The terminal type of the output device.
+.LC
+\fBterse\fR    default: noterse
+.ZP
+Shorter error diagnostics are produced for the experienced user.
+.LC
+\fBwarn\fR     default: warn
+.ZP
+Warn if there has been `[No write since last change]' before a `!'
+command escape.
+.LC
+\fBwindow\fR   default: window=speed dependent
+.ZP
+The number of lines in a text window in the
+.I visual
+command.
+The default is 8 at slow speeds (600 baud or less),
+16 at medium speed (1200 baud),
+and the full screen (minus one line) at higher speeds.
+.LC
+\fBw300,\ w1200\, w9600\fR
+.ZP
+These are not true options but set
+.B window
+only if the speed is slow (300), medium (1200), or high (9600),
+respectively.
+They are suitable for an EXINIT
+and make it easy to change the 8/16/full screen rule.
+.LC
+\fBwrapscan\fR, \fBws\fR       default: ws
+.ZP
+Searches using the regular expressions in addressing
+will wrap around past the end of the file.
+.LC
+\fBwrapmargin\fR, \fBwm\fR     default: wm=0
+.ZP
+Defines a margin for automatic wrapover of text during input in
+.I open
+and
+.I visual
+modes.  See
+.I "An Introduction to Text Editing with Vi"
+for details.
+.LC
+\fBwriteany\fR, \fBwa\fR       default: nowa
+.IP
+Inhibit the checks normally made before
+.I write
+commands, allowing a write to any file which the system protection
+mechanism will allow.
+.NH 1
+Acknowledgements
+.PP
+Chuck Haley contributed greatly to the early development of
+.I ex.
+Bruce Englar encouraged the redesign which led to
+.I ex
+version 1.
+Bill Joy wrote versions 1 and 2.0 through 2.7,
+and created the framework that users see in the present editor.
+Mark Horton added macros and other features and made the
+editor work on a large number of terminals and Unix systems.
diff --git a/dist/nvi/docs/exref/ex.summary b/dist/nvi/docs/exref/ex.summary
new file mode 100644 (file)
index 0000000..1f3d4b9
--- /dev/null
@@ -0,0 +1,704 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: ex.summary,v 8.3 1996/08/18 11:36:16 bostic Exp (Berkeley) Date: 1996/08/18 11:36:16
+.\"
+.ds p \v'-0.2'.\v'+0.2'
+.ds U \s-2UNIX\s+2
+.ds c \v'-0.2':\v'+0.2'
+.nr LL 6.5i
+.lt 6.5i
+.ll 6.5i
+.ds CH
+.ds LF Computing Services, U.C. Berkeley
+.ds RF April 3, 1979
+.de SP
+.sp 1v
+..
+.nr PI 3n
+.nr PD 0
+.ND
+.ps 12
+.ft B
+.ce 1
+Ex/Edit Command Summary (Version 2.0)
+.sp 1
+.ft R
+.nr VS 11
+.nr PS 9
+.2C
+.PP
+.I Ex
+and
+.I edit
+are text editors, used for creating
+and modifying files of text on the \*U
+computer system.
+.I Edit
+is a variant of
+.I ex
+with features designed to
+make it less complicated
+to learn and use.
+In terms of command syntax and effect
+the editors are essentially identical,
+and this command summary applies to both.
+.PP
+The summary is meant as a quick reference
+for users already acquainted
+with
+.I edit
+or \fIex\fP.
+Fuller explanations of the editors are available
+in the documents
+.I
+Edit: A Tutorial
+.R
+(a self-teaching introduction) and the
+.I
+Ex Reference Manual
+.R
+(the comprehensive reference source for
+both \fIedit\fP and \fIex\fP).
+Both of these writeups are available in the
+Computing Services Library.
+.PP
+In the examples included with the
+summary, commands and text entered by
+the user are printed in \fBboldface\fR to
+distinguish them from responses printed
+by the computer.
+.sp 0.45v
+.LP
+.B
+The Editor Buffer
+.PP
+In order to perform its tasks
+the editor sets aside a temporary
+work space,
+called a \fIbuffer\fR,
+separate from the user's permanent
+file.
+Before starting to work on an existing
+file the editor makes a copy of it in the
+buffer, leaving the original untouched.
+All editing changes are made to the
+buffer copy, which must then
+be written back to the permanent
+file in order to update the
+old version.
+The buffer disappears
+at the end of the editing session.
+.sp 0.45v
+.LP
+.B
+Editing: Command and Text Input Modes
+.PP
+.R
+During an editing session there are
+two usual modes of operation:
+\fIcommand\fP mode and \fItext input\fP
+mode.
+(This disregards, for the moment,
+.I open
+and
+.I visual
+modes, discussed below.)
+In command mode, the editor issues a
+colon prompt (:)
+to show that it is ready to
+accept and execute a command.
+In text input mode, on the other hand, there is
+no prompt and the editor merely accepts text to
+be added to the buffer.
+Text input mode is initiated by the commands
+\fIappend\fP, \fIinsert\fP, and \fIchange\fP,
+and is terminated by typing a period as the
+first and only character on a line.
+.sp 0.45v
+.LP
+.B
+Line Numbers and Command Syntax
+.PP
+.R
+The editor keeps track of lines of text
+in the buffer by numbering them consecutively
+starting with 1 and renumbering
+as lines are added or deleted.
+At any given time the editor is positioned
+at one of these lines; this position is
+called the \fIcurrent line\fP.
+Generally, commands that change the
+contents of the buffer print the
+new current line at the end of their
+execution.
+.PP
+Most commands can be preceded by one or two
+line-number addresses which indicate the lines
+to be affected.
+If one number is given the command operates on
+that line only; if two, on an inclusive range
+of lines.
+Commands that can take line-number prefixes also
+assume default prefixes if none are given.
+The default assumed by each command is designed
+to make it convenient to use in many instances
+without any line-number prefix.
+For the most part, a command used without a
+prefix operates on the current line,
+though exceptions to this rule should be noted.
+The \fIprint\fP command
+by itself, for instance, causes
+one line, the current line, to be
+printed at the terminal.
+.PP
+The summary shows the number of line addresses
+that can be
+prefixed to each command as well as
+the defaults assumed if they are omitted.
+For example,
+.I (.,.)
+means that up to 2 line-numbers may be given,
+and that if none is given the
+command operates on the current line.
+(In the address prefix notation, ``.'' stands
+for the current line and ``$'' stands for
+the last line of the buffer.)
+If no such notation appears, no
+line-number prefix may be used.
+.PP
+Some commands take trailing
+information;
+only
+the more important instances of this
+are mentioned in the summary.
+.sp 0.25v
+.LP
+.B
+Open and Visual Modes
+.PP
+.R
+Besides command and text input modes,
+.I ex
+and
+.I edit
+provide on some CRT terminals other modes of editing,
+.I open
+and
+.I visual .
+In these modes the cursor can
+be moved to individual words
+or characters in a line.
+The commands then given are very different
+from the standard editor commands; most do not appear on the screen when
+typed.
+.I
+An Introduction to Display Editing with Vi
+.R
+provides a full discussion.
+.sp 0.25v
+.LP
+.B
+Special Characters
+.PP
+.R
+.fi
+Some characters take on special meanings
+when used in context searches
+and in patterns given to the \fIsubstitute\fP command.
+For \fIedit\fR, these are ``^'' and ``$'',
+meaning the beginning and end of a line,
+respectively.
+.I Ex
+has the following additional special characters:
+.B
+.ce 1
+\&.     &     *     [     ]     ~
+.R
+To use one of the special characters as its
+simple graphic representation
+rather than with its special meaning,
+precede it by a backslash (\\).
+The backslash always has a special meaning.
+.1C
+.TS
+cp10 cp10 cp10 cp10
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+Name   Abbr    Description     Examples
+.sp 1.75
+(.)\fBappend   a       T{
+Begins text input mode,
+adding lines to the buffer after
+the line specified. Appending continues
+until ``.'' is typed alone at the
+beginning of a new line, followed by
+a carriage return. \fI0a\fR places
+lines at the beginning of the buffer.
+T}     T{
+.nf
+\fR:\fBa
+Three lines of text
+are added to the buffer
+after the current line.
+\*p
+.R
+\*c
+.fi
+T}
+.SP
+\fR(.,.)\fBchange      c       T{
+Deletes indicated line(s) and
+initiates text input mode to
+replace them with new text which follows.
+New text is terminated the same way
+as with \fIappend\fR.
+T}     T{
+.nf
+:\fB5,6c
+Lines 5 and 6 are
+deleted and replaced by
+these three lines.
+\*p
+.R
+\*c
+.fi
+T}
+.SP
+\fR(.,.)\fBcopy \fIaddr        co      T{
+Places a copy of the specified lines
+after the line indicated by \fIaddr\fR.
+The example places a copy of lines 8 through
+12, inclusive, after line 25.
+T}     T{
+.nf
+\fR:\fB8,12co 25
+\fRLast line copied is printed
+\fR\*c
+.fi
+T}
+.SP
+\fR(.,.)\fBdelete      d       T{
+Removes lines from the buffer
+and prints the current line after the deletion.
+T}     T{
+.nf
+\fR:\fB13,15d
+\fRNew current line is printed
+\*c
+.fi
+T}
+.TE
+.sp 0.5v
+.TS
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+T{
+\fBedit \fIfile\fP
+.br
+\fBedit! \fIfile\fP
+T}     T{
+e
+.br
+e!
+T}     T{
+.fi
+\fRClears the editor buffer and then
+copies into it the named \fIfile\fR,
+which becomes the current file.
+This is a way of shifting to a different
+file
+without leaving the editor.
+The editor issues a warning
+message if this command is used before
+saving changes
+made to the file already in the buffer;
+using the form \fBe!\fR overrides this protective mechanism.
+T}     T{
+.nf
+\fR:\fBe ch10\fR
+No write since last change
+:\fBe! ch10\fR
+"ch10" 3 lines, 62 characters
+\*c
+.fi
+T}
+.SP
+\fBfile \fIname\fR     f       T{
+\fRIf followed by a \fIname\fR, renames
+the current file to \fIname\fR.
+If used without \fIname\fR, prints
+the name of the current file.
+T}     T{
+.nf
+\fR:\fBf ch9
+\fR"ch9" [Modified] 3 lines ...
+:\fBf
+\fR"ch9" [Modified] 3 lines ...
+\*c
+.fi
+T}
+.SP
+(1,$)\fBglobal g       \fBglobal/\fIpattern\fB/\fIcommands     T{
+.nf
+:\fBg/nonsense/d
+\fR\*c
+.fi
+T}
+\fR(1,$)\fBglobal!     g!\fR or \fBv   T{
+Searches the entire buffer (unless a smaller
+range is specified by line-number prefixes) and
+executes \fIcommands\fR on every line with
+an expression matching \fIpattern\fR.
+The second form, abbreviated
+either \fBg!\fR or \fBv\fR,
+executes \fIcommands\fR on lines that \fIdo
+not\fR contain the expression \fIpattern\fR.
+T}     \^
+.SP
+\fR(.)\fBinsert        i       T{
+Inserts new lines of text immediately before the specified line.
+Differs from
+.I append
+only in that text is placed before, rather than after, the indicated line.
+In other words, \fB1i\fR has the same effect as \fB0a\fR.
+T}     T{
+.nf
+:\fB1i
+These lines of text will
+be added prior to line 1.
+\&.
+\fR:
+.fi
+T}
+.SP
+\fR(.,.+1)\fBjoin      j       T{
+Join lines together, adjusting white space (spaces
+and tabs) as necessary.
+T}     T{
+.nf
+:\fB2,5j\fR
+Resulting line is printed
+:
+.fi
+T}
+.TE
+.bp
+.TS
+cp10 cp10 cp10 cp10
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+Name   Abbr    Description     Examples
+.sp 1.75
+\fR(.,.)\fBlist        l       T{
+\fRPrints lines in a more
+unambiguous way than the \fIprint\fR
+command does. The end of a line,
+for example, is marked with a ``$'',
+and tabs printed as ``^I''.
+T}     T{
+.nf
+:\fB9l
+\fRThis is line 9$
+\*c
+.fi
+T}
+.TE
+.sp 0.5v
+.TS
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+\fR(.,.)\fBmove \fIaddr\fB     m       T{
+\fRMoves the specified lines
+to a position after the line
+indicated by \fIaddr\fR.
+T}     T{
+.nf
+\fR:\fB12,15m 25\fR
+New current line is printed
+\*c
+.fi
+T}
+.SP
+\fR(.,.)\fBnumber      nu      T{
+Prints each line preceded
+by its buffer line number.
+T}     T{
+.nf
+\fR:\fBnu
+\0\0\fR10\0 This is line 10
+\*c
+.fi
+T}
+.SP
+\fR(.)\fBopen  o       T{
+Too involved to discuss here,
+but if you enter open mode
+accidentally, press
+the \s-2ESC\s0 key followed by
+\fBq\fR to
+get back into normal editor
+command mode.
+\fIEdit\fP is designed to
+prevent accidental use of
+the open command.
+T}     
+.SP
+\fBpreserve    pre     T{
+Saves a copy of the current buffer contents as though the system had
+just crashed.  This is for use in an emergency when a
+.I write
+command has failed and you don't know how else to save your work.\(dg
+T}     T{
+.nf
+:\fBpreserve\fR
+File preserved.
+:
+.fi
+T}
+.SP
+\fR(.,.)\fBprint       p       Prints the text of line(s).     T{
+.nf
+:\fB+2,+3p\fR
+The second and third lines
+after the current line
+:
+.fi
+T}
+.TE
+.FS
+.ll 6.5i
+\(dg You should seek assistance from a system administrator as soon as
+possible after saving a file with the
+.I preserve
+command, because the preserved copy of the file is saved in a
+directory used to store temporary files, and thus, the preserved
+copy may only be available for a short period of time.
+.FE
+.SP
+.nf
+.TS
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+T{
+.nf
+\fBquit
+quit!
+.fi
+T}     T{
+.nf
+q
+q!
+T}     T{
+.fi
+\fREnds the editing session.
+You will receive a
+warning if you have changed the buffer
+since last writing its contents
+to the file. In this event you
+must either type \fBw\fR to write,
+or type \fBq!\fR to exit from
+the editor without saving your changes.
+T}     T{
+.nf
+\fR:\fBq
+\fRNo write since last change
+:\fBq!
+\fR%
+.fi
+T}
+.SP
+\fR(.)\fBread \fIfile\fP       r       T{
+.fi
+\fRPlaces a copy of \fIfile\fR in the
+buffer after the specified line.
+Address 0 is permissible and causes
+the copy of \fIfile\fR to be placed
+at the beginning of the buffer.
+The \fIread\fP command does not
+erase any text already in the buffer.
+If no line number is specified,
+\fIfile\fR is placed after the
+current line.
+T}     T{
+.nf
+\fR:\fB0r newfile
+\fR"newfile" 5 lines, 86 characters
+\*c
+.fi
+T}
+.SP
+\fBrecover \fIfile\fP  rec     T{
+.fi
+Retrieves a copy of the editor buffer
+after a system crash, editor crash,
+phone line disconnection, or
+\fIpreserve\fR command.
+T}
+.SP
+\fR(.,.)\fBsubstitute  s       T{
+.nf
+\fBsubstitute/\fIpattern\fB/\fIreplacement\fB/
+substitute/\fIpattern\fB/\fIreplacement\fB/gc
+.fi
+\fRReplaces the first occurrence of \fIpattern\fR
+on a line
+with \fIreplacement\fP.
+Including a \fBg\fR after the command
+changes all occurrences of \fIpattern\fP
+on the line.
+The \fBc\fR option allows the user to
+confirm each substitution before it is
+made; see the manual for details.
+T}     T{
+.nf
+:\fB3p
+\fRLine 3 contains a misstake
+:\fBs/misstake/mistake/
+\fRLine 3 contains a mistake
+\*c
+.fi
+T}
+.TE
+.bp
+.TS
+cp10 cp10 cp10 cp10
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+Name   Abbr    Description     Examples
+.sp 1.75
+\fBundo        u       T{
+.fi
+\fRReverses the changes made in
+the buffer by the last buffer-editing
+command.
+Note that this example contains
+a notification about the number of
+lines affected.
+T}     T{
+.nf
+\fR:\fB1,15d
+\fR15 lines deleted
+new line number 1 is printed
+:\fBu
+\fR15 more lines in file ...
+old line number 1 is printed
+\*c
+.fi
+T}
+.SP
+\fR(1,$)\fBwrite \fIfile\fR    w       T{
+.fi
+\fRCopies data from the buffer onto
+a permanent file. If no \fIfile\fR
+is named, the current filename
+is used.
+The file is automatically created
+if it does not yet exist.
+A response containing the number of
+lines and characters in the file
+indicates that the write
+has been completed successfully.
+The editor's built-in protections
+against overwriting existing files
+will in some circumstances
+inhibit a write.
+The form \fBw!\fR forces the
+write, confirming that
+an existing file is to be overwritten.
+T}     T{
+.nf
+\fR:\fBw
+\fR"file7" 64 lines, 1122 characters
+:\fBw file8
+\fR"file8" File exists ...
+:\fBw! file8
+\fR"file8" 64 lines, 1122 characters
+\*c
+.fi
+T}
+\fR(1,$)\fBwrite! \fIfile\fP   w!      \^      \^
+.TE
+.sp 0.5v
+.TS
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+\fR(.)\fBz \fIcount\fP z       T{
+.fi
+\fRPrints a screen full of text starting
+with the line indicated;
+or, if \fIcount\fR is specified,
+prints that number of lines.
+Variants of the \fIz\fR command
+are described in the manual.
+T}     
+.SP
+\fB!\fIcommand         T{
+.fi
+Executes the remainder of the line
+after \fB!\fR as a \*U command.
+The buffer is unchanged by this, and
+control is returned to the editor when
+the execution of \fIcommand\fR is complete.
+T}     T{
+.nf
+\fR:\fB!date
+\fRFri Jun 9 12:15:11 PDT 1978
+!
+\*c
+.fi
+T}
+.SP
+\fRcontrol-d           T{
+.fi
+Prints the next \fIscroll\fR of text,
+normally half of a screen. See the
+manual for details of the \fIscroll\fR
+option.
+T}
+.SP
+\fR(.+1)<cr>           T{
+.fi
+An address alone followed by a carriage
+return causes the line to be printed.
+A carriage return by itself prints the
+line following the current line.
+T}     T{
+.nf
+:\fR<cr>
+the line after the current line
+\*c
+.fi
+T}
+.TE
+.sp 0.5v
+.TS
+ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
+\fB/\fIpattern\fB/             T{
+.fi
+\fRSearches for the next line in which
+\fIpattern\fR occurs and prints it.
+T}     T{
+.nf
+\fR:\fB/This pattern/
+\fRThis pattern next occurs here.
+\*c
+.fi
+T}
+.SP
+\fB//          T{
+Repeats the most recent search.
+T}     T{
+.nf
+\fR:\fB//
+\fRThis pattern also occurs here.
+\*c
+.fi
+T}
+.SP
+\fB?\fIpattern\fB?             T{
+Searches in the reverse direction
+for \fIpattern\fP.
+T}     
+.SP
+\fB??          T{
+Repeats the most recent search,
+moving in the reverse direction
+through the buffer.
+T}
+.TE
diff --git a/dist/nvi/docs/vi.man/Makefile b/dist/nvi/docs/vi.man/Makefile
new file mode 100644 (file)
index 0000000..de4914e
--- /dev/null
@@ -0,0 +1,23 @@
+# Id: Makefile,v 8.9 2001/01/28 15:50:07 skimo Exp (Berkeley) Date: 2001/01/28 15:50:07
+
+ROFF=  groff
+
+all: vi.0 vi.0.ps ../html/vi.0.html
+
+vi.0: vi.1
+       ${ROFF} -man -Tascii < vi.1 > $@
+       chmod 444 $@
+
+vi.0.ps: vi.1
+       ${ROFF} -man < vi.1 > $@
+       chmod 444 $@
+
+../html/vi.0.html: vi.1
+       test -d ../html || mkdir ../html
+       ${ROFF} -man -Thtml < vi.1 | \
+           sed 's/<img src="$<.*png">//' > $@
+       rm -f "$<"*png
+       chmod 444 $@
+
+clean:
+       rm -f vi.0 vi.0.ps ../html/vi.0.html
diff --git a/dist/nvi/docs/vi.man/spell.ok b/dist/nvi/docs/vi.man/spell.ok
new file mode 100644 (file)
index 0000000..80ebcab
--- /dev/null
@@ -0,0 +1,179 @@
+Ar
+Bostic
+CDPATH
+COLUMNSXX
+Cscope
+Ds
+EXINIT
+Ee
+Ev
+Fa
+Ff
+Fl
+HUnhsh
+IPLPPPQPP
+LIpplpipbp
+Li
+Lite
+NEXINIT
+NHSHH
+Nex
+Nn
+POSIX
+Pp
+QQ
+SIGWINCHXX
+Std
+Sy
+TMPDIR
+Tt
+USD
+Unmap
+VI
+Vi
+XXXX
+ZZ
+ags
+ai
+altwerase
+ap
+autoindent
+autoprint
+autowrite
+aw
+bf
+bigwords
+cd
+cdpath
+cedit
+cmd
+co
+creens
+cs
+ctags
+db
+dbopen
+dd
+di
+dir
+dit
+doc
+docs
+eFRrsv
+eFRrv
+eFlRrv
+ead
+eb
+edcompatible
+egrep
+elete
+errorbells
+esc
+exrc
+exu
+fg
+filec
+hange
+hardtabs
+ht
+ic
+iclower
+ignorecase
+ile
+ind
+ious
+ist
+ize
+keytime
+leftright
+lhs
+li
+libc
+lobal
+lp
+matchtime
+mber
+mesg
+mk
+modeful
+modeline
+modelines
+nex
+nexrc
+nk
+nonblank
+nooption
+noprint
+nsert
+nul
+nvi
+oin
+onnections
+ove
+ppend
+prev
+pu
+readonly
+rec
+recdir
+redist
+rhs
+rint
+rk
+ro
+rsion
+sccs
+scr
+se
+searchincr
+sh
+shareware
+shellmeta
+shiftwidth
+showmatch
+showmode
+sidescroll
+slowopen
+sm
+smd
+sourceany
+su
+sual
+sw
+ta
+tabstop
+taglength
+tagn
+tagp
+tagstring
+th's
+tildeop
+tl
+tmp
+tr
+ts
+ttytype
+ttywerase
+ubstitute
+uffers
+uit
+unm
+urce
+var
+ve
+vi
+viu
+wa
+wi
+windowname
+wl
+wm
+wn
+wq
+wraplen
+wrapmargin
+wrapscan
+writeany
+ws
+ya
+yy
diff --git a/dist/nvi/docs/vi.man/vi.1 b/dist/nvi/docs/vi.man/vi.1
new file mode 100644 (file)
index 0000000..38efb87
--- /dev/null
@@ -0,0 +1,1638 @@
+.\"    $NetBSD: vi.1,v 1.5 2010/08/30 10:41:54 wiz Exp $
+.\"
+.\" Copyright (c) 1994
+.\"     The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\"    Keith Bostic.  All rights reserved.
+.\"
+.\" This document may not be republished without written permission from
+.\" Keith Bostic. 
+.\"
+.\" See the LICENSE file for redistribution information.
+.\"
+.\"     Id: vi.1,v 8.53 2001/01/28 13:20:06 skimo Exp (Berkeley) Date: 2001/01/28 13:20:06
+.\"
+.TH VI 1 "%Q%"
+.UC
+.SH NAME
+ex, vi, view \- text editors
+.SH SYNOPSIS
+.B ex
+[\c
+.B -eFGRrSsv\c
+] [\c
+.BI -c " cmd"\c
+] [\c
+.BI -t " tag"\c
+] [\c
+.BI -w " size"\c
+] [file ...]
+.br
+.B vi
+[\c
+.B -eFlRrSv\c
+] [\c
+.BI -c " cmd"\c
+] [\c
+.BI -t " tag"\c
+] [\c
+.BI -w " size"\c
+] [file ...]
+.br
+.B view
+[\c
+.B -eFGRrSv\c
+] [\c
+.BI -c " cmd"\c
+] [\c
+.BI -t " tag"\c
+] [\c
+.BI -w " size"\c
+] [file ...]
+.SH LICENSE
+The vi program is freely redistributable.  You are welcome to copy,
+modify and share it with others under the conditions listed in the
+LICENSE file.  If any company (not individual!) finds vi sufficiently
+useful that you would have purchased it, or if any company wishes to
+redistribute it, contributions to the authors would be appreciated.
+.SH DESCRIPTION
+.I \&Vi
+is a screen oriented text editor.
+.I \&Ex
+is a line-oriented text editor.
+.I \&Ex
+and
+.I \&vi
+are different interfaces to the same program,
+and it is possible to switch back and forth during an edit session.
+.I View
+is the equivalent of using the
+.B \-R
+(read-only) option of
+.IR \&vi .
+.PP
+This manual page is the one provided with the
+.I nex/nvi
+versions of the
+.I ex/vi
+text editors.
+.I Nex/nvi
+are intended as bug-for-bug compatible replacements for the original
+Fourth Berkeley Software Distribution (4BSD)
+.I \&ex
+and
+.I \&vi
+programs.
+For the rest of this manual page,
+.I nex/nvi
+is used only when it's necessary to distinguish it from the historic
+implementations of
+.IR ex/vi .
+.PP
+This manual page is intended for users already familiar with
+.IR ex/vi .
+Anyone else should almost certainly read a good tutorial on the
+editor before this manual page.
+If you're in an unfamiliar environment, and you absolutely have to
+get work done immediately, read the section after the options
+description, entitled ``Fast Startup''.
+It's probably enough to get you going.
+.PP
+The following options are available:
+.TP
+.B \-c
+Execute
+.B cmd
+immediately after starting the edit session.
+Particularly useful for initial positioning in the file, however
+.B cmd
+is not limited to positioning commands.
+This is the POSIX 1003.2 interface for the historic ``+cmd'' syntax.
+.I Nex/nvi
+supports both the old and new syntax.
+.TP
+.B \-e
+Start editing in ex mode, as if the command name were
+.IR \&ex .
+.TP
+.B \-F
+Don't copy the entire file when first starting to edit.
+(The default is to make a copy in case someone else modifies
+the file during your edit session.)
+.TP
+.B \-G
+Start editing in gtags mode, as if the gtagsmode option was set.
+.TP
+.B \-l
+Start editing with the lisp and showmatch options set.
+.TP
+.B \-R
+Start editing in read-only mode, as if the command name was
+.IR view ,
+or the
+.B readonly
+option was set.
+.TP
+.B \-r
+Recover the specified files, or, if no files are specified,
+list the files that could be recovered.
+If no recoverable files by the specified name exist,
+the file is edited as if the
+.B \-r
+option had not been specified.
+.TP
+.B \-S
+Run with the
+.B secure
+edit option set, disallowing all access to external programs.
+.TP
+.B \-s
+Enter batch mode; applicable only to
+.I \&ex
+edit sessions.
+Batch mode is useful when running
+.I \&ex
+scripts.
+Prompts, informative messages and other user oriented message
+are turned off,
+and no startup files or environmental variables are read.
+This is the POSIX 1003.2 interface for the historic ``\-'' argument.
+.I \&Nex/nvi
+supports both the old and new syntax.
+.TP
+.B \-t
+Start editing at the specified tag.
+(See
+.IR ctags (1)).
+.TP
+.B \-w
+Set the initial window size to the specified number of lines.
+.TP
+.B \-v
+Start editing in vi mode, as if the command name was
+.I \&vi
+or
+.IR view .
+.PP
+Command input for
+.I ex/vi
+is read from the standard input.
+In the
+.I \&vi
+interface, it is an error if standard input is not a terminal.
+In the
+.I \&ex
+interface, if standard input is not a terminal,
+.I \&ex
+will read commands from it regardless, however, the session will be a
+batch mode session, exactly as if the
+.B \-s
+option had been specified.
+.PP
+.I Ex/vi
+exits 0 on success, and greater than 0 if an error occurs.
+.SH FAST STARTUP
+This section will tell you the minimum amount that you need to
+do simple editing tasks using
+.IR \&vi .
+If you've never used any screen editor before, you're likely to have
+problems even with this simple introduction.
+In that case you should find someone that already knows
+.I \&vi
+and have them walk you through this section.
+.PP
+.I \&Vi
+is a screen editor.
+This means that it takes up almost the entire screen, displaying part
+of the file on each screen line, except for the last line of the screen.
+The last line of the screen is used for you to give commands to
+.IR \&vi ,
+and for
+.I \&vi
+to give information to you.
+.PP
+The other fact that you need to understand is that
+.I \&vi
+is a modeful editor, i.e. you are either entering text or you
+are executing commands, and you have to be in the right mode
+to do one or the other.
+You will be in command mode when you first start editing a file.
+There are commands that switch you into input mode.
+There is only one key that takes you out of input mode,
+and that is the <escape> key.
+(Key names are written using less-than and greater-than signs, e.g.
+<escape> means the ``escape'' key, usually labeled ``esc'' on your
+terminal's keyboard.)
+If you're ever confused as to which mode you're in,
+keep entering the <escape> key until
+.I \&vi
+beeps at you.
+(Generally,
+.I \&vi
+will beep at you if you try and do something that's not allowed.
+It will also display error messages.)
+.PP
+To start editing a file, enter the command ``vi file_name<carriage-return>''.
+The command you should enter as soon as you start editing is
+``:set verbose showmode<carriage-return>''.
+This will make the editor give you verbose error messages and display
+the current mode at the bottom of the screen.
+.PP
+The commands to move around the file are:
+.TP
+.B h
+Move the cursor left one character.
+.TP
+.B j
+Move the cursor down one line.
+.TP
+.B k
+Move the cursor up one line.
+.TP
+.B l
+Move the cursor right one character.
+.TP
+.B <cursor-arrows>
+The cursor arrow keys should work, too.
+.TP
+.B /text<carriage-return>
+Search for the string ``text'' in the file,
+and move the cursor to its first character.
+.PP
+The commands to enter new text are:
+.TP
+.B a
+Append new text,
+.I after
+the cursor.
+.TP
+.B i
+Insert new text,
+.I before
+the cursor.
+.TP
+.B o
+Open a new line below the line the cursor is on, and start
+entering text.
+.TP
+.B O
+Open a new line above the line the cursor is on, and start
+entering text.
+.TP
+.B <escape>
+Once you've entered input mode using the one of the
+.BR \&a ,
+.BR \&i ,
+.BR \&O
+or 
+.B \&o
+commands, use
+.B <escape>
+to quit entering text and return to command mode.
+.PP
+The commands to copy text are:
+.TP
+.B yy
+Copy the line the cursor is on.
+.TP
+.B p
+Append the copied line after the line the cursor is on.
+.PP
+The commands to delete text are:
+.TP
+.B dd
+Delete the line the cursor is on.
+.TP
+.B x
+Delete the character the cursor is on.
+.PP
+The commands to write the file are:
+.TP
+.B :w<carriage-return>
+Write the file back to the file with the name that you originally used
+as an argument on the
+.I \&vi
+command line.
+.TP
+.B ":w file_name<carriage-return>"
+Write the file back to the file with the name ``file_name''.
+.PP
+The commands to quit editing and exit the editor are:
+.TP
+.B :q<carriage-return>
+Quit editing and leave vi (if you've modified the file, but not
+saved your changes,
+.I \&vi
+will refuse to quit).
+.TP
+.B :q!<carriage-return>
+Quit, discarding any modifications that you may have made.
+.PP
+One final caution.
+Unusual characters can take up more than one column on the screen,
+and long lines can take up more than a single screen line.
+The above commands work on ``physical'' characters and lines,
+i.e. they affect the entire line no matter how many screen lines it
+takes up and the entire character no matter how many screen columns
+it takes up.
+.SH VI COMMANDS
+The following section describes the commands available in the command
+mode of the
+.I \&vi
+editor.
+In each entry below, the tag line is a usage synopsis for the command
+character.
+.PP
+.TP
+.B "[count] <control-A>"
+Search forward
+.I count
+times for the current word.
+.TP
+.B "[count] <control-B>"
+Page backwards
+.I count
+screens.
+.TP
+.B "[count] <control-D>"
+Scroll forward
+.I count
+lines.
+.TP
+.B "[count] <control-E>"
+Scroll forward
+.I count
+lines, leaving the current line and column as is, if possible.
+.TP
+.B "[count] <control-F>"
+Page forward
+.I count
+screens.
+.TP
+.B "<control-G>"
+Display the file information.
+.TP
+.B "<control-H>"
+.TP
+.B "[count] h"
+Move the cursor back
+.I count
+characters in the current line.
+.TP
+.B "[count] <control-J>"
+.TP
+.B "[count] <control-N>"
+.TP
+.B "[count] j"
+Move the cursor down
+.I count
+lines without changing the current column.
+.TP
+.B "<control-L>"
+.TP
+.B "<control-R>"
+Repaint the screen.
+.TP
+.B "[count] <control-M>"
+.TP
+.B "[count] +"
+Move the cursor down
+.I count
+lines to the first nonblank character of that line.
+.TP
+.B "[count] <control-P>"
+.TP
+.B "[count] k"
+Move the cursor up
+.I count
+lines, without changing the current column.
+.TP
+.B "<control-T>"
+Return to the most recent tag context.
+.TP
+.B "<control-U>"
+Scroll backwards
+.I count
+lines.
+.TP
+.B "<control-W>"
+Switch to the next lower screen in the window, or, to the first
+screen if there are no lower screens in the window.
+.TP
+.B "<control-Y>"
+Scroll backwards
+.I count
+lines, leaving the current line and column as is, if possible.
+.TP
+.B "<control-Z>"
+Suspend the current editor session.
+.TP
+.B "<escape>"
+Execute
+.I \&ex
+commands or cancel partial commands.
+.TP
+.B "<control-]>"
+Push a tag reference onto the tag stack.
+In gtagsmode, if at the first column of line,
+locate function references otherwise function definitions.
+.TP
+.B "<control-^>"
+Switch to the most recently edited file.
+.TP
+.B "[count] <space>"
+.TP
+.B "[count] l"
+Move the cursor forward
+.I count
+characters without changing the current line.
+.TP
+.B "[count] ! motion shell-argument(s)"
+Replace text with results from a shell command.
+.TP
+.B "[count] # #|+|-"
+Increment or decrement the cursor number.
+.TP
+.B "[count] $"
+Move the cursor to the end of a line.
+.TP
+.B "%"
+Move to the matching character.
+.TP
+.B "&"
+Repeat the previous substitution command on the current line.
+.TP
+.B "'<character>"
+.TP
+.B "`<character>"
+Return to a context marked by the character
+.IR <character> .
+.TP
+.B "[count] ("
+Back up
+.I count
+sentences.
+.TP
+.B "[count] )"
+Move forward
+.I count
+sentences.
+.TP
+.B "[count] ,"
+Reverse find character
+.I count
+times.
+.TP
+.B "[count] -"
+Move to first nonblank of the previous line,
+.I count
+times.
+.TP
+.B "[count] ."
+Repeat the last
+.I \&vi
+command that modified text.
+.TP
+.B "/RE<carriage-return>"
+.TP
+.B "/RE/ [offset]<carriage-return>"
+.TP
+.B "?RE<carriage-return>"
+.TP
+.B "?RE? [offset]<carriage-return>"
+.TP
+.B "N"
+.TP
+.B "n"
+Search forward or backward for a regular expression.
+.TP
+.B "0"
+Move to the first character in the current line.
+.TP
+.B ":"
+Execute an ex command.
+.TP
+.B "[count] ;"
+Repeat the last character find
+.I count
+times.
+.TP
+.B "[count] < motion"
+.TP
+.B "[count] > motion"
+Shift lines left or right.
+.TP
+.B "@ buffer"
+Execute a named buffer.
+.TP
+.B "[count] A"
+Enter input mode, appending the text after the end of the line.
+.TP
+.B "[count] B"
+Move backwards
+.I count
+bigwords.
+.TP
+.B "[buffer] [count] C"
+Change text from the current position to the end-of-line.
+.TP
+.B "[buffer] D"
+Delete text from the current position to the end-of-line.
+.TP
+.B "[count] E"
+Move forward
+.I count
+end-of-bigwords.
+.TP
+.B "[count] F <character>"
+Search
+.I count
+times backward through the current line for
+.IR <character> .
+.TP
+.B "[count] G"
+Move to line
+.IR count ,
+or the last line of the file if
+.I count
+not specified.
+.TP
+.B "[count] H"
+Move to the screen line
+.I "count - 1"
+lines below the top of the screen.
+.TP
+.B "[count] I"
+Enter input mode, inserting the text at the beginning of the line.
+.TP
+.B "[count] J"
+Join lines.
+.TP
+.B "[count] L"
+Move to the screen line
+.I "count - 1"
+lines above the bottom of the screen.
+.TP
+.B " M"
+Move to the screen line in the middle of the screen.
+.TP
+.B "[count] O"
+Enter input mode, appending text in a new line above the current line.
+.TP
+.B "[buffer] P"
+Insert text from a buffer.
+.TP
+.B "Q"
+Exit
+.I \&vi
+(or visual) mode and switch to
+.I \&ex
+mode.
+.TP
+.B "[count] R"
+Enter input mode, replacing the characters in the current line.
+.TP
+.B "[buffer] [count] S"
+Substitute
+.I count
+lines.
+.TP
+.B "[count] T <character>"
+Search backwards,
+.I count
+times,
+through the current line for the character
+.I after
+the specified
+.IR <character> .
+.TP
+.B "U"
+Restore the current line to its state before the cursor last
+moved to it.
+.TP
+.B "[count] W"
+Move forward
+.I count
+bigwords.
+.TP
+.B "[buffer] [count] X"
+Delete
+.I count
+characters before the cursor.
+.TP
+.B "[buffer] [count] Y"
+Copy (or ``yank'')
+.I count
+lines into the specified buffer.
+.TP
+.B "ZZ"
+Write the file and exit
+.IR \&vi .
+.TP
+.B "[count] [["
+Back up
+.I count
+section boundaries.
+.TP
+.B "[count] ]]"
+Move forward
+.I count
+section boundaries.
+.TP
+.B "\&^"
+Move to first nonblank character on the current line.
+.TP
+.B "[count] _"
+Move down
+.I "count - 1"
+lines, to the first nonblank character.
+.TP
+.B "[count] a"
+Enter input mode, appending the text after the cursor.
+.TP
+.B "[count] b"
+Move backwards
+.I count
+words.
+.TP
+.B "[buffer] [count] c motion"
+Change a region of text.
+.TP
+.B "[buffer] [count] d motion"
+Delete a region of text.
+.TP
+.B "[count] e"
+Move forward
+.I count
+end-of-words.
+.TP
+.B "[count] f<character>"
+Search forward,
+.I count
+times, through the rest of the current line for
+.IR <character> .
+.TP
+.B "[count] i"
+Enter input mode, inserting the text before the cursor.
+.TP
+.B "m <character>"
+Save the current context (line and column) as
+.IR <character> .
+.TP
+.B "[count] o"
+Enter input mode, appending text in a new line under the current line.
+.TP
+.B "[buffer] p"
+Append text from a buffer.
+.TP
+.B "[count] r <character>"
+Replace
+.I count
+characters.
+.TP
+.B "[buffer] [count] s"
+Substitute
+.I count
+characters in the current line starting with the current character.
+.TP
+.B "[count] t <character>"
+Search forward,
+.I count
+times, through the current line for the character immediately
+.I before
+.IR <character> .
+.TP
+.B "u"
+Undo the last change made to the file.
+.TP
+.B "[count] w"
+Move forward
+.I count
+words.
+.TP
+.B "[buffer] [count] x"
+Delete
+.I count
+characters.
+.TP
+.B "[buffer] [count] y motion"
+Copy (or ``yank'')
+a text region specified by the
+.I count
+and motion into a buffer.
+.TP
+.B "[count1] z [count2] -|.|+|^|<carriage-return>"
+Redraw, optionally repositioning and resizing the screen.
+.TP
+.B "[count] {"
+Move backward
+.I count
+paragraphs.
+.TP
+.B "[count] |"
+Move to a specific
+.I column
+position on the current line.
+.TP
+.B "[count] }"
+Move forward
+.I count
+paragraphs.
+.TP
+.B "[count] ~"
+Reverse the case of the next
+.I count
+character(s).
+.TP
+.B "[count] ~ motion"
+Reverse the case of the characters in a text region specified by the
+.I count
+and
+.IR motion .
+.TP
+.B "<interrupt>"
+Interrupt the current operation.
+.SH VI TEXT INPUT COMMANDS
+The following section describes the commands available in the text
+input mode of the
+.I \&vi
+editor.
+.PP
+.TP
+.B "<nul>"
+Replay the previous input.
+.TP
+.B "<control-D>"
+Erase to the previous
+.B shiftwidth
+column boundary.
+.TP
+.B "^<control-D>"
+Erase all of the autoindent characters, and reset the autoindent level.
+.TP
+.B "0<control-D>"
+Erase all of the autoindent characters.
+.TP
+.B "<control-T>"
+Insert sufficient
+.I <tab>
+and
+.I <space>
+characters to move forward to the next
+.B shiftwidth
+column boundary.
+If
+.B expandtab
+is set, only insert
+.I <space>
+characters.
+.TP
+.B "<erase>
+.TP
+.B "<control-H>"
+Erase the last character.
+.TP
+.B "<literal next>"
+Quote the next character.
+.TP
+.B "<escape>
+Resolve all text input into the file, and return to command mode.
+.TP
+.B "<line erase>"
+Erase the current line.
+.TP
+.B "<control-W>"
+.TP
+.B "<word erase>"
+Erase the last word.
+The definition of word is dependent on the
+.B altwerase
+and
+.B ttywerase
+options.
+.TP
+.B "<control-X>[0-9A-Fa-f]+"
+Insert a character with the specified hexadecimal value into the text.
+.TP
+.B "<interrupt>"
+Interrupt text input mode, returning to command mode.
+.SH EX COMMANDS
+The following section describes the commands available in the
+.I \&ex
+editor.
+In each entry below, the tag line is a usage synopsis for the command.
+.PP
+.TP
+.B "<end-of-file>"
+Scroll the screen.
+.TP
+.B "! argument(s)"
+.TP
+.B "[range]! argument(s)"
+Execute a shell command, or filter lines through a shell command.
+.TP
+.B \&"
+A comment.
+.TP
+.B "[range] nu[mber] [count] [flags]"
+.TP
+.B "[range] # [count] [flags]"
+Display the selected lines, each preceded with its line number.
+.TP
+.B "@ buffer"
+.TP
+.B "* buffer"
+Execute a buffer.
+.TP
+.B "[line] a[ppend][!]"
+The input text is appended after the specified line.
+.TP
+.B "[range] c[hange][!] [count]"
+The input text replaces the specified range.
+.TP
+.B "cs[cope] add | find | help | kill | reset"
+Execute a Cscope command.
+.TP
+.B "[range] d[elete] [buffer] [count] [flags]"
+Delete the lines from the file.
+.TP
+.B "di[splay] b[uffers] | c[onnections] | s[creens] | t[ags]"
+Display buffers, Cscope connections, screens or tags.
+.TP
+.B "[Ee][dit][!] [+cmd] [file]"
+.TP
+.B "[Ee]x[!] [+cmd] [file]"
+Edit a different file.
+.TP
+.B "exu[sage] [command]"
+Display usage for an
+.I \&ex
+command.
+.TP
+.B "f[ile] [file]"
+Display and optionally change the file name.
+.TP
+.B "[Ff]g [name]"
+.I \&Vi
+mode only.
+Foreground the specified screen.
+.TP
+.B "[range] g[lobal] /pattern/ [commands]"
+.TP
+.B "[range] v /pattern/ [commands]"
+Apply commands to lines matching (or not matching) a pattern.
+.TP
+.B "he[lp]"
+Display a help message.
+.TP
+.B "[line] i[nsert][!]"
+The input text is inserted before the specified line.
+.TP
+.B "[range] j[oin][!] [count] [flags]"
+Join lines of text together.
+.TP
+.B "[range] l[ist] [count] [flags]"
+Display the lines unambiguously.
+.TP
+.B "map[!] [lhs rhs]"
+Define or display maps (for
+.I \&vi
+only).
+.TP
+.B "[line] ma[rk] <character>"
+.TP
+.B "[line] k <character>"
+Mark the line with the mark
+.IR <character> .
+.TP
+.B "[range] m[ove] line"
+Move the specified lines after the target line.
+.TP
+.B "mk[exrc][!] file"
+Write the abbreviations, editor options and maps to the specified
+file.
+.TP
+.B "[Nn][ext][!] [file ...]"
+Edit the next file from the argument list.
+.TP
+.B "[line] o[pen] /pattern/ [flags]"
+Enter open mode.
+.TP
+.B "pre[serve]"
+Save the file in a form that can later be recovered using the
+.I \&ex
+.B \-r
+option.
+.TP
+.B "[Pp]rev[ious][!]"
+Edit the previous file from the argument list.
+.TP
+.B "[range] p[rint] [count] [flags]"
+Display the specified lines.
+.TP
+.B "[line] pu[t] [buffer]"
+Append buffer contents to the current line.
+.TP
+.B "q[uit][!]"
+End the editing session.
+.TP
+.B "[line] r[ead][!] [file]"
+Read a file.
+.TP
+.B "rec[over] file"
+Recover
+.I file
+if it was previously saved.
+.TP
+.B "res[ize] [+|-]size"
+.I \&Vi
+mode only.
+Grow or shrink the current screen.
+.TP
+.B "rew[ind][!]"
+Rewind the argument list.
+.TP
+.B "rta[g][!] tagstring"
+Edit the file referring the specified tag. (Only in gtagsmode)
+.TP
+.B "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
+Display or set editor options.
+.TP
+.B "sh[ell]"
+Run a shell program.
+.TP
+.B "so[urce] file"
+Read and execute
+.I \&ex
+commands from a file.
+.TP
+.B "[range] s[ubstitute] [/pattern/replace/] [options] [count] [flags]"
+.TP
+.B "[range] & [options] [count] [flags]"
+.TP
+.B "[range] ~ [options] [count] [flags]"
+Make substitutions.
+.TP
+.B "su[spend][!]"
+.TP
+.B "st[op][!]"
+.TP
+.B <suspend>
+Suspend the edit session.
+.TP
+.B "[Tt]a[g][!] tagstring"
+Edit the file containing the specified tag.
+.TP
+.B "tagn[ext][!]"
+Edit the file containing the next context for the current tag.
+.TP
+.B "tagp[op][!] [file | number]"
+Pop to the specified tag in the tags stack.
+.TP
+.B "tagp[rev][!]"
+Edit the file containing the previous context for the current tag.
+.TP
+.B "unm[ap][!] lhs"
+Unmap a mapped string.
+.TP
+.B "ve[rsion]"
+Display the version of the
+.I \&ex/vi
+editor.
+.TP
+.B "[line] vi[sual] [type] [count] [flags]"
+.I \&Ex
+mode only.
+Enter
+.IR \&vi .
+.TP
+.B "[Vi]i[sual][!] [+cmd] [file]"
+.I \&Vi
+mode only.
+Edit a new file.
+.TP
+.B "viu[sage] [command]"
+Display usage for a
+.I \&vi
+command.
+.TP
+.B "[range] w[rite][!] [>>] [file]"
+.TP
+.B "[range] w[rite] [!] [file]"
+.TP
+.B "[range] wn[!] [>>] [file]"
+.TP
+.B "[range] wq[!] [>>] [file]"
+Write the file.
+.TP
+.B "[range] x[it][!] [file]"
+Write the file if it has been modified.
+.TP
+.B "[range] ya[nk] [buffer] [count]"
+Copy the specified lines to a buffer.
+.TP
+.B "[line] z [type] [count] [flags]"
+Adjust the window.
+.SH SET OPTIONS
+There are a large number of options that may be set (or unset) to
+change the editor's behavior.
+This section describes the options, their abbreviations and their
+default values.
+.PP
+In each entry below, the first part of the tag line is the full name
+of the option, followed by any equivalent abbreviations.
+The part in square brackets is the default value of the option.
+Most of the options are boolean, i.e. they are either on or off,
+and do not have an associated value.
+.PP
+Options apply to both
+.I \&ex
+and
+.I \&vi
+modes, unless otherwise specified.
+.PP
+.TP
+.B "altwerase [off]"
+.I \&Vi
+only.
+Select an alternate word erase algorithm.
+.TP
+.B "autoindent, ai [off]"
+Automatically indent new lines.
+.TP
+.B "autoprint, ap [off]"
+.I \&Ex
+only.
+Display the current line automatically.
+.TP
+.B "autowrite, aw [off]"
+Write modified files automatically when changing files.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms backup [QQ]
+.TP
+.B "\*(ms"
+.tr QQ
+Backup files before they are overwritten.
+.TP
+.B "beautify, bf [off]"
+Discard control characters.
+.TP
+.B "cdpath [environment variable CDPATH, or current directory]"
+The directory paths used as path prefixes for the
+.B cd
+command.
+.TP
+.B "cedit [no default]"
+Set the character to edit the colon command-line history.
+.TP
+.B "columns, co [80]"
+Set the number of columns in the screen.
+.TP
+.B "comment [off]"
+.I \&Vi
+only.
+Skip leading comments in shell, C and C++ language files.
+.TP
+.B "directory, dir [environment variable TMPDIR, or /tmp]"
+The directory where temporary files are created.
+.TP
+.B "edcompatible, ed [off]"
+Remember the values of the ``c'' and ``g'' suffices to the
+.B substitute
+commands, instead of initializing them as unset for each new
+command.
+.TP
+.B "errorbells, eb [off]"
+.I \&Ex
+only.
+Announce error messages with a bell.
+.TP
+.B "expandtab, et [off]"
+Prevent the use of
+.I <tab>
+characters in leading whitespace when shifting text, autoindenting,
+indenting with
+.BR "<control-T>" ,
+or outdenting with
+.BR "<control-D>" .
+.TP
+.B "exrc, ex [off]"
+Read the startup files in the local directory.
+.TP
+.B "extended [off]"
+Regular expressions are extended (i.e.
+.IR egrep (1)\-\c
+style) expressions.
+.TP
+.B "filec [no default]"
+Set the character to perform file path completion on the colon
+command line.
+.TP
+.B "flash [on]"
+Flash the screen instead of beeping the keyboard on error.
+.TP
+.B "gtagsmode, gt [off]"
+Use GTAGS and GRTAGS instead of tags.
+.TP
+.B "hardtabs, ht [8]"
+Set the spacing between hardware tab settings.
+.TP
+.B "iclower [off]"
+Makes all Regular Expressions case-insensitive,
+as long as an upper-case letter does not appear in the search string.
+.TP
+.B "ignorecase, ic [off]"
+Ignore case differences in regular expressions.
+.TP
+.B "keytime [6]"
+The 10th's of a second
+.I ex/vi
+waits for a subsequent key to complete a key mapping.
+.TP
+.B "leftright [off]"
+.I \&Vi
+only.
+Do left-right scrolling.
+.TP
+.B "lines, li [24]"
+.I \&Vi
+only.
+Set the number of lines in the screen.
+.TP
+.B "lisp [off]"
+.I \&Vi
+only.
+Modify various search commands and options to work with Lisp.
+.I "This option is not yet implemented."
+.TP
+.B "list [off]"
+Display lines in an unambiguous fashion.
+.TP
+.B "lock [on]"
+Attempt to get an exclusive lock on any file being edited,
+read or written.
+.TP
+.B "magic [on]"
+Treat certain characters specially in regular expressions.
+.TP
+.B "matchchars [[]{}()<>]"
+Character pairs looked for by the % command.
+.TP
+.B "matchtime [7]"
+.I \&Vi
+only.
+The 10th's of a second
+.I ex/vi
+pauses on the matching character when the
+.B showmatch
+option is set.
+.TP
+.B "mesg [on]"
+Permit messages from other users.
+.TP
+.B "modelines, modeline [off]"
+Read the first and last few lines of each file for
+.I ex
+commands.
+.I "This option will never be implemented."
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms noprint [QQ]
+.TP
+.B "\*(ms"
+.tr QQ
+Characters that are never handled as printable characters.
+.TP
+.B "number, nu [off]"
+Precede each line displayed with its current line number.
+.TP
+.B "octal [off]"
+Display unknown characters as octal numbers, instead of the default
+hexadecimal.
+.TP
+.B "open [on]"
+.I \&Ex
+only.
+If this option is not set, the
+.B open
+and
+.B visual
+commands are disallowed.
+.TP
+.B "optimize, opt [on]"
+.I \&Vi
+only.
+Optimize text throughput to dumb terminals.
+.I "This option is not yet implemented."
+.TP
+.B "paragraphs, para [IPLPPPQPP LIpplpipbp]"
+.I \&Vi
+only.
+Define additional paragraph boundaries for the
+.B \&{
+and
+.B \&}
+commands.
+.TP
+.B "path []"
+Define additional directories to search for files being edited.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms print [QQ]
+.TP
+.B "\*(ms"
+.tr QQ
+Characters that are always handled as printable characters.
+.TP
+.B "prompt [on]"
+.I \&Ex
+only.
+Display a command prompt.
+.TP
+.B "readonly, ro [off]"
+Mark the file and session as read-only.
+.TP
+.B "recdir [/var/tmp/vi.recover]"
+The directory where recovery files are stored.
+.TP
+.B "redraw, re [off]"
+.I \&Vi
+only.
+Simulate an intelligent terminal on a dumb one.
+.I "This option is not yet implemented."
+.TP
+.B "remap [on]"
+Remap keys until resolved.
+.TP
+.B "report [5]"
+Set the number of lines about which the editor reports changes
+or yanks.
+.TP
+.B "ruler [off]"
+.I \&Vi
+only.
+Display a row/column ruler on the colon command line.
+.TP
+.B "scroll, scr [window / 2]"
+Set the number of lines scrolled.
+.TP
+.B "searchincr [off]"
+Makes the
+.B \&/
+and
+.B \&?
+commands incremental.
+.TP
+.B "sections, sect [NHSHH HUnhsh]"
+.I \&Vi
+only.
+Define additional section boundaries for the
+.B \&[[
+and
+.B \&]]
+commands.
+.TP
+.B "secure [off]"
+Turns off all access to external programs.
+.TP
+.B "shell, sh [environment variable SHELL, or /bin/sh]"
+Select the shell used by the editor.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms shellmeta [~{[*?$`'Q\e]
+.TP
+.B "\*(ms"
+.tr QQ
+Set the meta characters checked to determine if file name expansion
+is necessary.
+.TP
+.B "shiftwidth, sw [8]"
+Set the autoindent and shift command indentation width.
+.TP
+.B "showmatch, sm [off]"
+.I \&Vi
+only.
+Note matching ``{'' and ``('' for ``}'' and ``)'' characters.
+.TP
+.B "showmode, smd [off]"
+.I \&Vi
+only.
+Display the current editor mode and a ``modified'' flag.
+.TP
+.B "sidescroll [16]"
+.I \&Vi
+only.
+Set the amount a left-right scroll will shift.
+.TP
+.B "slowopen, slow [off]"
+Delay display updating during text input.
+.I "This option is not yet implemented."
+.TP
+.B "sourceany [off]"
+Read startup files not owned by the current user.
+.I "This option will never be implemented."
+.TP
+.B "tabstop, ts [8]"
+This option sets tab widths for the editor display.
+.TP
+.B "taglength, tl [0]"
+Set the number of significant characters in tag names.
+.TP
+.B "tags, tag [tags /var/db/libc.tags /sys/kern/tags]"
+Set the list of tags files.
+.TP
+.B "term, ttytype, tty [environment variable TERM]"
+Set the terminal type.
+.TP
+.B "terse [off]"
+This option has historically made editor messages less verbose.
+It has no effect in this implementation.
+.TP
+.B "tildeop [off]"
+Modify the
+.B \&~
+command to take an associated motion.
+.TP
+.B "timeout, to [on]"
+Time out on keys which may be mapped.
+.TP
+.B "ttywerase [off]"
+.I \&Vi
+only.
+Select an alternate erase algorithm.
+.TP
+.B "verbose [off]"
+.I \&Vi
+only.
+Display an error message for every error.
+.TP
+.B "w300 [no default]"
+.I \&Vi
+only.
+Set the window size if the baud rate is less than 1200 baud.
+.TP
+.B "w1200 [no default]"
+.I \&Vi
+only.
+Set the window size if the baud rate is equal to 1200 baud.
+.TP
+.B "w9600 [no default]"
+.I \&Vi
+only.
+Set the window size if the baud rate is greater than 1200 baud.
+.TP
+.B "warn [on]"
+.I \&Ex
+only.
+This option causes a warning message to the terminal if the file has
+been modified, since it was last written, before a
+.B \&!
+command.
+.TP
+.B "window, w, wi [environment variable LINES]"
+Set the window size for the screen.
+.TP
+.B "windowname [off]"
+Change the icon/window name to the current file name even if it can't
+be restored on editor exit.
+.TP
+.B "wraplen, wl [0]"
+.I \&Vi
+only.
+Break lines automatically, the specified number of columns from the
+left-hand margin.
+If both the
+.B wraplen
+and
+.B wrapmargin
+edit options are set, the
+.B wrapmargin
+value is used.
+.TP
+.B "wrapmargin, wm [0]"
+.I \&Vi
+only.
+Break lines automatically, the specified number of columns from the
+right-hand margin.
+If both the
+.B wraplen
+and
+.B wrapmargin
+edit options are set, the
+.B wrapmargin
+value is used.
+.TP
+.B "wrapscan, ws [on]"
+Set searches to wrap around the end or beginning of the file.
+.TP
+.B "writeany, wa [off]"
+Turn off file-overwriting checks.
+.SH "ENVIRONMENT VARIABLES
+.TP
+.I COLUMNS
+The number of columns on the screen.
+This value overrides any system or terminal specific values.
+If the
+.I COLUMNS
+environmental variable is not set when
+.I ex/vi
+runs, or the
+.B columns
+option is explicitly reset by the user,
+.I ex/vi
+enters the value into the environment.
+.TP
+.I EXINIT
+A list of
+.I \&ex
+startup commands, read if the variable
+.I NEXINIT
+is not set.
+.TP
+.I HOME
+The user's home directory, used as the initial directory path
+for the startup ``$\fIHOME\fP/.nexrc'' and ``$\fIHOME\fP/.exrc''
+files.
+This value is also used as the default directory for the
+.I \&vi
+.B \&cd
+command.
+.TP
+.I LINES
+The number of rows on the screen.
+This value overrides any system or terminal specific values.
+If the
+.I LINES
+environmental variable is not set when
+.I ex/vi
+runs, or the
+.B lines
+option is explicitly reset by the user,
+.I ex/vi
+enters the value into the environment.
+.TP
+.I NEXINIT
+A list of
+.I \&ex
+startup commands.
+.TP
+.I SHELL
+The user's shell of choice (see also the
+.B shell
+option).
+.TP
+.I TERM
+The user's terminal type.
+The default is the type ``unknown''.
+If the
+.I TERM
+environmental variable is not set when
+.I ex/vi
+runs, or the
+.B term
+option is explicitly reset by the user,
+.I ex/vi
+enters the value into the environment.
+.TP
+.I TMPDIR
+The location used to stored temporary files (see also the
+.B directory
+edit option).
+.SH ASYNCHRONOUS EVENTS
+.TP
+SIGALRM
+.I \&Vi/ex
+uses this signal for periodic backups of file modifications and to
+display ``busy'' messages when operations are likely to take a long time.
+.TP
+SIGHUP
+.TP
+SIGTERM
+If the current buffer has changed since it was last written in its
+entirety, the editor attempts to save the modified file so it can
+be later recovered.
+See the
+.I \&vi/ex
+Reference manual section entitled ``Recovery'' for more information.
+.TP
+SIGINT
+When an interrupt occurs,
+the current operation is halted,
+and the editor returns to the command level.
+If interrupted during text input,
+the text already input is resolved into the file as if the text
+input had been normally terminated.
+.TP
+SIGWINCH
+The screen is resized.
+See the
+.I \&vi/ex
+Reference manual section entitled ``Sizing the Screen'' for more information.
+.TP
+SIGCONT
+.TP
+SIGQUIT
+.TP
+SIGTSTP
+.I \&Vi/ex
+ignores these signals.
+.SH FILES
+.TP
+/bin/sh
+The default user shell.
+.TP
+/etc/vi.exrc
+System-wide vi startup file.
+.TP
+/tmp
+Temporary file directory.
+.TP
+/var/tmp/vi.recover
+The default recovery file directory.
+.TP
+$HOME/.nexrc
+1st choice for user's home directory startup file.
+.TP
+$HOME/.exrc
+2nd choice for user's home directory startup file.
+.TP
+\&.nexrc
+1st choice for local directory startup file.
+.TP
+\&.exrc
+2nd choice for local directory startup file.
+.SH SEE ALSO
+.IR ctags (1),
+.IR more (1),
+.IR curses (3),
+.IR dbopen (3)
+.sp
+The ``Vi Quick Reference'' card.
+.sp
+``An Introduction to Display Editing with Vi'', found in the
+``UNIX User's Manual Supplementary Documents''
+section of both the 4.3BSD and 4.4BSD manual sets.
+This document is the closest thing available to an introduction to the
+.I \&vi
+screen editor.
+.sp
+``Ex Reference Manual (Version 3.7)'',
+found in the
+``UNIX User's Manual Supplementary Documents''
+section of both the 4.3BSD and 4.4BSD manual sets.
+This document is the final reference for the
+.I \&ex
+editor, as distributed in most historic 4BSD and System V systems.
+.sp
+``Edit: A tutorial'',
+found in the
+``UNIX User's Manual Supplementary Documents''
+section of the 4.3BSD manual set.
+This document is an introduction to a simple version of the
+.I \&ex
+screen editor.
+.sp
+``Ex/Vi Reference Manual'',
+found in the
+``UNIX User's Manual Supplementary Documents''
+section of the 4.4BSD manual set.
+This document is the final reference for the
+.I \&nex/nvi
+text editors, as distributed in 4.4BSD and 4.4BSD-Lite.
+.PP
+.I Roff
+source for all of these documents is distributed with
+.I nex/nvi
+in the
+.I nvi/USD.doc
+directory of the
+.I nex/nvi
+source code.
+.sp
+The files ``autowrite'', ``input'', ``quoting'' and ``structures''
+found in the
+.I nvi/docs/internals
+directory of the
+.I nex/nvi
+source code.
+.SH HISTORY
+The
+.I nex/nvi
+replacements for the
+.I ex/vi
+editor first appeared in 4.4BSD.
+.SH STANDARDS
+.I \&Nex/nvi
+is close to IEEE Std1003.2 (``POSIX'').
+That document differs from historical
+.I ex/vi
+practice in several places; there are changes to be made on both sides.
diff --git a/dist/nvi/docs/vi.ref/Makefile b/dist/nvi/docs/vi.ref/Makefile
new file mode 100644 (file)
index 0000000..7896b1c
--- /dev/null
@@ -0,0 +1,25 @@
+#      Id: Makefile,v 8.25 2001/08/20 09:40:50 skimo Exp (Berkeley) Date: 2001/08/20 09:40:50
+
+MACROS=        -me
+ROFF=  groff
+TBL=   tbl
+
+all: vi.ref.txt vi.ref.ps ../html/vi.ref.html
+
+vi.ref.txt: vi.texi
+       -makeinfo --no-headers vi.texi > $@ 2>/dev/null
+       chmod 444 $@
+
+vi.ref.ps: vi.texi
+       texi2dvi -c vi.texi
+       dvips -o $@ vi.dvi
+       rm -f vi.dvi
+       chmod 444 $@
+
+../html/vi.ref.html: vi.texi
+       test -d ../html || mkdir ../html
+       -makeinfo --html --no-split vi.texi --output=$@ 2>/dev/null
+       chmod 444 $@
+
+clean:
+       rm -f vi.ref.ps vi.ref.txt index index.so ../html/vi.ref.html
diff --git a/dist/nvi/docs/vi.ref/ex.cmd.texi b/dist/nvi/docs/vi.ref/ex.cmd.texi
new file mode 100644 (file)
index 0000000..33af6e7
--- /dev/null
@@ -0,0 +1,1987 @@
+@comment  Copyright (c) 1994
+@c $NetBSD: ex.cmd.texi,v 1.1.1.2 2008/05/18 14:30:59 aymeric Exp $
+@comment       The Regents of the University of California.  All rights reserved.
+@comment  Copyright (c) 1994, 1995, 1996
+@comment       Keith Bostic.  All rights reserved.
+@comment 
+@comment  See the LICENSE file for redistribution information.
+@comment 
+@comment       Id: ex.cmd.texi,v 8.2 2001/08/20 16:05:50 skimo Exp (Berkeley) Date: 2001/08/20 16:05:50
+@comment 
+@chapter Ex Description
+
+The following words have special meanings for
+@CO{ex}
+commands.
+@itemize @bullet
+@cindex "<end-of-file>"
+@IP{<end-of-file>}
+
+The end-of-file character is used to scroll the screen in the
+@CO{ex}
+editor.
+This character is normally
+@LI{<control-D>}.
+However, whatever character is set for the current terminal is supported
+as well as
+@LI{<control-D>}.
+@cindex "line"
+@IP{line}
+
+A single-line address, given in any of the forms described in the
+section entitled
+@QB{Ex Addressing} .
+The default for
+@LI{line}is the current line.
+@cindex "range"
+@IP{range}
+
+A line, or a pair of line addresses, separated by a comma or semicolon.
+(See the section entitled
+@QB{Ex Addressing}
+for more information.)
+The default for range is the current line
+@emph{only},
+i.e.
+@QT{.,.}.
+A percent sign
+@PQ{%}
+stands for the range
+@QT{1,$}.
+The starting address must be less than, or equal to, the ending address.
+@cindex "count"
+@IP{count}
+
+A positive integer, specifying the number of lines to be affected by
+the command; the default is 1.
+Generally, a count past the end-of-file may be specified, e.g. the
+command
+@QT{p 3000}
+in a 10 line file is acceptable, and will print from the current line
+through the last line in the file.
+@cindex "flags"
+@IP{flags}
+
+One or more of the characters
+@QQ{#},
+@QQ{p},
+and
+@QQ{l}.
+When a command that accepts these flags completes, the addressed line(s)
+are written out as if by the corresponding
+@CO{#},
+@CO{l}
+or
+@CO{p}
+commands.
+In addition, any number of
+@QT{+}
+or
+@QT{-}
+characters can be specified before, after, or during the flags, in which
+case the line written is not necessarily the one affected by the command,
+but rather the line addressed by the offset address specified.
+The default for
+@LI{flags}is none.
+@cindex "file"
+@IP{file}
+
+A pattern used to derive a pathname; the default is the current file.
+File names are subjected to normal
+@XR{sh,1}
+word expansions.
+@end itemize
+
+Anywhere a file name is specified, it is also possible to use
+the special string
+@QT{/tmp}.
+This will be replaced with a temporary file name which can be used
+for temporary work, e.g.
+@QT{:e /tmp}
+creates and edits a new file.
+
+If both a count and a range are specified for commands that use either,
+the starting line for the command is the
+@emph{last}
+line addressed by the range, and
+@LI{count}- 1
+subsequent lines are affected by the command, e.g. the command
+@QT{2,3p4}
+prints out lines 3, 4, 5 and 6.
+
+When only a line or range is specified, with no command, the implied
+command is either a
+@CO{list},
+@CO{number}
+or
+@CO{print}
+command.
+The command used is the most recent of the three commands to have been
+used (including any use as a flag).
+If none of these commands have been used before, the
+@CO{print}
+command is the implied command.
+When no range or count is specified and the command line is a blank line,
+the current line is incremented by 1 and then the current line is displayed.
+
+Zero or more whitespace characters may precede or follow the addresses,
+count, flags, or command name.
+Any object following a command name (such as buffer, file, etc.),
+that begins with an alphabetic character,
+should be separated from the command name by at least one whitespace
+character.
+
+Any character, including
+@LI{<carriage-return>},
+@QT{%}
+and
+@QT{#}
+retain their literal value when preceded by a backslash.
+@chapter Ex Commands
+
+The following section describes the commands available in the
+@CO{ex}
+editor.
+In each entry below, the tag line is a usage synopsis for the command.
+
+Each command can be entered as the abbreviation
+(those characters in the synopsis command word preceding the
+@QQ{[}
+character),
+the full command (all characters shown for the command word,
+omitting the
+@QQ{[}
+and
+@QQ{]}
+characters),
+or any leading subset of the full command down to the abbreviation.
+For example, the args command (shown as
+@QT{ar[gs]}
+in the synopsis)
+can be entered as
+@QT{ar},
+@QT{arg}
+or
+@QT{args}.
+
+Each
+@CO{ex}
+command described below notes the new current line after it
+is executed, as well as any options that affect the command.
+@cindex DOUBLEQUOTE
+@deftypefn Command {} {"}
+
+A comment.
+Command lines beginning with the double-quote character
+@PQ{"}
+are ignored.
+This permits comments in editor scripts and startup files.
+@end deftypefn
+@cindex "<control-D>"
+@cindex "<end-of-file>"
+@deftypefn Command {} {<control-D>}
+
+@deftypefnx Command {} {<end-of-file>}
+
+Scroll the screen.
+Write the next N lines, where N is the value of the
+@OP{scroll}
+option.
+The command is the end-of-file terminal character, which may be
+different on different terminals.
+Traditionally, it is the
+@LI{<control-D>}key.
+@sp 1
+Historically, the
+@CO{eof}
+command ignored any preceding count, and the
+@LI{<end-of-file>}character was ignored unless it was entered as the first character
+of the command.
+This implementation treats it as a command
+@emph{only}
+if entered as the first character of the command line, and otherwise
+treats it as any other character.
+@table @asis
+@item Line:
+Set to the last line written.
+@item Options:
+Affected by the
+@OP{scroll}
+option.
+@end table
+@end deftypefn
+@cindex "!"
+@deftypefn Command {} {!} {argument(s)}
+
+@deftypefnx Command {}  {[range]!} {argument(s)}
+Execute a shell command, or filter lines through a shell command.
+In the first synopsis, the remainder of the line after the
+@QT{!}
+character is passed to the program named by the
+@OP{shell}
+option, as a single argument.
+@sp 1
+Within the rest of the line,
+@QT{%}
+and
+@QT{#}
+are expanded into the current and alternate pathnames, respectively.
+The character
+@QT{!}
+is expanded with the command text of the previous
+@CO{!}
+command.
+(Therefore, the command
+@CO{!!}
+repeats the previous
+@CO{!}
+command.)
+The special meanings of
+@QT{%},
+@QT{#},
+and
+@QT{!}
+can be overridden by escaping them with a backslash.
+If no
+@CO{!}
+or
+@CO{:!}
+command has yet been executed, it is an error to use an unescaped
+@QT{!}
+character.
+The
+@CO{!}
+command does
+@emph{not}
+do shell expansion on the strings provided as arguments.
+If any of the above expansions change the command the user entered,
+the command is redisplayed at the bottom of the screen.
+@sp 1
+@CO{Ex}
+then executes the program named by the
+@OP{shell}
+option, with a
+@strong{-c}
+flag followed by the arguments (which are bundled into a single argument).
+@sp 1
+The
+@CO{!}
+command is permitted in an empty file.
+@sp 1
+If the file has been modified since it was last completely written,
+the
+@CO{!}
+command will warn you.
+@sp 1
+A single
+@QT{!}
+character is displayed when the command completes.
+@sp 1
+In the second form of the
+@CO{!}
+command, the remainder of the line after the
+@QT{!}
+is passed to the program named by the
+@OP{shell}
+option, as described above.
+The specified lines are passed to the program as standard input,
+and the standard and standard error output of the program replace
+the original lines.
+@table @asis
+@item Line:
+Unchanged if no range was specified, otherwise set to the first
+line of the range.
+@item Options:
+Affected by the
+@OP{shell}
+and
+@OP{warn}
+options.
+@end table
+@end deftypefn
+@cindex "#"
+@deftypefn Command {[range]} {#} {[count] [flags]}
+
+@cindex "number"
+@deftypefnx Command  {[range]} {nu[mber]} {[count] [flags]}
+Display the selected lines, each preceded with its line number.
+@sp 1
+The line number format is
+@QQ{%6d},
+followed by two spaces.
+@table @asis
+@item Line:
+Set to the last line displayed.
+@item Options:
+Affected by the
+@OP{list}
+option.
+@end table
+@end deftypefn
+@cindex "@@"
+@deftypefn Command {@@} {buffer}
+
+@cindex "*"
+@deftypefnx Command {}  {*} {buffer}
+Execute a buffer.
+Each line in the named buffer is executed as an
+@CO{ex}
+command.
+If no buffer is specified, or if the specified buffer is
+@QT{@@}
+or
+@QT{*},
+the last buffer executed is used.
+@end deftypefn
+@cindex <
+@deftypefn Command {[range]} {<[< ...]} {[count] [flags]}
+
+Shift lines left or right.
+The specified lines are shifted to the left (for the
+@CO{<}
+command) or right (for the
+@CO{>}
+command), by the number of columns specified by the
+@OP{shiftwidth}
+option.
+Only leading whitespace characters are deleted when shifting left;
+once the first column of the line contains a nonblank character,
+the
+@CO{shift}
+command will succeed, but the line will not be modified.
+@sp 1
+If the command character
+@CO{<}
+or
+@CO{>}
+is repeated more than once, the command is repeated once for each
+additional command character.
+@table @asis
+@item Line:
+If the current line is set to one of the lines that are affected
+by the command, it is unchanged.
+Otherwise, it is set to the first nonblank character of the lowest
+numbered line shifted.
+@item Options:
+Affected by the
+@OP{shiftwidth}
+option.
+@end table
+@end deftypefn
+@cindex =
+@deftypefn Command {[line]} {=} {[flags]}
+
+Display the line number of
+@LI{line}(which defaults to the last line in the file).
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex >
+@deftypefn Command {[range]} {>[> ...]} {[count] [flags]}
+
+Shift right.
+The specified lines are shifted to the right by the number of columns
+specified by the
+@OP{shiftwidth}
+option, by inserting tab and space characters.
+Empty lines are not changed.
+@sp 1
+If the command character
+@QT{>}
+is repeated more than once, the command is repeated once for each
+additional command character.
+@table @asis
+@item Line:
+Set to the last line modified by the command.
+@item Options:
+Affected by the
+@OP{shiftwidth}
+option.
+@end table
+@end deftypefn
+@cindex abbrev
+@deftypefn Command {} {ab[brev]} {lhs rhs}
+
+Add an abbreviation to the current abbreviation list.
+When inserting text in
+@CO{vi},
+each time a non-word character is entered after a word character,
+a set of characters ending at the word character are checked for
+a match with
+@LI{lhs}.
+If a match is found, they are replaced with
+@LI{rhs}.
+The set of characters that are checked for a match are defined as follows,
+for inexplicable historical reasons.
+If only one or two characters were entered before the non-word character
+that triggered the check,
+and after the beginning of the insertion,
+or the beginning of the line or the file,
+or the last
+@LI{<blank>}character that was entered,
+then the one or the both characters are checked for a match.
+Otherwise, the set includes both characters,
+as well as the characters that precede them that are the same word
+class (i.e. word or non-word) as the
+@strong{second}
+to last character entered before the non-word character that triggered
+the check,
+back to the first
+@LI{<blank>}character,
+the beginning of the insertion,
+or the beginning of the line or the file.
+@sp 1
+For example, the abbreviations:
+@sp 1
+@multitable {:abbreviate} {/*#i} {/********************}
+@item :abbreviate @tab abc @tab ABC
+@item :abbreviate @tab #i @tab #include
+@item :abbreviate @tab /*#i @tab /*#include
+@end multitable
+will all work, while the abbreviations:
+@sp 1
+@multitable {:abbreviate} {/*#i} {/********************}
+@item :abbreviate @tab a#i @tab A#include
+@item :abbreviate @tab /* @tab /********************
+@end multitable
+will not work, and are not permitted by
+@CO{nvi}.
+@sp 1
+To keep the abbreviation expansion from happening,
+the character immediately following the
+@LI{lhs}characters should be quoted with a
+@LI{<literal-next>}character.
+@sp 1
+The replacement
+@LI{rhs}is itself subject to both further abbreviation expansion and further
+map expansion.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex append
+@deftypefn Command {[line]} {a[ppend][!]}
+
+The input text is appended to the specified line.
+If line 0 is specified, the text is inserted at the beginning of the file.
+Set to the last line input.
+If no lines are input, then set to
+@LI{line},
+or to the first line of the file if a
+@LI{line}of 0 was specified.
+Following the command name with a
+@QT{!}
+character causes the
+@OP{autoindent}
+option to be toggled for the duration of the command.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{autoindent}
+and
+@OP{number}
+options.
+@end table
+@end deftypefn
+@cindex args
+@deftypefn Command {} {ar[gs]}
+
+Display the argument list.
+The current argument is displayed inside of
+@QT{[}
+and
+@QT{]}
+characters.
+The argument list is the list of operands specified on startup,
+which can be replaced using the
+@CO{next}
+command.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex bg
+@deftypefn Command {} {bg}
+
+@CO{Vi}
+mode only.
+Background the current screen.
+The screen is unchanged,
+but is no longer accessible and disappears from the display.
+Use the
+@CO{fg}
+command to bring the screen back to the display foreground.
+@table @asis
+@item Line:
+Set to the current line when the screen was last edited.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex change
+@deftypefn Command {[range]} {c[hange][!]} {[count]}
+
+Replace the lines with input text.
+Following the command name with a
+@QT{!}
+character causes the
+@OP{autoindent}
+option to be toggled for the duration of the command.
+@table @asis
+@item Line:
+Set to the last line input, or, if no lines were input,
+set to the line before the target line, or to the first
+line of the file if there are no lines preceding the target line.
+@item Options:
+Affected by the
+@OP{autoindent}
+and
+@OP{number}
+options.
+@end table
+@cindex cd
+@end deftypefn
+@cindex chdir
+@deftypefn Command {} {chd[ir][!]} {[directory]}
+
+@deftypefnx Command {}  {cd[!]} {[directory]}
+Change the current working directory.
+The
+@LI{directory}argument is subjected to
+@XR{sh,1}
+word expansions.
+When invoked with no directory argument and the
+@LI{HOME}environment variable is set, the directory named by the
+@LI{HOME}environment variable becomes the new current directory.
+Otherwise, the new current directory becomes the directory returned
+by the
+@XR{getpwent,3}
+routine.
+@sp 1
+The
+@CO{chdir}
+command will fail if the file has been modified since the last complete
+write of the file.
+You can override this check by appending a
+@QT{!}
+character to the command.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{cdpath}
+option.
+@end table
+@cindex copy
+@end deftypefn
+@cindex t
+@deftypefn Command {[range]} {co[py]} {line [flags]}
+
+@deftypefnx Command  {[range]} {t} {line [flags]}
+Copy the specified lines (range) after the destination line.
+Line 0 may be specified to insert the lines at the beginning of
+the file.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex cscope
+@deftypefn Command {} {cs[cope]} {command [args]}
+
+Execute a
+@CO{cscope}
+command.
+For more information, see the section of the reference manual entitled
+@QB{Tags, Tag Stacks, and Cscope} .
+@end deftypefn
+@cindex delete
+@deftypefn Command {[range]} {d[elete]} {[buffer] [count] [flags]}
+
+Delete the lines from the file.
+The deleted text is saved in the specified buffer, or, if no buffer
+is specified, in the unnamed buffer.
+If the command name is followed by a letter that could be interpreted
+as either a buffer name or a flag value (because neither a
+@LI{count}or
+@LI{flags}values were given),
+@CO{ex}
+treats the letter as a
+@LI{flags}value if the letter immediately follows the command name,
+without any whitespace separation.
+If the letter is preceded by whitespace characters,
+it treats it as a buffer name.
+@table @asis
+@item Line:
+Set to the line following the deleted lines,
+or to the last line if the deleted lines were at the end.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex display
+@deftypefn Command {} {di[splay]} {b[uffers] | c[onnections] | s[creens] | t[ags]}
+
+Display buffers,
+@CO{cscope}
+connections, screens or tags.
+The
+@CO{display}
+command takes one of three additional arguments, which are as follows:
+@table @asis
+@item b[uffers]
+Display all buffers (including named, unnamed, and numeric)
+that contain text.
+@item c[onnections]
+Display the source directories for all attached
+@CO{cscope}
+databases.
+@item s[creens]
+Display the file names of all background screens.
+@item t[ags]
+Display the tags stack.
+@end table
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex edit
+@deftypefn Command {} {e[dit][!]} {[+cmd] [file]}
+@deftypefnx Command {}  {ex[!]} {[+cmd] [file]}
+@deftypefnx Command {} {vs[plit][!]} {[+cmd] [file]}
+Edit a different file.
+If the current buffer has been modified since the last complete write,
+the command will fail.
+You can override this by appending a
+@QT{!}
+character to the command name.
+@sp 1
+If the
+@QT{+cmd}
+option is specified, that
+@CO{ex}
+command will be executed in the new file.
+Any
+@CO{ex}
+command may be used, although the most common use of this feature is
+to specify a line number or search pattern to set the initial location
+in the new file.
+@sp 1
+Capitalizing the first letter of the command, i.e.,
+@CO{Edit}
+or
+@CO{Ex},
+while in
+@CO{vi}
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@cindex vertical split
+@cindex splitting, vertically
+@CO{vsplit} is similar, but the screen will be split vertically
+to produce the new screen, rather than horizontally.
+
+@table @asis
+@item Line:
+If you have previously edited the file, the current line will be set
+to your last position in the file.
+If that position does not exist, or you have not previously edited the
+file, the current line will be set to the first line of the file if
+you are in
+@CO{vi}
+mode, and the last line of the file if you are in
+@CO{ex}.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex exusage
+@deftypefn Command {} {exu[sage]} {[command]}
+
+Display usage for an
+@CO{ex}
+command.
+If
+@LI{command}is specified, a usage statement for that command is displayed.
+Otherwise, usage statements for all
+@CO{ex}
+commands are displayed.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex file
+@deftypefn Command {} {f[ile]} {[file]}
+
+Display and optionally change the file name.
+If a file name is specified, the current pathname is changed to the
+specified name.
+The current pathname, the number of lines, and the current position
+in the file are displayed.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex fg
+@deftypefn Command {} {fg} {[name]}
+
+@CO{Vi}
+mode only.
+Foreground the specified screen.
+If the argument name doesn't exactly match the name of a file displayed
+by a background screen,
+it is compared against the last component of each of the file names.
+If no background screen is specified,
+the first background screen is foregrounded.
+@sp 1
+By default,
+foregrounding causes the current screen to be swapped with the backgrounded
+screen.
+Capitalizing the first letter of the command, i.e.
+@CO{Fg},
+will foreground the backgrounded screen in a new screen instead of
+swapping it with the current screen.
+@table @asis
+@item Line:
+Set to the current line when the screen was last edited.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex global
+@deftypefn Command {[range]} {g[lobal]} {/pattern/ [commands]}
+
+@cindex v
+@deftypefnx Command  {[range]} {v} {/pattern/ [commands]}
+Apply commands to lines matching (or not matching) a pattern.
+The lines within the given range that match
+@PQ{g[lobal]},
+or do not match
+@PQ{v}
+the given pattern are selected.
+Then, the specified
+@CO{ex}
+command(s) are executed with the current line
+@PQ{.}
+set to each selected line.
+If no range is specified, the entire file is searched for matching,
+or not matching, lines.
+@sp 1
+Multiple commands can be specified, one per line, by escaping each
+@LI{<newline>}character with a backslash, or by separating commands with a
+@QT{|}
+character.
+If no commands are specified, the command defaults to the
+@CO{print}
+command.
+@sp 1
+For the
+@CO{append},
+@CO{change}
+and
+@CO{insert}
+commands, the input text must be part of the global command line.
+In this case, the terminating period can be omitted if it ends the commands.
+@sp 1
+The
+@CO{visual}
+command may also be specified as one of the
+@CO{ex}
+commands.
+In this mode, input is taken from the terminal.
+Entering a
+@CO{Q}
+command in
+@CO{vi}
+mode causes the next line matching the pattern to be selected and
+@CO{vi}
+to be reentered, until the list is exhausted.
+@sp 1
+The
+@CO{global},
+@CO{v}
+and
+@CO{undo}
+commands cannot be used as part of these commands.
+@sp 1
+The editor options
+@OP{autoindent},
+@OP{autoprint}
+and
+@OP{report}
+are turned off for the duration of the
+@CO{global}
+and
+@CO{v}
+commands.
+@table @asis
+@item Line:
+The last line modified.
+@item Options:
+Affected by the
+@OP{ignorecase}
+and
+@OP{magic}
+options.
+Turns off the
+@OP{autoindent},
+@OP{autoprint}
+and
+@OP{report}
+options.
+@end table
+@end deftypefn
+@cindex help
+@deftypefn Command {} {he[lp]}
+
+Display a help message.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex insert
+@deftypefn Command {[line]} {i[nsert][!]}
+
+The input text is inserted before the specified line.
+Following the command name with a
+@QT{!}
+character causes the
+@OP{autoindent}
+option setting to be toggled for the duration of this command.
+@table @asis
+@item Line:
+Set to the last line input; if no lines were input,
+set to the line before the target line, or to the first line
+of the file if there are no lines preceding the target line.
+Affected by the
+@OP{autoindent}
+and
+@OP{number}
+options.
+@end table
+@end deftypefn
+@cindex join
+@deftypefn Command {[range]} {j[oin][!]} {[count] [flags]}
+
+Join lines of text together.
+@sp 1
+A
+@LI{count}specified to the
+@CO{join}
+command specifies that the last line of the
+@LI{range}plus
+@LI{count}subsequent lines will be joined.
+(Note, this differs by one from the general rule where only
+@LI{count}- 1
+subsequent lines are affected.)
+@sp 1
+If the current line ends with a whitespace character, all whitespace
+is stripped from the next line.
+Otherwise, if the next line starts with a open parenthesis
+@PQ{(},
+do nothing.
+Otherwise, if the current line ends with a question mark
+@PQ{?},
+period
+@PQ{.}
+or exclamation point
+@PQ{!},
+insert two spaces.
+Otherwise, insert a single space.
+@sp 1
+Appending a
+@QT{!}
+character to the command name causes a simpler join with no
+white-space processing.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex list
+@deftypefn Command {[range]} {l[ist]} {[count] [flags]}
+
+Display the lines unambiguously.
+Tabs are displayed as
+@QT{^I},
+and the end of the line is marked with a
+@QT{$}
+character.
+@table @asis
+@item Line:
+Set to the last line displayed.
+@item Options:
+Affected by the
+@OP{number}
+option.
+@end table
+@end deftypefn
+@cindex map
+@deftypefn Command {} {map[!]} {[lhs rhs]}
+
+Define or display maps (for
+@CO{vi}
+only).
+@sp 1
+If
+@QT{lhs}
+and
+@QT{rhs}
+are not specified, the current set of command mode maps are displayed.
+If a
+@QT{!}
+character is appended to to the command,
+the text input mode maps are displayed.
+@sp 1
+Otherwise, when the
+@QT{lhs}
+character sequence is entered in
+@CO{vi},
+the action is as if the corresponding
+@QT{rhs}
+had been entered.
+If a
+@QT{!}
+character is appended to the command name,
+the mapping is effective during text input mode,
+otherwise, it is effective during command mode.
+This allows
+@QT{lhs}
+to have two different macro definitions at the same time: one for command
+mode and one for input mode.
+@sp 1
+Whitespace characters require escaping with a
+@LI{<literal-next>}character to be entered in the
+@LI{lhs}string in visual mode.
+@sp 1
+Normally, keys in the
+@LI{rhs}string are remapped (see the
+@OP{remap}
+option),
+and it is possible to create infinite loops.
+However, keys which map to themselves are not further remapped,
+regardless of the setting of the
+@OP{remap}
+option.
+For example, the command
+@QT{:map n nz.}
+maps the
+@QT{n}
+key to the
+@CO{n}
+and
+@CO{z}
+commands.
+@sp 1
+To exit an infinitely looping map, use the terminal
+@LI{<interrupt>}character.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{remap}
+option.
+@end table
+@cindex mark
+@end deftypefn
+@cindex k
+@deftypefn Command {[line]} {ma[rk]} {<character>}
+
+@deftypefnx Command  {[line]} {k} {<character>}
+Mark the line with the mark
+@LI{<character>}.
+The expressions
+@QT{'<character>}
+and
+@QT{`<character>}
+can then be used as an address in any command that uses one.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex move
+@deftypefn Command {[range]} {m[ove]} {line}
+
+Move the specified lines after the target line.
+A target line of 0 places the lines at the beginning of the file.
+@table @asis
+@item Line:
+Set to the first of the moved lines.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex mkexrc
+@deftypefn Command {} {mk[exrc][!]} {file}
+
+Write the abbreviations, editor options and maps to the specified
+file.
+Information is written in a form which can later be read back in
+using the
+@CO{ex}
+@CO{source}
+command.
+If
+@LI{file}already exists, the
+@CO{mkexrc}
+command will fail.
+This check can be overridden by appending a
+@QT{!}
+character to the command.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex next
+@deftypefn Command {} {n[ext][!]} {[file ...]}
+
+Edit the next file from the argument list.
+The
+@CO{next}
+command will fail if the file has been modified since the last complete
+write.
+This check can be overridden by appending the
+@QT{!}
+character to the command name.
+The argument list can optionally be replaced by specifying a new one
+as arguments to this command.
+In this case, editing starts with the first file on the new list.
+@sp 1
+Capitalizing the first letter of the command, i.e.
+@CO{Next},
+while in
+@CO{vi}
+mode, will set the argument list and edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@table @asis
+@item Line:
+Set as described for the
+@CO{edit}
+command.
+@item Options:
+Affected by the options
+@OP{autowrite}
+and
+@OP{writeany}.
+@end table
+@end deftypefn
+@cindex open
+@deftypefn Command {[line]} {o[pen]} {/pattern/ [flags]}
+
+Enter open mode.
+Open mode is the same as being in
+@CO{vi},
+but with a one-line window.
+All the standard
+@CO{vi}
+commands are available.
+If a match is found for the optional RE argument,
+the cursor is set to the start of the matching pattern.
+@sp 1
+@emph{This command is not yet implemented.}
+@table @asis
+@item Line:
+Unchanged, unless the optional RE is specified, in which case it is
+set to the line where the matching pattern is found.
+@item Options:
+Affected by the
+@OP{open}
+option.
+@end table
+@end deftypefn
+@cindex preserve
+@deftypefn Command {} {pre[serve]}
+
+Save the file in a form that can later be recovered using the
+@CO{ex}
+@strong{-r}
+option.
+When the file is preserved, an email message is sent to the user.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex previous
+@deftypefn Command {} {prev[ious][!]}
+
+Edit the previous file from the argument list.
+The
+@CO{previous}
+command will fail if the file has been modified since the last complete
+write.
+This check can be overridden by appending the
+@QT{!}
+character to the command name.
+@sp 1
+Capitalizing the first letter of the command, i.e.
+@CO{Previous},
+while in
+@CO{vi}
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@table @asis
+@item Line:
+Set as described for the
+@CO{edit}
+command.
+@item Options:
+Affected by the options
+@OP{autowrite}
+and
+@OP{writeany}.
+None.
+@end table
+@end deftypefn
+@cindex print
+@deftypefn Command {[range]} {p[rint]} {[count] [flags]}
+
+Display the specified lines.
+@table @asis
+@item Line:
+Set to the last line displayed.
+@item Options:
+Affected by the
+@OP{list}
+and
+@OP{number}
+option.
+@end table
+@end deftypefn
+@cindex put
+@deftypefn Command {[line]} {pu[t]} {[buffer]}
+
+Append buffer contents to the current line.
+If a buffer is specified, its contents are appended to the line,
+otherwise, the contents of the unnamed buffer are used.
+@table @asis
+@item Line:
+Set to the line after the current line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex quit
+@deftypefn Command {} {q[uit][!]}
+
+End the editing session.
+If the file has been modified since the last complete write, the
+@CO{quit}
+command will fail.
+This check may be overridden by appending a
+@QT{!}
+character to the command.
+@sp 1
+If there are more files to edit, the
+@CO{quit}
+command will fail.
+Appending a
+@QT{!}
+character to the command name or entering two
+@CO{quit}
+commands (i.e.
+@CO{wq},
+@CO{quit},
+@CO{xit}
+or
+@CO{ZZ})
+in a row) will override this check and the editor will exit.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex read
+@deftypefn Command {[line]} {r[ead][!]} {[file]}
+
+Read a file.
+A copy of the specified file is appended to the line.
+If
+@LI{line}is 0, the copy is inserted at the beginning of the file.
+If no file is specified, the current file is read; if there is no
+current file, then
+@LI{file}becomes the current file.
+If there is no current file and no
+@LI{file}is specified, then the
+@CO{read}
+command will fail.
+@sp 1
+If
+@LI{file}is preceded by a
+@QT{!}
+character,
+@LI{file}is treated as if it were a shell command, and passed to the program
+named by the
+@OP{shell}
+edit option.
+The standard and standard error outputs of that command are read into
+the file after the specified line.
+The special meaning of the
+@QT{!}
+character can be overridden by escaping it with a backslash
+@PQ{\e}
+character.
+@table @asis
+@item Line:
+When executed from
+@CO{ex},
+the current line is set to the last line read.
+When executed from
+@CO{vi},
+the current line is set to the first line read.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex recover
+@deftypefn Command {} {rec[over]} {file}
+
+Recover
+@LI{file}if it was previously saved.
+If no saved file by that name exists, the
+@CO{recover}
+command behaves equivalently to the
+@CO{edit}
+command.
+@table @asis
+@item Line:
+Set as described for the
+@CO{edit}
+command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex resize
+@deftypefn Command {} {res[ize]} {[+|-]size}
+
+@CO{Vi}
+mode only.
+Grow or shrink the current screen.
+If
+@LI{size}is a positive, signed number, the current screen is grown by that many lines.
+If
+@LI{size}is a negative, signed number, the current screen is shrunk by that many lines.
+If
+@LI{size}is not signed, the current screen is set to the specified
+@LI{size}.
+Applicable only to split screens.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex rewind
+@deftypefn Command {} {rew[ind][!]}
+
+Rewind the argument list.
+If the current file has been modified since the last complete write,
+the
+@CO{rewind}
+command will fail.
+This check may be overridden by appending the
+@QT{!}
+character to the command.
+@sp 1
+Otherwise, the current file is set to the first file in the argument
+list.
+@table @asis
+@item Line:
+Set as described for the
+@CO{edit}
+command.
+@item Options:
+Affected by the
+@OP{autowrite}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex set
+@deftypefn Command {} {se[t]} {[option[=[value]] ...] [nooption ...] [option? ...] [all]}
+
+Display or set editor options.
+When no arguments are specified, the editor option
+@OP{term},
+and any editor options whose values have been changed from the
+default settings are displayed.
+If the argument
+@LI{all}is specified, the values of all of editor options are displayed.
+@sp 1
+Specifying an option name followed by the character
+@QT{?}
+causes the current value of that option to be displayed.
+The
+@QT{?}
+can be separated from the option name by whitespace characters.
+The
+@QT{?}
+is necessary only for Boolean valued options.
+Boolean options can be given values by the form
+@QT{set option}
+to turn them on, or
+@QT{set nooption}
+to turn them off.
+String and numeric options can be assigned by the form
+@QT{set option=value}.
+Any whitespace characters in strings can be included literally by preceding
+each with a backslash.
+More than one option can be set or listed by a single set command,
+by specifying multiple arguments, each separated from the next by
+whitespace characters.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex shell
+@deftypefn Command {} {sh[ell]}
+
+Run the shell program.
+The program named by the
+@OP{shell}
+option is run with a
+@strong{-i}
+(for interactive) flag.
+Editing is resumed when that program exits.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{shell}
+option.
+@end table
+@end deftypefn
+@cindex source
+@deftypefn Command {} {so[urce]} {file}
+
+Read and execute
+@CO{ex}
+commands from a file.
+@CO{Source}
+commands may be nested.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex substitute
+@deftypefn Command {[range]} {s[ubstitute]} {[/pattern/replace/] [options] [count] [flags]}
+
+@cindex &
+@deftypefnx Command  {[range]} {&} {[options] [count] [flags]}
+@cindex ~
+@deftypefnx Command  {[range]} {~} {[options] [count] [flags]}
+Make substitutions.
+Replace the first instance of
+@LI{pattern}with the string
+@LI{replace}on the specified line(s).
+If the
+@QT{/pattern/repl/}
+argument is not specified, the
+@QT{/pattern/repl/}
+from the previous
+@CO{substitute}
+command is used.
+Any character other than an alphabetic, numeric, <blank> or backslash
+character may be used as the delimiter.
+@sp 1
+If
+@LI{options}includes the letter
+@QT{c}
+(confirm), you will be prompted for confirmation before each replacement
+is done.
+An affirmative response (in English, a
+@QT{y}
+character) causes the replacement to be made.
+A quit response (in English, a
+@QT{q}
+character) causes the
+@CO{substitute}
+command to be terminated.
+Any other response causes the replacement not to be made, and the
+@CO{substitute}
+command continues.
+If
+@LI{options}includes the letter
+@QT{g}
+(global), all nonoverlapping instances of
+@LI{pattern}in the line are replaced.
+@sp 1
+The
+@CO{&}
+version of the command is the same as not specifying a pattern
+or replacement string to the
+@CO{substitute}
+command, and the
+@QT{&}
+is replaced by the pattern and replacement information from the
+previous substitute command.
+@sp 1
+The
+@CO{~}
+version of the command is the same as
+@CO{&}
+and
+@CO{s},
+except that the search pattern used is the last RE used in
+@emph{any}
+command, not necessarily the one used in the last
+@CO{substitute}
+command.
+@sp 1
+For example, in the sequence
+@example
+s/red/blue/
+/green
+~
+@end example
+the
+@QT{~}
+is equivalent to
+@QT{s/green/blue/}.
+@sp 1
+The
+@CO{substitute}
+command may be interrupted, using the terminal interrupt character.
+All substitutions completed before the interrupt are retained.
+@table @asis
+@item Line:
+Set to the last line upon which a substitution was made.
+@item Options:
+Affected by the
+@OP{ignorecase}
+and
+@OP{magic}
+option.
+@end table
+@end deftypefn
+@cindex suspend
+@deftypefn Command {} {su[spend][!]}
+
+@cindex stop
+@deftypefnx Command {}  {st[op][!]}
+@deftypefnx Comamnd {}  <control-Z>
+Suspend the edit session.
+Appending a
+@QT{!}
+character to these commands turns off the
+@OP{autowrite}
+option for the command.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{autowrite}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex tag
+@deftypefn Command {} {ta[g][!]} {tagstring}
+
+Edit the file containing the specified tag.
+If the tag is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+@CO{tag}
+command will fail.
+This check can be overridden by appending the
+@QT{!}
+character to the command name.
+@sp 1
+The
+@CO{tag}
+command searches for
+@LI{tagstring}in the tags file(s) specified by the
+@OP{tags}
+option.
+(See
+@XR{ctags,1}
+for more information on tags files.)
+@sp 1
+Capitalizing the first letter of the command, i.e.
+@CO{Tag},
+while in
+@CO{vi}
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@table @asis
+@item Line:
+Set to the line indicated by the tag.
+@item Options:
+Affected by the
+@OP{autowrite},
+@OP{taglength},
+@OP{tags}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex tagnext
+@deftypefn Command {} {tagn[ext][!]}
+
+Edit the file containing the next context for the current tag.
+If the context is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+@CO{tagnext}
+command will fail.
+This check can be overridden by appending the
+@QT{!}
+character to the command name.
+@sp 1
+Capitalizing the first letter of the command, i.e.
+@CO{Tagnext},
+while in 
+@CO{vi}
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@table @asis 
+@item Line:
+Set to the line indicated by the tag.
+@item Options:
+Affected by the 
+@OP{autowrite}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex tagpop
+@deftypefn Command {} {tagp[op][!]} {[file | number]}
+
+Pop to the specified tag in the tags stack.
+If neither
+@LI{file}or
+@LI{number}is specified, the
+@CO{tagpop}
+command pops to the most recent entry on the tags stack.
+If
+@LI{file}or
+@LI{number}is specified, the
+@CO{tagpop}
+command pops to the most recent entry in the tags stack for that file,
+or numbered entry in the tags stack, respectively.
+(See the
+@CO{display}
+command for information on displaying the tags stack.)
+@sp 1
+If the file has been modified since the last complete write, the
+@CO{tagpop}
+command will fail.
+This check may be overridden by appending a
+@QT{!}
+character to the command name.
+@table @asis
+@item Line:
+Set to the line indicated by the tag.
+@item Options:
+Affected by the
+@OP{autowrite}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex tagprev
+@deftypefn Command {} {tagp[rev][!]}
+
+Edit the file containing the previous context for the current tag.
+If the context is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+@CO{tagprev}
+command will fail.
+This check can be overridden by appending the
+@QT{!}
+character to the command name.
+@sp 1
+Capitalizing the first letter of the command, i.e.
+@CO{Tagprev},
+while in 
+@CO{vi}
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@table @asis 
+@item Line:
+Set to the line indicated by the tag.
+@item Options:
+Affected by the 
+@OP{autowrite}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex tagtop
+@deftypefn Command {} {tagt[op][!]}
+
+Pop to the least recent tag on the tags stack, clearing the tags stack.
+@sp 1
+If the file has been modified since the last complete write, the
+@CO{tagtop}
+command will fail.
+This check may be overridden by appending a
+@QT{!}
+character to the command name.
+@table @asis
+@item Line:
+Set to the line indicated by the tag.
+@item Options:
+Affected by the
+@OP{autowrite}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex unabbrev
+@deftypefn Command {} {una[bbrev]} {lhs}
+
+Delete an abbreviation.
+Delete
+@LI{lhs}from the current list of abbreviations.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex undo
+@deftypefn Command {} {u[ndo]}
+
+Undo the last change made to the file.
+Changes made by
+@CO{global},
+@CO{v},
+@CO{visual}
+and map sequences are considered a single command.
+If repeated, the
+@CO{u}
+command alternates between these two states, and is its own inverse.
+@table @asis
+@item Line:
+Set to the last line modified by the command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex unmap
+@deftypefn Command {} {unm[ap][!]} {lhs}
+
+Unmap a mapped string.
+Delete the command mode map definition for
+@LI{lhs}.
+If a
+@QT{!}
+character is appended to the command name, delete the text input mode
+map definition instead.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex version
+@deftypefn Command {} {ve[rsion]}
+
+Display the version of the
+@CO{ex/vi}
+editor.
+@end deftypefn
+@cindex visual
+@deftypefn Command {[line]} {vi[sual]} {[type] [count] [flags]}
+
+@CO{Ex}
+mode only.
+Enter
+@CO{vi}.
+The
+@LI{type}is optional, and can be
+@QT{-},
+@QT{+}
+or
+@QT{^},
+as in the
+@CO{ex}
+@CO{z}
+command, to specify the position of the specified line in the screen
+window.
+(The default is to place the line at the top of the screen window.)
+A
+@LI{count}specifies the number of lines that will initially be displayed.
+(The default is the value of the
+@OP{window}
+editor option.)
+@table @asis
+@item Line:
+Unchanged unless
+@LI{line}is specified, in which case it is set to that line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex visual
+@deftypefn Command {} {vi[sual][!]} {[+cmd] [file]}
+
+@CO{Vi}
+mode only.
+Edit a new file.
+Identical to the
+@QT{edit[!] [+cmd] [file]}
+command.
+@sp 1
+Capitalizing the first letter of the command, i.e.
+@CO{Visual},
+will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+@end deftypefn
+@cindex viusage
+@deftypefn Command {} {viu[sage]} {[command]}
+
+Display usage for a
+@CO{vi}
+command.
+If
+@LI{command}is specified, a usage statement for that command is displayed.
+Otherwise, usage statements for all
+@CO{vi}
+commands are displayed.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex write
+@deftypefn Command {[range]} {w[rite][!]} {[>>] [file]}
+
+@deftypefnx Command  {[range]} {w[rite]} {[!] [file]}
+@cindex wn
+@deftypefnx Command  {[range]} {wn[!]} {[>>] [file]}
+@cindex wq
+@deftypefnx Command  {[range]} {wq[!]} {[>>] [file]}
+Write the file.
+The specified lines (the entire file, if no range is given) is written
+to
+@LI{file}.
+If
+@LI{file}is not specified, the current pathname is used.
+If
+@LI{file}is specified, and it exists, or if the current pathname was set using the
+@CO{file}
+command, and the file already exists, these commands will fail.
+Appending a
+@QT{!}
+character to the command name will override this check and the write
+will be attempted, regardless.
+@sp 1
+Specifying the optional
+@QT{>>}
+string will cause the write to be appended to the file, in which case
+no tests are made for the file already existing.
+@sp 1
+If the file is preceded by a
+@QT{!}
+character, the program named by the shell edit option is
+invoked with file as its second argument, and the specified
+lines are passed as standard input to that command.
+The
+@QT{!}
+in this usage must be separated from command name by at least one
+whitespace character.
+The special meaning of the
+@QT{!}
+may be overridden by escaping it with a backslash
+@PQ{\e}
+character.
+@sp 1
+The
+@CO{wq}
+version of the write command will exit the editor after writing the file,
+if there are no further files to edit.
+Appending a
+@QT{!}
+character to the command name or entering two
+@QQ{quit}
+commands (i.e.
+@CO{wq},
+@CO{quit},
+@CO{xit}
+or
+@CO{ZZ})
+in a row) will override this check and the editor will exit,
+ignoring any files that have not yet been edited.
+@sp 1
+The
+@CO{wn}
+version of the write command will move to the next file after writing
+the file, unless the write fails.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{readonly}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex xit
+@deftypefn Command {[range]} {x[it][!]} {[file]}
+
+Write the file if it has been modified.
+The specified lines are written to
+@LI{file},
+if the file has been modified since the last complete write to any
+file.
+If no
+@LI{range}is specified, the entire file is written.
+@sp 1
+The
+@CO{xit}
+command will exit the editor after writing the file,
+if there are no further files to edit.
+Appending a
+@QT{!}
+character to the command name or entering two
+@QQ{quit}
+commands (i.e.
+@CO{wq},
+@CO{quit},
+@CO{xit}
+or
+@CO{ZZ})
+in a row) will override this check and the editor will exit,
+ignoring any files that have not yet been edited.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+Affected by the
+@OP{readonly}
+and
+@OP{writeany}
+options.
+@end table
+@end deftypefn
+@cindex yank
+@deftypefn Command {[range]} {ya[nk]} {[buffer] [count]}
+
+Copy the specified lines to a buffer.
+If no buffer is specified, the unnamed buffer is used.
+@table @asis
+@item Line:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex z
+@deftypefn Command {[line]} {z} {[type] [count] [flags]}
+
+Adjust the window.
+If no
+@LI{type}is specified, then
+@LI{count}lines following the specified line are displayed.
+The default
+@LI{count}is the value of the
+@OP{window}
+option.
+The
+@LI{type}argument changes the position at which
+@LI{line}is displayed on the screen by changing the number of lines
+displayed before and after
+@LI{line}.
+The following
+@LI{type}characters may be used:
+@table @asis
+@item -
+Place the line at the bottom of the screen.
+@item +
+Place the line at the top of the screen.
+@item .
+Place the line in the middle of the screen.
+@item ^
+Write out count lines starting
+@LI{count * 2}lines before
+@LI{line};
+the net effect of this is that a
+@QT{z^}
+command following a
+@CO{z}
+command writes the previous page.
+@item =
+Center
+@LI{line}on the screen with a line of hyphens displayed immediately before and
+after it.
+The number of preceding and following lines of text displayed are
+reduced to account for those lines.
+@end table
+@table @asis
+@item Line:
+Set to the last line displayed, with the exception of the
+@QT{=}
+@LI{type},
+where the current line is set to the line specified by the command.
+@item Options:
+Affected by the
+@OP{scroll}
+option.
+@end table
+@end deftypefn
diff --git a/dist/nvi/docs/vi.ref/ref.texi b/dist/nvi/docs/vi.ref/ref.texi
new file mode 100644 (file)
index 0000000..97f8330
--- /dev/null
@@ -0,0 +1,65 @@
+@comment  Copyright (c) 1994
+@c $NetBSD: ref.texi,v 1.1.1.2 2008/05/18 14:31:00 aymeric Exp $
+@comment      The Regents of the University of California.  All rights reserved.
+@comment  Copyright (c) 1994, 1995, 1996
+@comment       Keith Bostic.  All rights reserved.
+@comment 
+@comment  See the LICENSE file for redistribution information.
+@comment 
+@comment      Id: ref.texi,v 8.1 2001/08/18 20:43:48 skimo Exp (Berkeley) Date: 2001/08/18 20:43:48
+@comment 
+@comment 
+@comment  indented paragraph, with spaces between the items, bold font
+@macro IP{item}
+@item @strong{\item\}
+@comment @deffn {Command} {\item\}
+@comment @end deffn
+@end macro
+@comment  indented paragraph, no spaces between the items, bold font
+@comment .de Ip
+@comment .tm arg 1 \\$1 arg 2 \\$2 arg 3 \\$3
+@macro Ip{item}
+@itemx @strong{\item\}
+@end macro
+@comment  typewriter font
+@macro LI{command}
+@code{\command\}
+@end macro
+@comment  ex/vi names in command font
+@macro EV{ex,vi}
+@strong{\ex\}/@strong{\vi\}
+@end macro
+@comment  command names
+@macro CO{command}
+@strong{\command\}
+@end macro
+@comment  option names
+@macro OP{option}
+@code{\option\}
+@end macro
+@comment  paren quoted (typewriter font)
+@macro PQ{command}
+``@code{\command\}''
+@end macro
+@comment  quoted bold
+@macro QB{command}
+``@strong{\command\}''
+@end macro
+@comment  quoted command
+@macro QC{command}
+``@strong{\command\}''
+@end macro
+@comment  quoted option
+@comment  quoted (no font change)
+@macro QQ{command}
+``\command\''
+@end macro
+@comment  quoted (typewriter font)
+@macro QT{command}
+``@code{\command\}''
+@end macro
+@comment  section macro to build TOC
+@comment  manual section
+@macro XR{command,section}
+@command{\command\}(\section\)
+@end macro
diff --git a/dist/nvi/docs/vi.ref/set.opt.texi b/dist/nvi/docs/vi.ref/set.opt.texi
new file mode 100644 (file)
index 0000000..b2332a9
--- /dev/null
@@ -0,0 +1,1371 @@
+@comment  Copyright (c) 1994
+@c $NetBSD: set.opt.texi,v 1.4 2008/12/12 22:55:56 lukem Exp $
+@comment      The Regents of the University of California.  All rights reserved.
+@comment  Copyright (c) 1994, 1995, 1996
+@comment       Keith Bostic.  All rights reserved.
+@comment 
+@comment  See the LICENSE file for redistribution information.
+@comment 
+@comment      Id: set.opt.texi,v 8.1 2001/08/18 20:43:48 skimo Exp (Berkeley) Date: 2001/08/18 20:43:48
+@comment 
+@chapter Set Options
+
+There are a large number of options that may be set (or unset) to
+change the editor's behavior.
+This section describes the options, their abbreviations and their
+default values.
+
+In each entry below, the first part of the tag line is the full name
+of the option, followed by any equivalent abbreviations.
+(Regardless of the abbreviations, it is only necessary to use the
+minimum number of characters necessary to distinguish an abbreviation
+from all other commands for it to be accepted, in
+@EV{nex,nvi}.
+Historically, only the full name and the official abbreviations
+were accepted by
+@EV{ex,vi}.
+Using full names in your startup files and environmental variables will
+probably make them more portable.)
+The part in square brackets is the default value of the option.
+Most of the options are boolean, i.e. they are either on or off,
+and do not have an associated value.
+
+Options apply to both
+@CO{ex}
+and
+@CO{vi}
+modes, unless otherwise specified.
+
+With a few exceptions,
+all options are settable per screen, i.e. the
+@OP{tags}
+option can be set differently in each screen.
+The exceptions are the
+@OP{columns},
+@OP{lines},
+@OP{secure}
+and
+@OP{term}
+options.
+Changing these options modifies the respective information for all screens.
+
+For information on modifying the options or to display the options and
+their current values, see the
+@QQ{set}
+command in the section entitled
+@QB{Ex Commands} .
+@itemize @bullet
+@cindex altwerase
+@IP{altwerase [off]}
+
+@CO{Vi}
+only.
+Change how
+@CO{vi}
+does word erase during text input.
+When this option is set, text is broken up into three classes:
+alphabetic, numeric and underscore characters, other nonblank
+characters, and blank characters.
+Changing from one class to another marks the end of a word.
+In addition, the class of the first character erased is ignored
+(which is exactly what you want when erasing pathname components).
+@cindex autoindent
+@IP{autoindent, ai [off]}
+
+If this option is set, whenever you create a new line (using the
+@CO{vi}
+@CO{A},
+@CO{a},
+@CO{C},
+@CO{c},
+@CO{I},
+@CO{i},
+@CO{O},
+@CO{o},
+@CO{R},
+@CO{r},
+@CO{S},
+and
+@CO{s}
+commands, or the
+@CO{ex}
+@CO{append},
+@CO{change},
+and
+@CO{insert}
+commands) the new line is automatically indented to align the cursor with
+the first nonblank character of the line from which you created it.
+Lines are indented using tab characters to the extent possible (based on
+the value of the
+@OP{tabstop}
+option,
+and if
+@OP{expandtab}
+is not set) and then using space characters as necessary.
+For commands inserting text into the middle of a line, any blank characters
+to the right of the cursor are discarded, and the first nonblank character
+to the right of the cursor is aligned as described above.
+@sp 1
+The indent characters are themselves somewhat special.
+If you do not enter more characters on the new line before moving to
+another line, or entering
+@LI{<escape>},
+the indent character will be deleted and the line will be empty.
+For example, if you enter
+@LI{<carriage-return>}twice in succession,
+the line created by the first
+@LI{<carriage-return>}will not have any characters in it,
+regardless of the indentation of the previous or subsequent line.
+@sp 1
+Indent characters also require that you enter additional erase characters
+to delete them.
+For example,
+if you have an indented line, containing only blanks, the first
+@LI{<word-erase>}character you enter will erase up to end of the indent characters,
+and the second will erase back to the beginning of the line.
+(Historically, only the
+@LI{<control-D>}key would erase the indent characters.
+Both the
+@LI{<control-D>}key and the usual erase keys work in
+@CO{nvi}.)
+In addition, if the cursor is positioned at the end of the indent
+characters, the keys
+@QT{0<control-D>}
+will erase all of the indent characters for the current line,
+resetting the indentation level to 0.
+Similarly, the keys
+@QT{^<control-D>}
+will erase all of the indent characters for the current line,
+leaving the indentation level for future created lines unaffected.
+@sp 1
+Finally, if the
+@OP{autoindent}
+option is set, the
+@CO{S}
+and
+@CO{cc}
+commands change from the first nonblank of the line to the end of the
+line, instead of from the beginning of the line to the end of the line.
+@cindex autoprint
+@IP{autoprint, ap [off]}
+
+@CO{Ex}
+only.
+Cause the current line to be automatically displayed after the
+@CO{ex}
+commands
+@CO{<},
+@CO{>},
+@CO{copy},
+@CO{delete},
+@CO{join},
+@CO{move},
+@CO{put},
+@CO{t},
+@CO{Undo},
+and
+@CO{undo}.
+This automatic display is suppressed during
+@CO{global}
+and
+@CO{v}
+commands, and for any command where optional flags are used to explicitly
+display the line.
+@cindex autowrite
+@IP{autowrite, aw [off]}
+
+If this option is set, the
+@CO{vi}
+@CO{!},
+@CO{^^},
+@CO{^]}
+and
+@CO{<control-Z>}
+commands, and the
+@CO{ex}
+@CO{edit},
+@CO{next},
+@CO{rewind},
+@CO{stop},
+@CO{suspend},
+@CO{tag},
+@CO{tagpop},
+and
+@CO{tagtop}
+commands automatically write the current file back to the current file name
+if it has been modified since it was last written.
+If the write fails, the command fails and goes no further.
+@sp 1
+Appending the optional force flag character
+@QT{!}
+to the
+@CO{ex}
+commands
+@CO{next},
+@CO{rewind},
+@CO{stop},
+@CO{suspend},
+@CO{tag},
+@CO{tagpop},
+and
+@CO{tagtop}
+stops the automatic write from being attempted.
+@sp 1
+(Historically, the
+@CO{next}
+command ignored the optional force flag.)
+Note, the
+@CO{ex}
+commands
+@CO{edit},
+@CO{quit},
+@CO{shell},
+and
+@CO{xit}
+are
+@emph{not}
+affected by the
+@OP{autowrite}
+option.
+@sp 1
+The
+@OP{autowrite}
+option is ignored if the file is considered read-only for any reason.
+@comment  I cannot get a double quote to print between the square brackets
+@comment  to save my life.  The ONLY way I've been able to get this to work
+@comment  is with the .tr command.
+@cindex backup
+@IP{backup [""]}
+
+If this option is set, it specifies a pathname used as a backup file,
+and, whenever a file is written, the file's current contents are copied
+to it.
+The pathname is
+@QT{#},
+@QT{%}
+and
+@QT{!}
+expanded.
+@sp 1
+If the first character of the pathname is
+@QT{N},
+a version number is appended to the pathname (and the
+@QT{N}
+character is then discarded).
+Version numbers are always incremented, and each backup file will have
+a version number one greater than the highest version number currently
+found in the directory.
+@sp 1
+Backup files must be regular files, owned by the real user ID of the
+user running the editor, and not accessible by any other user.
+@cindex beautify
+@IP{beautify, bf [off]}
+
+If this option is set, all control characters that are not currently being
+specially interpreted, other than
+@LI{<tab>},
+@LI{<newline>},
+and
+@LI{<form-feed>},
+are
+discarded from commands read in by
+@CO{ex}
+from command files, and from input text entered to
+@CO{vi}
+(either into the file or to the colon command line).
+Text files read by
+@EV{ex,vi}
+are
+@emph{not}
+affected by the
+@OP{beautify}
+option.
+@cindex cdpath
+@IP{cdpath [environment variable CDPATH, or current directory]}
+
+This option is used to specify a colon separated list of directories
+which are used as path prefixes for any relative path names used as
+arguments for the
+@CO{cd}
+command.
+The value of this option defaults to the value of the environmental
+variable
+@LI{CDPATH}if it is set, otherwise to the current directory.
+For compatibility with the POSIX 1003.2 shell, the
+@CO{cd}
+command does
+@emph{not}
+check the current directory as a path prefix for relative path names
+unless it is explicitly specified.
+It may be so specified by entering an empty string or a
+@QT{.}
+character into the
+@LI{CDPATH}variable or the option value.
+@cindex cedit
+@IP{cedit [no default]}
+
+This option adds the ability to edit the colon command-line history.
+This option is set to a string.
+Whenever the first character of that string is entered on the colon
+command line,
+you will enter a normal editing window on the collected commands that
+you've entered on the
+@CO{vi}
+colon command-line.
+You may then modify and/or execute the commands.
+All normal text editing is available,
+except that you cannot use
+@CO{<control-W>}
+to switch to an alternate screen.
+Entering a
+@CO{<carriage-return>}
+will execute the current line of the screen window as an ex command in
+the context of the screen from which you created the colon command-line
+screen,
+and you will then return to that screen.
+@sp 1
+Because of
+@CO{vi}'s
+parsing rules, it can be difficult to set the colon command-line edit
+character to the
+@LI{<escape>}character.
+To set it to
+@LI{<escape>},
+use
+@QT{set cedit=<literal-next><escape>}.
+@sp 1
+If the
+@OP{cedit}
+edit option is set to the same character as the
+@OP{filec}
+edit option,
+@CO{vi}
+will perform colon command-line editing if the character is entered as
+the first character of the line,
+otherwise,
+@CO{vi}
+will perform file name expansion.
+@cindex columns
+@IP{columns, co [80]}
+
+The number of columns in the screen.
+Setting this option causes
+@EV{ex,vi}
+to set (or reset) the environmental variable
+@LI{COLUMNS}.
+See the section entitled
+@QB{Sizing the Screen}
+more information.
+@cindex comment
+@IP{comment [off]}
+
+@CO{Vi}
+only.
+If the first non-empty line of the file begins with the string
+@QT{#},
+@QT{/*}
+or
+@QT{//},
+this option causes
+@CO{vi}
+to skip to the end of that shell, C or C++ comment (probably a
+terribly boring legal notice) before displaying the file.
+@cindex directory
+@IP{directory, dir [environment variable TMPDIR, or /tmp]}
+
+The directory where temporary files are created.
+The environmental variable
+@LI{TMPDIR}is used as the default value if it exists, otherwise
+@LI{/tmp}is used.
+@cindex edcompatible
+@IP{edcompatible, ed [off]}
+
+Remember the values of the
+@QQ{c}
+and
+@QQ{g}
+suffixes to the
+@CO{substitute}
+commands, instead of initializing them as unset for each new
+command.
+Specifying pattern and replacement strings to the
+@CO{substitute}
+command unsets the
+@QQ{c}
+and
+@QQ{g}
+suffixes as well.
+@cindex escapetime
+@IP{escapetime [1]}
+
+The 10th's of a second
+@EV{ex,vi}
+waits for a subsequent key to complete an
+@LI{<escape>}key mapping.
+@cindex errorbells
+@IP{errorbells, eb [off]}
+
+@CO{Ex}
+only.
+@CO{Ex}
+error messages are normally presented in inverse video.
+If that is not possible for the terminal, setting this option causes
+error messages to be announced by ringing the terminal bell.
+@cindex expandtab
+@IP{expandtab, et [off]}
+
+Prevent the use of
+@LI{<tab>}
+characters in leading whitespace when shifting text, autoindenting,
+indenting with
+@CO{<control-T>},
+or outdenting with
+@CO{<control-D>}.
+@cindex exrc
+@IP{exrc, ex [off]}
+
+If this option is turned on in the EXINIT environment variables,
+or the system or $HOME startup files,
+the local startup files are read,
+unless they are the same as the system or $HOME startup files or
+fail to pass the standard permission checks.
+See the section entitled
+@QB{Startup Information}
+for more information.
+@cindex extended
+@IP{extended [off]}
+
+This option causes all regular expressions to be treated as POSIX
+1003.2 Extended Regular Expressions (which are similar to historic
+@XR{egrep,1}
+style expressions).
+@cindex filec
+@IP{filec [no default]}
+
+This option adds the ability to do shell expansion when entering input
+on the colon command line.
+This option is set to a string.
+Whenever the first character of that string is entered on the colon
+command line,
+the <blank> delimited string immediately before the cursor is expanded
+as if it were followed by a
+@LI{*}character, and file name expansion for the
+@CO{ex}
+edit command was done.
+If no match is found, the screen is flashed and text input resumed.
+If a single match results, that match replaces the expanded text.
+In addition, if the single match is for a directory, a
+@LI{/}character is appended and file completion is repeated.
+If more than a single match results,
+any unique prefix shared by the matches replaces the expanded text,
+the matches are displayed,
+and text input resumed.
+@sp 1
+Because of
+@CO{vi}'s
+parsing rules, it can be difficult to set the path completion character
+to two command values,
+@LI{<escape>}and
+@LI{<tab>}.
+To set it to
+@LI{<escape>},
+use
+@QT{set filec=<literal-next><escape>}.
+To set it to
+@LI{<tab>},
+use
+@QT{set filec=\e<tab>}.
+@sp 1
+If the
+@OP{cedit}
+edit option is set to the same character as the
+@OP{filec}
+edit option,
+@CO{vi}
+will perform colon command-line editing if the character is entered as
+the first character of the line,
+otherwise,
+@CO{vi}
+will perform file name expansion.
+@cindex flash
+@IP{flash [on]}
+
+This option causes the screen to flash instead of beeping the keyboard,
+on error, if the terminal has the capability.
+@cindex hardtabs
+@IP{hardtabs, ht [8]}
+
+This option defines the spacing between hardware tab settings, i.e.
+the tab expansion done by the operating system and/or the terminal
+itself.
+As
+@EV{nex,nvi}
+never writes
+@LI{<tab>}characters to the terminal, unlike historic versions of
+@EV{ex,vi},
+this option does not currently have any affect.
+@cindex iclower
+@IP{iclower [off]}
+
+The
+@OP{iclower}
+edit option makes all Regular Expressions case-insensitive,
+as long as an upper-case letter does not appear in the search string.
+@cindex ignorecase
+@IP{ignorecase, ic [off]}
+
+This option causes regular expressions, both in
+@CO{ex}
+commands and in searches,
+to be evaluated in a case-insensitive manner.
+@cindex keytime
+@IP{keytime [6]}
+
+The 10th's of a second
+@EV{ex,vi}
+waits for a subsequent key to complete a key mapping.
+@cindex leftright
+@IP{leftright [off]}
+
+@CO{Vi}
+only.
+This option causes the screen to be scrolled left-right to view
+lines longer than the screen, instead of the traditional
+@CO{vi}
+screen interface which folds long lines at the right-hand margin
+of the terminal.
+@cindex lines
+@IP{lines, li [24]}
+
+@CO{Vi}
+only.
+The number of lines in the screen.
+Setting this option causes
+@EV{ex,vi}
+to set (or reset) the environmental variable
+@LI{LINES}.
+See the section entitled
+@QB{Sizing the Screen}
+for more information.
+@cindex lisp
+@IP{lisp [off]}
+
+@CO{Vi}
+only.
+This option changes the behavior of the
+@CO{vi}
+@CO{(},
+@CO{)},
+@strong{@{},
+@strong{@}},
+@CO{[[}
+and
+@CO{]]}
+commands to match the Lisp language.
+Also, the
+@OP{autoindent}
+option's behavior is changed to be appropriate for Lisp.
+@sp 1
+@emph{This option is not yet implemented.}
+@cindex list
+@IP{list [off]}
+
+This option causes lines to be displayed in an unambiguous fashion.
+Specifically, tabs are displayed as control characters, i.e.
+@QT{^I},
+and the ends of lines are marked with a
+@QT{$}
+character.
+@cindex lock
+@IP{lock [on]}
+
+This option causes the editor to attempt to get an exclusive lock on
+any file being edited, read or written.
+Reading or writing a file that cannot be locked produces a warning
+message, but no other effect.
+Editing a file that cannot be locked results in a read only edit session,
+as if the
+@OP{readonly}
+edit option were set.
+@cindex magic
+@IP{magic [on]}
+
+This option is on by default.
+Turning the
+@OP{magic}
+option off causes all regular expression characters except for
+@QT{^}
+and
+@QT{$},
+to be treated as ordinary characters.
+To re-enable characters individually, when the
+@OP{magic}
+option is off,
+precede them with a backslash
+@QT{\e}
+character.
+See the section entitled
+@QB{Regular Expressions and Replacement Strings}
+for more information.
+@cindex matchchars
+@IP{matchchars [[]@{@}()<>]}
+
+@CO{Vi}
+only.
+This option defines the character pairs used by the
+@CO{%}
+command.
+
+@cindex matchtime
+@IP{matchtime [7]}
+
+@CO{Vi}
+only.
+The 10th's of a second
+@CO{vi}
+pauses on the matching character when the
+@OP{showmatch}
+option is set.
+@cindex mesg
+@IP{mesg [on]}
+
+This option allows other users to contact you using the
+@XR{talk,1}
+and
+@XR{write,1}
+utilities, while you are editing.
+@EV{Ex,vi}
+does not turn message on, i.e. if messages were turned off when the
+editor was invoked, they will stay turned off.
+This option only permits you to disallow messages for the edit session.
+See the
+@XR{mesg,1}
+utility for more information.
+@cindex msgcat
+@IP{msgcat [./]}
+
+This option selects a message catalog to be used to display error and
+informational messages in a specified language.
+If the value of this option ends with a '/', it is treated as the name
+of a directory that contains a message catalog
+@QT{vi_XXXX},
+where
+@QT{XXXX}
+is the value of the
+@LI{LANG}environmental variable, if it's set, or the value of the
+@LI{LC_MESSAGES}environmental variable if it's not.
+If neither of those environmental variables are set,
+or if the option doesn't end in a '/',
+the option is treated as the full path name of the message catalog to use.
+@sp 1
+If any messages are missing from the catalog,
+the backup text (English) is used instead.
+@sp 1
+See the distribution file
+@LI{catalog/README}for additional information on building and installing message catalogs.
+@cindex modelines
+@IP{modelines, modeline [off]}
+
+If the
+@OP{modelines}
+option is set,
+@EV{ex,vi}
+has historically scanned the first and last five lines of each file as
+it is read for editing, looking for any
+@CO{ex}
+commands that have been placed in those lines.
+After the startup information has been processed, and before the user
+starts editing the file, any commands embedded in the file are executed.
+@sp 1
+Commands were recognized by the letters
+@QQ{e}
+or
+@QQ{v}
+followed by
+@QQ{x}
+or
+@QQ{i},
+at the beginning of a line or following a tab or space character,
+and followed by a
+@QQ{:},
+an
+@CO{ex}
+command, and another
+@QQ{:}.
+@sp 1
+This option is a security problem of immense proportions,
+and should not be used under any circumstances.
+@sp 1
+@emph{This option will never be implemented.}
+@comment  I cannot get a double quote to print between the square brackets
+@comment  to save my life.  The ONLY way I've been able to get this to work
+@comment  is with the .tr command.
+@cindex noprint
+@IP{noprint [""]}
+
+Characters that are never handled as printable characters.
+By default, the C library function
+@XR{isprint,3}
+is used to determine if a character is printable or not.
+This edit option overrides that decision.
+@cindex number
+@IP{number, nu [off]}
+
+Precede each line displayed with its current line number.
+@cindex octal
+@IP{octal [off]}
+
+Display unknown characters as octal numbers
+@PQ{"\e###"},
+instead of the default
+hexadecimal
+@PQ{"\ex##"}.
+@cindex open
+@IP{open [on]}
+
+@CO{Ex}
+only.
+If this option is not set, the
+@CO{open}
+and
+@CO{visual}
+commands are disallowed.
+@cindex optimize
+@IP{optimize, opt [on]}
+
+@CO{Vi}
+only.
+Throughput of text is expedited by setting the terminal not to do automatic
+carriage returns when printing more than one (logical) line of output,
+greatly speeding output on terminals without addressable cursors when text
+with leading white space is printed.
+@sp 1
+@emph{This option is not yet implemented.}
+@cindex paragraphs
+@IP{paragraphs, para [IPLPPPQPP LIpplpipbp]}
+
+@CO{Vi}
+only.
+Define additional paragraph boundaries for the
+@CO{@{}
+and
+@strong{@}}
+commands.
+The value of this option must be a character string consisting
+of zero or more character pairs.
+@sp 1
+In the text to be edited, the character string
+@LI{<newline>.<char-pair>},
+(where
+@LI{<char-pair>}is one of the character pairs in the option's value)
+defines a paragraph boundary.
+For example, if the option were set to
+@LI{LaA<space>##},
+then all of the following additional paragraph boundaries would be
+recognized:
+@sp 1
+@example
+<newline>.La
+<newline>.A<space>
+<newline>.##
+@end example
+@cindex path
+@IP{path []}
+
+The path option can be used to specify a <colon>-separated list of
+paths, similar to the
+@LI{PATH}environment variable in the shells.
+If this option is set,
+the name of the file to be edited is not an absolute pathname,
+the first component of the filename is not
+@QT{.}
+or
+@QT{..},
+and the file to be edited doesn't exist in the current directory,
+the elements of the
+@OP{path}
+option are sequentially searched for a file of the specified name.
+If such a file is found, it is edited.
+@comment  I cannot get a double quote to print between the square brackets
+@comment  to save my life.  The ONLY way I've been able to get this to work
+@comment  is with the .tr command.
+@cindex print
+@IP{print [""]}
+
+Characters that are always handled as printable characters.
+By default, the C library function
+@XR{isprint,3}
+is used to determine if a character is printable or not.
+This edit option overrides that decision.
+@cindex prompt
+@IP{prompt [on]}
+
+@CO{Ex}
+only.
+This option causes
+@CO{ex}
+to prompt for command input with a
+@QT{:}
+character; when it is not set, no prompt is displayed.
+@cindex readonly
+@IP{readonly, ro [off]}
+
+This option causes a force flag to be required to attempt to write the file.
+Setting this option is equivalent to using the
+@strong{-R}
+command line option,
+or executing the
+@CO{vi}
+program using the name
+@CO{view}.
+@sp 1
+The
+@OP{readonly}
+edit option is not usually persistent, like other edit options.
+If the
+@strong{-R}
+command line option is set,
+@CO{vi}
+is executed as
+@CO{view},
+or the
+@OP{readonly}
+edit option is explicitly set,
+all files edited in the screen will be marked readonly,
+and the force flag will be required to write them.
+However, if none of these conditions are true,
+or the
+@OP{readonly}
+edit option is explicitly unset,
+then the
+@OP{readonly}
+edit option will toggle based on the write permissions of the file currently
+being edited as of when it is loaded into the edit buffer.
+In other words, the
+@OP{readonly}
+edit option will be set if the current file lacks write permissions,
+and will not be set if the user has write permissions for the file.
+@cindex recdir
+@IP{recdir [/var/tmp/vi.recover]}
+
+The directory where recovery files are stored.
+@sp 1
+If you change the value of
+@OP{recdir},
+be careful to choose a directory whose contents are not regularly
+deleted.
+Bad choices include directories in memory based filesystems,
+or
+@LI{/tmp},
+on most systems,
+as their contents are removed when the machine is rebooted.
+@sp 1
+Public directories like
+@LI{/usr/tmp}and
+@LI{/var/tmp}are usually safe, although some sites periodically prune old files
+from them.
+There is no requirement that you use a public directory,
+e.g. a sub-directory of your home directory will work fine.
+@sp 1
+Finally, if you change the value of
+@OP{recdir},
+you must modify the recovery script to operate in your chosen recovery
+area.
+@sp 1
+See the section entitled
+@QB{Recovery}
+for further information.
+@cindex redraw
+@IP{redraw, re [off]}
+
+@CO{Vi}
+only.
+The editor simulates (using great amounts of output), an intelligent
+terminal on a dumb terminal (e.g. during insertions in
+@CO{vi}
+the characters to the right of the cursor are refreshed as each input
+character is typed).
+@sp 1
+@emph{This option is not yet implemented.}
+@cindex remap
+@IP{remap [on]}
+
+If this option is set,
+it is possible to define macros in terms of other macros.
+Otherwise, each key is only remapped up to one time.
+For example, if
+@QT{A}
+is mapped to
+@QT{B},
+and
+@QT{B}
+is mapped to
+@QT{C},
+The keystroke
+@QT{A}
+will be mapped to
+@QT{C}
+if the
+@OP{remap}
+option is set, and to
+@QT{B}
+if it is not set.
+@cindex report
+@IP{report [5]}
+
+Set the threshold of the number of lines that need to be changed or
+yanked before a message will be displayed to the user.
+For everything but the yank command, the value is the largest value
+about which the editor is silent, i.e. by default, 6 lines must be
+deleted before the user is notified.
+However, if the number of lines yanked is greater than
+@emph{or equal to}
+the set value, it is reported to the user.
+@cindex ruler
+@IP{ruler [off]}
+
+@CO{Vi}
+only.
+Display a row/column ruler on the colon command line.
+@cindex scroll
+@IP{scroll, scr [(environment variable LINES - 1) / 2]}
+
+Set the number of lines scrolled by the
+@CO{ex}
+@CO{<control-D>}
+and
+@CO{<end-of-file>}
+commands.
+@sp 1
+Historically, the
+@CO{ex}
+@CO{z}
+command, when specified without a count, used two times the size of the
+scroll value; the POSIX 1003.2 standard specified the window size, which
+is a better choice.
+@cindex searchincr
+@IP{searchincr [off]}
+
+The
+@OP{searchincr}
+edit option makes the search commands
+@CO{/}
+and
+@CO{?}
+incremental, i.e. the screen is updated and the cursor moves to the matching
+text as the search pattern is entered.
+If the search pattern is not found,
+the screen is beeped and the cursor remains on the colon-command line.
+Erasing characters from the search pattern backs the cursor up to the
+previous matching text.
+@cindex sections
+@IP{sections, sect [NHSHH HUnhsh]}
+
+@CO{Vi}
+only.
+Define additional section boundaries for the
+@CO{[[}
+and
+@CO{]]}
+commands.
+The
+@OP{sections}
+option should be set to a character string consisting of zero or
+more character pairs.
+In the text to be edited, the character string
+@LI{<newline>.<char-pair>},
+(where
+@LI{<char-pair>}is one of the character pairs in the option's value),
+defines a section boundary in the same manner that
+@OP{paragraphs}
+option boundaries are defined.
+@cindex secure
+@IP{secure [off]}
+
+The
+@OP{secure}
+edit option turns off all access to external programs.
+This means that the versions of the
+@CO{read}
+and
+@CO{write}
+commands that filter text through other programs,
+the
+@CO{vi}
+@CO{!}
+and
+@CO{<control-Z>}
+commands,
+the
+@CO{ex}
+@CO{!},
+@CO{script},
+@CO{shell},
+@CO{stop}
+and
+@CO{suspend}
+commands and file name expansion will not be permitted.
+Once set,
+the
+@OP{secure}
+edit option may not be unset.
+@cindex shell
+@IP{shell, sh [environment variable SHELL, or /bin/sh]}
+
+Select the shell used by the editor.
+The specified path is the pathname of the shell invoked by the
+@CO{vi}
+@CO{!}
+shell escape command and by the
+@CO{ex}
+@CO{shell}
+command.
+This program is also used to resolve any shell meta-characters in
+@CO{ex}
+commands.
+@comment  I cannot get a double quote to print between the square brackets
+@comment  to save my life.  The ONLY way I've been able to get this to work
+@comment  is with the .tr command.
+@cindex shellmeta
+@comment @IP{shellmeta [~@{[*?@$`'"\e]}
+@item @strong{shellmeta [~@{[*?$`'"\]}
+
+The set of characters that
+@CO{ex}
+checks for when doing file name expansion.
+If any of the specified characters are found in the file name arguments
+to the
+@CO{ex}
+commands,
+the arguments are expanded using the program defined by the
+@OP{shell}
+option.
+The default set of characters is a union of meta characters
+from the Version 7 and the Berkeley C shell.
+@cindex shiftwidth
+@IP{shiftwidth, sw [8]}
+
+Set the autoindent and shift command indentation width.
+This width is used by the
+@OP{autoindent}
+option and by the
+@CO{<},
+@CO{>},
+and
+@CO{shift}
+commands.
+@cindex showmatch
+@IP{showmatch, sm [off]}
+
+@CO{Vi}
+only.
+This option causes
+@CO{vi},
+when a
+@comment QT
+``@code{@}}''
+or
+@QT{)}
+is entered, to briefly move the cursor the matching
+@comment QT
+``@code{@{}''
+or
+@QT{(}.
+See the
+@OP{matchtime}
+option for more information.
+@cindex showmode
+@IP{showmode, smd [off]}
+
+@CO{Vi}
+only.
+This option causes
+@CO{vi}
+to display a string identifying the current editor mode on the colon
+command line.
+The string is preceded by an asterisk (``*'') if the file has been
+modified since it was last completely written,
+@cindex sidescroll
+@IP{sidescroll [16]}
+
+@CO{Vi}
+only.
+Sets the number of columns that are shifted to the left or right,
+when
+@CO{vi}
+is doing left-right scrolling and the left or right margin is
+crossed.
+See the
+@OP{leftright}
+option for more information.
+@cindex slowopen
+@IP{slowopen, slow [off]}
+
+This option affects the display algorithm used by
+@CO{vi},
+holding off display updating during input of new text to improve
+throughput when the terminal in use is slow and unintelligent.
+@sp 1
+@emph{This option is not yet implemented.}
+@cindex sourceany
+@IP{sourceany [off]}
+
+If this option is turned on,
+@CO{vi}
+historically read startup files that were owned by someone other than
+the editor user.
+See the section entitled
+@QB{Startup Information}
+for more information.
+This option is a security problem of immense proportions,
+and should not be used under any circumstances.
+@sp 1
+@emph{This option will never be implemented.}
+@cindex tabstop
+@IP{tabstop, ts [8]}
+
+This option sets tab widths for the editor display.
+@cindex taglength
+@IP{taglength, tl [0]}
+
+This option sets the maximum number of characters that are considered
+significant in a tag name.
+Setting the value to 0 makes all of the characters in the tag name
+significant.
+@cindex tags
+@IP{tags, tag [tags /var/db/libc.tags /sys/kern/tags]}
+
+Sets the list of tags files, in search order,
+which are used when the editor searches for a tag.
+@cindex term
+@IP{term, ttytype, tty [environment variable TERM]}
+
+Set the terminal type.
+Setting this option causes
+@EV{ex,vi}
+to set (or reset) the environmental variable
+@LI{TERM}.
+@cindex terse
+@IP{terse [off]}
+
+This option has historically made editor messages less verbose.
+It has no effect in this implementation.
+See the
+@OP{verbose}
+option for more information.
+@cindex tildeop
+@IP{tildeop [off]}
+
+Modify the
+@CO{~}
+command to take an associated motion.
+@cindex timeout
+@IP{timeout, to [on]}
+
+If this option is set,
+@EV{ex,vi}
+waits for a specific period for a subsequent key to complete a key
+mapping (see the
+@OP{keytime}
+option).
+If the option is not set, the editor waits until enough keys are
+entered to resolve the ambiguity, regardless of how long it takes.
+@cindex ttywerase
+@IP{ttywerase [off]}
+
+@CO{Vi}
+only.
+This option changes how
+@CO{vi}
+does word erase during text input.
+If this option is set, text is broken up into two classes,
+blank characters and nonblank characters.
+Changing from one class to another marks the end of a word.
+@cindex verbose
+@IP{verbose [off]}
+
+@CO{Vi}
+only.
+@CO{Vi}
+historically bells the terminal for many obvious mistakes, e.g. trying
+to move past the left-hand margin, or past the end of the file.
+If this option is set, an error message is displayed for all errors.
+@cindex w300
+@IP{w300 [no default]}
+
+@CO{Vi}
+only.
+Set the window size if the baud rate is less than 1200 baud.
+See the
+@OP{window}
+option for more information.
+@cindex w1200
+@IP{w1200 [no default]}
+
+@CO{Vi}
+only.
+Set the window size if the baud rate is equal to 1200 baud.
+See the
+@OP{window}
+option for more information.
+@cindex w9600
+@IP{w9600 [no default]}
+
+@CO{Vi}
+only.
+Set the window size if the baud rate is greater than 1200 baud.
+See the
+@OP{window}
+option for more information.
+@cindex warn
+@IP{warn [on]}
+
+@CO{Ex}
+only.
+This option causes a warning message to the terminal if the file has
+been modified, since it was last written, before a
+@CO{!}
+command.
+@cindex window
+@IP{window, w, wi [environment variable LINES - 1]}
+
+This option determines the default number of lines in a screenful,
+as displayed by the
+@CO{z}
+command.
+It also determines the number of lines scrolled by the
+@CO{vi}
+commands
+@CO{<control-B>}
+and
+@CO{<control-F>},
+and the default number of lines scrolled by the
+@CO{vi}
+commands
+@CO{<control-D>}
+and
+@CO{<control-U>}.
+The value of window can be unrelated to the real screen size,
+although it starts out as the number of lines on the screen.
+See the section entitled
+@QB{Sizing the Screen}
+for more information.
+Setting the value of the
+@OP{window}
+option is the same as using the
+@strong{-w}
+command line option.
+@sp 1
+If the value of the
+@OP{window}
+option (as set by the
+@OP{window},
+@OP{w300},
+@OP{w1200}
+or
+@OP{w9600}
+options) is smaller than the actual size of the screen,
+large screen movements will result in displaying only that smaller
+number of lines on the screen.
+(Further movements in that same area will result in the screen being
+filled.)
+This can provide a performance improvement when viewing different
+places in one or more files over a slow link.
+@sp 1
+Resetting the window size does not reset the default number of lines
+scrolled by the
+@CO{<control-D>}
+and
+@CO{<control-U>}
+commands.
+@cindex windowname
+@IP{windowname [off]}
+
+@CO{Vi}
+changes the name of the editor's icon/window to the current file name
+when it's possible and not destructive, i.e.,
+when the editor can restore it to its original value on exit or when
+the icon/window will be discarded as the editor exits.
+If the
+@OP{windowname}
+edit option is set,
+@CO{vi}
+will change the icon/window name even when it's destructive and the
+icon/window name will remain after the editor exits.
+(This is the case for
+@XR{xterm,1}).
+@cindex wraplen
+@IP{wraplen, wl [0]}
+
+This option is identical to the
+@OP{wrapmargin}
+option, with the exception that it specifies the number of columns
+from the
+@emph{left}
+margin before the line splits, not the right margin.
+@sp 1
+If both
+@OP{wraplen}
+and
+@OP{wrapmargin}
+are set, the
+@OP{wrapmargin}
+value is used.
+@cindex wrapmargin
+@IP{wrapmargin, wm [0]}
+
+@CO{Vi}
+only.
+If the value of the
+@OP{wrapmargin}
+option is non-zero,
+@CO{vi}
+will split lines so that they end at least that number of columns
+before the right-hand margin of the screen.
+(Note, the value of
+@OP{wrapmargin}
+is
+@emph{not}
+a text length.
+In a screen that is 80 columns wide, the command
+@QT{:set wrapmargin=8}
+attempts to keep the lines less than or equal to 72 columns wide.)
+@sp 1
+Lines are split at the previous whitespace character closest to the
+number.
+Any trailing whitespace characters before that character are deleted.
+If the line is split because of an inserted
+@LI{<space>}or
+@LI{<tab>}character, and you then enter another
+@LI{<space>}character, it is discarded.
+@sp 1
+If wrapmargin is set to 0,
+or if there is no blank character upon which to split the line,
+the line is not broken.
+@sp 1
+If both
+@OP{wraplen}
+and
+@OP{wrapmargin}
+are set, the
+@OP{wrapmargin}
+value is used.
+@cindex wrapscan
+@IP{wrapscan, ws [on]}
+
+This option causes searches to wrap around the end or the beginning
+of the file, and back to the starting point.
+Otherwise, the end or beginning of the file terminates the search.
+@cindex writeany
+@IP{writeany, wa [off]}
+
+If this option is set, file-overwriting checks that would usually be
+made before the
+@CO{write}
+and
+@CO{xit}
+commands, or before an automatic write (see the
+@OP{autowrite}
+option), are not made.
+This allows a write to any file, provided the file permissions allow it.
+@end itemize
diff --git a/dist/nvi/docs/vi.ref/spell.ok b/dist/nvi/docs/vi.ref/spell.ok
new file mode 100644 (file)
index 0000000..a7d95e3
--- /dev/null
@@ -0,0 +1,414 @@
+ABC
+Amir
+Autoindent
+Autoprint
+BRE's
+Bostic
+Bourne
+CDPATH
+CSCOPE
+Cscope
+DIRS
+DOUBLEQUOTE
+Dq
+Ds
+ERE's
+EXINIT
+Englar
+Ev
+FF
+Fa
+Fg
+FindScreen
+Fl
+Foregrounding
+HUnhsh
+IPLPPPQPP
+Kirkendall
+Korn
+LC
+LIpplpipbp
+LaA
+Li
+Lowercase
+MINUSSIGN
+Makefiles
+Mayoff
+NEX
+NEXINIT
+NHSHH
+NVI
+Neville
+Nex
+Nvi
+OS
+POSIX
+Perl
+PostScript
+QQ
+RE's
+README
+RECDIR
+Reference''USD:13
+SENDMAIL
+SIGHUP
+SIGWINCH
+SQUOTE
+Se
+Std
+Std1003.2
+Sven
+Sy
+TANDARDS
+TIOCGWINSZ
+TMPDIR
+TOC
+Tagnext
+Tagprev
+Tcl
+Tk
+Todo
+USD
+USD.doc
+USD:13
+UUNET
+Unmap
+VI
+Verdoolaege
+Vi
+Vx
+Whitespace
+XOFF
+XON
+XOptions
+XXCOLUMNS
+XXXX
+XXXXXX
+XXb
+ZZ
+ab
+abbrev
+abc
+ags
+ai
+al
+altwerase
+ap
+api
+ar
+arg
+args
+att
+autoindent
+autoprint
+autowrite
+aw
+backgrounded
+backgrounding
+bbrev
+berkeley
+bf
+bg
+bigword
+bigwords
+bostic
+bp
+brev
+bsd
+bugs.current
+c2w
+carat
+cd
+cdpath
+cdy
+cedit
+changelog
+chd
+chdir
+cmd
+co
+count1
+count2
+creens
+cs
+cs.berkeley.edu
+cscope
+ctags
+cw
+db
+dbopen
+dd
+def
+di
+dir
+dit
+docs
+eE
+eFlRsv
+eFlRv
+eL
+eU
+ead
+eb
+edcompatible
+edu
+ee
+egrep
+elete
+elp
+elvis
+email
+enum
+eof
+errorbells
+esc
+escapetime
+eset
+eu
+ex.cmd.roff
+exrc
+ext
+exu
+exusage
+fcntl
+fg
+fi
+filec
+filesystem
+filesystems
+foo
+foregrounded
+foregrounding
+ftp.cs.berkeley.edu
+ftp.uu.net
+gdb
+gdb.script
+getpwent
+gs
+gzip'd
+halfbyte
+hange
+hangup
+hardtabs
+ht
+html
+http
+ic
+iclower
+ifdef
+ignorecase
+ile
+ind
+initially
+ious
+ir
+iscntrl
+isprint
+ist
+ize
+keystroke
+keystrokes
+keytime
+leftright
+lhs
+li
+lib
+libc
+libc.tags
+lineNum
+lineNumber
+lobal
+lowercase
+lp
+luR
+matchtime
+mber
+mesg
+meta
+mk
+mkexrc
+modeful
+modeline
+modelines
+ms
+msgcat
+ndo
+nex
+nexrc
+nk
+nomagic
+nonblank
+nonoverlapping
+nooption
+noprint
+nsert
+nul
+nvi
+nvi.tar.Z
+nvi.tar.z
+nz
+oin
+onnections
+op
+ove
+para
+pathname
+pathnames
+pe
+perl
+perld
+ppend
+prev
+pu
+py
+rc
+rc.local
+readonly
+rec
+recdir
+recfile
+recover.XXXX
+recover.XXXXXX
+recover.c
+recover.script
+redist
+redistributable
+reimplementations
+remapmax
+remapped
+repl
+res
+rew
+rhs
+rint
+ript
+rk
+rl
+ro
+roff
+rsion
+sc
+sccs
+scr
+screeen
+screenId
+se
+searchincr
+sendmail
+set.opt.roff
+settable
+setuid
+sh
+shareware
+shellmeta
+shiftwidth
+showmatch
+showmode
+sidescroll
+slowopen
+sm
+smd
+sourceany
+sp
+spell.ok
+ssg
+st
+su
+sual
+svi
+sw
+ta
+tabstop
+taglength
+tagn
+tagnext
+tagp
+tagpop
+tagprev
+tagstring
+tagt
+tagtop
+tc
+tcl
+tclproc
+terminfo
+th
+th's
+tildeop
+tl
+tmp
+toolchest
+tpath
+tr
+ts
+ttytype
+ttywerase
+uR
+ubstitute
+ucb
+uffers
+uit
+una
+unabbrev
+unescaped
+unm
+unmap
+unsets
+uppercase
+urce
+usr
+uunet
+v
+var
+ve
+vi
+vi.0.ps
+vi.0.txt
+vi.1
+vi.XXXX
+vi.XXXXXX
+vi.cmd.roff
+vi.exrc
+vi.recover
+viAppendLine
+viDelLine
+viEndScreen
+viFindScreen
+viGetCursor
+viGetLine
+viGetMark
+viGetOpt
+viInsertLine
+viLastLine
+viMapKey
+viMsg
+viNewScreen
+viSetCursor
+viSetLine
+viSetMark
+viSetOpt
+viSwitchScreen
+viUnmMapKey
+vibackup
+virecovery
+viu
+viusage
+wa
+whitespace
+wi
+windowname
+wl
+wm
+wn
+wq
+wraplen
+wrapmargin
+wrapscan
+writeany
+ws
+www
+xaw
+xit
+xterm
+ya
+yy
diff --git a/dist/nvi/docs/vi.ref/vi.cmd.texi b/dist/nvi/docs/vi.ref/vi.cmd.texi
new file mode 100644 (file)
index 0000000..80400cf
--- /dev/null
@@ -0,0 +1,3155 @@
+@comment  Copyright (c) 1994
+@c $NetBSD: vi.cmd.texi,v 1.2 2008/10/01 21:20:09 christos Exp $
+@comment       The Regents of the University of California.  All rights reserved.
+@comment  Copyright (c) 1994, 1995, 1996
+@comment       Keith Bostic.  All rights reserved.
+@comment 
+@comment  See the LICENSE file for redistribution information.
+@comment 
+@comment       Id: vi.cmd.texi,v 8.1 2001/08/18 20:43:49 skimo Exp (Berkeley) Date: 2001/08/18 20:43:49
+@comment 
+@chapter Vi Description
+
+@CO{Vi} takes up the entire screen to display the edited file,
+except for the bottom line of the screen.
+The bottom line of the screen is used to enter
+@CO{exp}
+commands, and for
+@CO{vi}
+error and informational messages.
+If no other information is being displayed,
+the default display can show the current cursor row and cursor column,
+an indication of whether the file has been modified,
+and the current mode of the editor.
+See the
+@OP{ruler}
+and
+@OP{showmode}
+options for more information.
+
+Empty lines do not have any special representation on the screen,
+but lines on the screen that would logically come after the end of
+the file are displayed as a single tilde
+@PQ{~}
+character.
+To differentiate between empty lines and lines consisting of only
+whitespace characters, use the
+@OP{list}
+option.
+Historically, implementations of
+@CO{vi}
+have also displayed some lines as single asterisk
+@PQ{@@}
+characters.
+These were lines that were not correctly displayed, i.e. lines on the
+screen that did not correspond to lines in the file, or lines that did
+not fit on the current screen.
+@CO{Nvi}
+never displays lines in this fashion.
+
+@CO{Vi}
+is a modeful editor, i.e. it has two modes,
+@QQ{command}
+mode and
+@QQ{text input}
+mode.
+When
+@CO{vi}
+first starts, it is in command mode.
+There are several commands that change
+@CO{vi}
+into text input mode.
+The
+@LI{<escape>}character is used to resolve the text input into the file,
+and exit back into command mode.
+In
+@CO{vi}
+command mode, the cursor is always positioned on the last column of
+characters which take up more than one column on the screen.
+In
+@CO{vi}
+text insert mode, the cursor is positioned on the first column of
+characters which take up more than one column on the screen.
+
+When positioning the cursor to a new line and column,
+the type of movement is defined by the distance to the new cursor position.
+If the new position is close,
+the screen is scrolled to the new location.
+If the new position is far away,
+the screen is repainted so that the new position is on the screen.
+If the screen is scrolled,
+it is moved a minimal amount,
+and the cursor line will usually appear at the top or bottom of the screen.
+If the screen is repainted,
+the cursor line will appear in the center of the screen,
+unless the cursor is sufficiently close to the beginning or end of the file
+that this isn't possible.
+If the
+@OP{leftright}
+option is set, the screen may be scrolled or repainted in a horizontal
+direction as well as in a vertical one.
+
+A major difference between the historical
+@CO{vi}
+presentation and
+@CO{nvi}
+is in the scrolling and screen oriented position commands,
+@CO{<control-B>},
+@CO{<control-D>},
+@CO{<control-E>},
+@CO{<control-F>},
+@CO{<control-U>},
+@CO{<control-Y>},
+@CO{H},
+@CO{L}
+and
+@CO{M}.
+In historical implementations of
+@CO{vi},
+these commands acted on physical (as opposed to logical, or screen)
+lines.
+For lines that were sufficiently long in relation to the size of the
+screen, this meant that single line scroll commands might repaint the
+entire screen, scrolling or screen positioning commands might not change
+the screen or move the cursor at all, and some lines simply could not
+be displayed, even though
+@CO{vi}
+would edit the file that contained them.
+In
+@CO{nvi},
+these commands act on logical, i.e. screen lines.
+You are unlikely to notice any difference unless you are editing files
+with lines significantly longer than a screen width.
+
+@CO{Vi}
+keeps track of the currently
+@QQ{most attractive}
+cursor position.
+Each command description (for commands that alter the current cursor
+position),
+specifies if the cursor is set to a specific location in the line,
+or if it is moved to the
+@QQ{most attractive cursor position}.
+The latter means that the cursor is moved to the cursor position that
+is horizontally as close as possible to the current cursor position.
+If the current line is shorter than the cursor position
+@CO{vi}
+would select, the cursor is positioned on the last character in the line.
+(If the line is empty, the cursor is positioned on the first column
+of the line.)
+If a command moves the cursor to the most attractive position,
+it does not alter the current cursor position, and a subsequent
+movement will again attempt to move the cursor to that position.
+Therefore, although a movement to a line shorter than the currently
+most attractive position will cause the cursor to move to the end of
+that line, a subsequent movement to a longer line will cause the
+cursor to move back to the most attractive position.
+
+In addition, the
+@CO{$}
+command makes the end of each line the most attractive cursor position
+rather than a specific column.
+
+Each
+@CO{vi}
+command described below notes where the cursor ends up after it is
+executed.
+This position is described in terms of characters on the line, i.e.
+@QQ{the previous character},
+or,
+@QQ{the last character in the line}.
+This is to avoid needing to continually refer to on what part of the
+character the cursor rests.
+
+The following words have special meaning for
+@CO{vi}
+commands.
+@itemize @bullet
+@cindex "previous context"
+@IP{previous context}
+
+The position of the cursor before the command which caused the
+last absolute movement was executed.
+Each 
+@CO{vi}
+command described in the next section that is considered an
+absolute movement is so noted.
+In addition, specifying
+@emph{any}
+address to an
+@CO{ex}
+command is considered an absolute movement.
+@cindex "motion"
+@IP{motion}
+
+A second
+@CO{vi}
+command can be used as an optional trailing argument to the
+@CO{vi}
+@CO{<},
+@CO{>},
+@CO{!},
+@CO{c},
+@CO{d},
+@CO{y},
+and (depending on the
+@OP{tildeop}
+option)
+@CO{~}
+commands.
+This command indicates the end of the region of text that's affected by
+the command.
+The motion command may be either the command character repeated (in
+which case it means the current line) or a cursor movement command.
+In the latter case, the region affected by the command is from the
+starting or stopping cursor position which comes first in the file,
+to immediately before the starting or stopping cursor position which
+comes later in the file.
+Commands that operate on lines instead of using beginning and ending
+cursor positions operate on all of the lines that are wholly or
+partially in the region.
+In addition, some other commands become line oriented depending on
+where in the text they are used.
+The command descriptions below note these special cases.
+@sp 1
+The following commands may all be used as motion components for
+@CO{vi}
+commands:
+@sp 1
+@multitable {@CO{<control-N>}} {@CO{'<character>}} {@CO{<control-J>}} {@CO{<control-M>}}
+@item @CO{<control-A>} @tab @CO{<control-H>} @tab @CO{<control-J>} @tab @CO{<control-M>}
+@item @CO{<control-N>} @tab @CO{<control-P>} @tab @CO{<space>} @tab @CO{$}
+@item @CO{%} @tab @CO{'<character>} @tab @CO{(} @tab @CO{)}
+@item @CO{+} @tab @CO{,} @tab @CO{-} @tab @CO{/}
+@item @CO{0} @tab @CO{;} @tab @CO{?} @tab @CO{B}
+@item @CO{E} @tab @CO{F} @tab @CO{G} @tab @CO{H}
+@item @CO{L} @tab @CO{M} @tab @CO{N} @tab @CO{T}
+@item @CO{W} @tab @CO{[[} @tab @CO{]]} @tab @CO{^}
+@item @CO{_} @tab @CO{`<character>} @tab @CO{b} @tab @CO{e}
+@item @CO{f} @tab @CO{h} @tab @CO{j} @tab @CO{k}
+@item @CO{l} @tab @CO{n} @tab @CO{t} @tab @CO{w}
+@item @strong{@{} @tab @CO{|} @tab @strong{@}}
+@end multitable
+@sp 1
+The optional count prefix available for some of the
+@CO{vi}
+commands that take motion commands,
+or the count prefix available for the
+@CO{vi}
+commands that are used as motion components,
+may be included and is
+@emph{always}
+considered part of the motion argument.
+For example, the commands
+@QT{c2w}
+and
+@QT{2cw}
+are equivalent, and the region affected by the
+@CO{c}
+command is two words of text.
+In addition,
+if the optional count prefix is specified for both the
+@CO{vi}
+command and its motion component,
+the effect is multiplicative and is considered part of the motion argument.
+For example, the commands
+@QT{4cw}
+and
+@QT{2c2w}
+are equivalent, and the region affected by the
+@CO{c}
+command is four words of text.
+@cindex "count"
+@IP{count}
+
+A positive number used as an optional argument to most commands,
+either to give a size or a position (for display or movement commands),
+or as a repeat count (for commands that modify text).
+The count argument is always optional and defaults to 1 unless otherwise
+noted in the command description.
+@sp 1
+When a
+@CO{vi}
+command synopsis shows both a
+@LI{[buffer]}and
+@LI{[count]},
+they may be presented in any order.
+@cindex word
+@IP{word}
+
+Generally, in languages where it is applicable,
+@CO{vi}
+recognizes two kinds of words.
+First, a sequence of letters, digits and underscores,
+delimited at both ends by:
+characters other than letters, digits, or underscores,
+the beginning or end of a line, and the beginning or end of the file.
+Second, a sequence of characters other than letters, digits, underscores,
+or whitespace characters, delimited at both ends by: a letter, digit,
+underscore, or whitespace character,
+the beginning or end of a line, and the beginning or end of the file.
+For example, the characters
+@QT{ !@@#abc$%^ }
+contain three words:
+@QT{!@@#},
+@QT{abc}
+and
+@QT{$%^}.
+@sp 1
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single word.
+@cindex "bigword"
+@IP{bigword}
+
+A set of non-whitespace characters preceded and followed by whitespace
+characters or the beginning or end of the file or line.
+For example, the characters
+@QT{ !@@#abc$%^ }
+contain one bigword:
+@QT{!@@#abc$%^}.
+@sp 1
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single bigword.
+@cindex "paragraph"
+@IP{paragraph}
+
+An area of text that begins with either the beginning of a file,
+an empty line, or a section boundary, and continues until either
+an empty line, section boundary, or the end of the file.
+@sp 1
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single paragraph.
+@sp 1
+Additional paragraph boundaries can be defined using the
+@OP{paragraphs}
+option.
+@cindex "section"
+@IP{section}
+
+An area of text that starts with the beginning of the file or a line
+whose first character is an open brace
+@comment PQ
+``@code{@{}''
+and continues until the next section or the end of the file.
+@sp 1
+Additional section boundaries can be defined using the
+@OP{sections}
+option.
+@cindex "sentence"
+@IP{sentence}
+
+An area of text that begins with either the beginning of the file or the
+first nonblank character following the previous sentence, paragraph, or
+section boundary and continues until the end of the file or a period
+@PQ{.}
+exclamation point
+@PQ{!}
+or question mark
+@PQ{?}
+character,
+followed by either an end-of-line or two whitespace characters.
+Any number of closing parentheses
+@PQ{)},
+brackets
+@PQ{]},
+double-quote
+@PQ{"}
+or single quote
+@PQ{'}
+characters can appear between the period, exclamation point,
+or question mark and the whitespace characters or end-of-line.
+@sp 1
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single sentence.
+@chapter Vi Commands
+@end itemize
+
+The following section describes the commands available in the command
+mode of the
+@CO{vi}
+editor.
+In each entry below, the tag line is a usage synopsis for the command
+character.
+In addition, the final line and column the cursor rests upon,
+and any options which affect the command are noted.
+
+@cindex <control-A>
+@deftypefn Command {[count]} {<control-A>}
+
+Search forward
+@LI{count}times for the current word.
+The current word begins at the first non-whitespace character on or
+after the current cursor position,
+and extends up to the next non-word character or the end of the line.
+The search is literal, i.e. no characters in the word have any special
+meaning in terms of Regular Expressions.
+It is an error if no matching pattern is found between the starting position
+and the end of the file.
+@sp 1
+The
+@CO{<control-A>}
+command is an absolute movement.
+The
+@CO{<control-A>}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Set to the line where the word is found.
+@item Column:
+Set to the first character of the word.
+@item Options:
+Affected by the
+@OP{ignorecase}
+and
+@OP{wrapscan}
+options.
+@end table
+@end deftypefn
+@cindex <control-B>
+@deftypefn Command {[count]} {<control-B>}
+
+Page backward
+@LI{count}screens.
+Two lines of overlap are maintained, if possible,
+by displaying the window starting at line
+@LI{(top_line - count * window_size) + 2},
+where
+@LI{window_size}is the value of the
+@OP{window}
+option.
+(In the case of split screens, this size is corrected to the
+current screen size.)
+It is an error if the movement is past the beginning of the file.
+@table @asis
+@item Line:
+Set to the last line of text displayed on the screen.
+@item Column:
+Set to the first nonblank character of the line.
+@item Options:
+Affected by the
+@OP{window}
+option.
+@end table
+@end deftypefn
+@cindex <control-D>
+@deftypefn Command {[count]} {<control-D>}
+
+Scroll forward
+@LI{count}lines.
+If
+@LI{count}is not specified, scroll forward the number of lines specified by the last
+@CO{<control-D>}
+or
+@CO{<control-U>}
+command.
+If this is the first
+@CO{<control-D>}
+or
+@CO{<control-U>}
+command,
+scroll forward half the number of lines in the screen.
+(In the case of split screens, the default scrolling distance is
+corrected to half the current screen size.)
+It is an error if the movement is past the end of the file.
+@table @asis
+@item Line:
+Set to the current line plus the number of lines scrolled.
+@item Column:
+Set to the first nonblank character of the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-E>
+@deftypefn Command {[count]} {<control-E>}
+
+Scroll forward
+@LI{count}lines, leaving the cursor on the current line and column, if possible.
+It is an error if the movement is past the end of the file.
+@table @asis
+@item Line:
+Unchanged unless the current line scrolls off the screen,
+in which case it is set to the first line on the screen.
+@item Column:
+Unchanged unless the current line scrolls off the screen,
+in which case it is set to the most attractive cursor position.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-F>
+@deftypefn Command {[count]} {<control-F>}
+
+Page forward
+@LI{count}screens.
+Two lines of overlap are maintained, if possible,
+by displaying the window starting at line
+@LI{top_line + count * window_size - 2},
+where
+@LI{window_size}is the value of the
+@OP{window}
+option.
+(In the case of split screens, this size is corrected to the
+current screen size.)
+It is an error if the movement is past the end of the file.
+@table @asis
+@item Line:
+Set to the first line on the screen.
+@item Column:
+Set to the first nonblank character of the current line.
+@item Options:
+Affected by the
+@OP{window}
+option.
+@end table
+@end deftypefn
+@cindex <control-G>
+@deftypefn Command {} {<control-G>}
+
+Display the file information.
+The information includes the current pathname, the current line,
+the number of total lines in the file, the current line as a percentage
+of the total lines in the file, if the file has been modified,
+was able to be locked, if the file's name has been changed,
+and if the edit session is read-only.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+
+@cindex <control-H>
+@deftypefn Command {[count]} {<control-H>}
+@deftypefnx Command {[count]} {h}
+Move the cursor back
+@LI{count}characters in the current line.
+It is an error if the cursor is on the first character in the line.
+@sp 1
+The
+@CO{<control-H>}
+and
+@CO{h}
+commands may be used as the motion component of other
+@CO{vi}
+commands,
+in which case any text copied into a buffer is character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the
+@LI{current - count}character, or, the first character in the line if
+@LI{count}is greater than or equal to the number of characters in the line
+before the cursor.
+@item Options:
+None.
+@end table
+@end deftypefn
+
+@cindex <control-J>
+@deftypefn Command {[count]} {<control-J>}
+
+@cindex <control-N>
+@deftypefnx Command  {[count]} {<control-N>}
+@cindex j
+@deftypefnx Command  {[count]} {j}
+Move the cursor down
+@LI{count}lines without changing the current column.
+It is an error if the movement is past the end of the file.
+@sp 1
+The
+@CO{<control-J>},
+@CO{<control-N>}
+and
+@CO{j}
+commands may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to the current line plus
+@LI{count}.
+@item Column:
+The most attractive cursor position.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-L>
+@deftypefn Command {} {<control-L>}
+
+@cindex <control-R>
+@deftypefnx Command {}  {<control-R>}
+Repaint the screen.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-M>
+@deftypefn Command {[count]} {<control-M>}
+
+@cindex +
+@deftypefnx Command  {[count]} {+}
+Move the cursor down
+@LI{count}lines to the first nonblank character of that line.
+It is an error if the movement is past the end of the file.
+@sp 1
+The
+@CO{<control-M>}
+and
+@CO{+}
+commands may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to the current line plus
+@LI{count}.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-P>
+@deftypefn Command {[count]} {<control-P>}
+
+@cindex k
+@deftypefnx Command  {[count]} {k}
+Move the cursor up
+@LI{count}lines, without changing the current column.
+It is an error if the movement is past the beginning of the file.
+@sp 1
+The
+@CO{<control-P>}
+and
+@CO{k}
+commands may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to the current line minus
+@LI{count}.
+@item Column:
+The most attractive cursor position.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-T>
+@deftypefn Command {} {<control-T>}
+
+Return to the most recent tag context.
+The
+@CO{<control-T>}
+command is an absolute movement.
+@table @asis
+@item Line:
+Set to the context of the previous tag command.
+@item Column:
+Set to the context of the previous tag command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-U>
+@deftypefn Command {[count]} {<control-U>}
+
+Scroll backward
+@LI{count}lines.
+If
+@LI{count}is not specified, scroll backward the number of lines specified by the
+last
+@CO{<control-D>}
+or
+@CO{<control-U>}
+command.
+If this is the first
+@CO{<control-D>}
+or
+@CO{<control-U>}
+command,
+scroll backward half the number of lines in the screen.
+(In the case of split screens, the default scrolling distance is
+corrected to half the current screen size.)
+It is an error if the movement is past the beginning of the file.
+@table @asis
+@item Line:
+Set to the current line minus the amount scrolled.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-W>
+@deftypefn Command {} {<control-W>}
+
+Switch to the next lower screen in the window, or, to the first
+screen if there are no lower screens in the window.
+@table @asis
+@item Line:
+Set to the previous cursor position in the window.
+@item Column:
+Set to the previous cursor position in the window.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-Y>
+@deftypefn Command {[count]} {<control-Y>}
+
+Scroll backward
+@LI{count}lines, leaving the current line and column as is, if possible.
+It is an error if the movement is past the beginning of the file.
+@table @asis
+@item Line:
+Unchanged unless the current line scrolls off the screen,
+in which case it is set to the last line of text displayed
+on the screen.
+@item Column:
+Unchanged unless the current line scrolls off the screen,
+in which case it is the most attractive cursor position.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-Z>
+@deftypefn Command {} {<control-Z>}
+
+Suspend the current editor session.
+If the file has been modified since it was last completely written,
+and the
+@OP{autowrite}
+option is set, the file is written before the editor session is
+suspended.
+If this write fails, the editor session is not suspended.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged.
+@item Options:
+Affected by the
+@OP{autowrite}
+option.
+@end table
+@end deftypefn
+@cindex <escape>
+@deftypefn Command {} {<escape>}
+
+Execute
+@CO{ex}
+commands or cancel partial commands.
+If an
+@CO{ex}
+command is being entered (e.g.
+@CO{/},
+@CO{?},
+@CO{:}
+or
+@CO{!}),
+the command is executed.
+If a partial command has been entered, e.g.
+@QT{[0-9]*},
+or
+@QT{[0-9]*[!<>cdy]},
+the command is cancelled.
+Otherwise, it is an error.
+@table @asis
+@item Line:
+When an
+@CO{ex}
+command is being executed, the current line is set as described for
+that command.
+Otherwise, unchanged.
+@item Column:
+When an
+@CO{ex}
+command is being executed, the current column is set as described for
+that command.
+Otherwise, unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <control-]>
+@deftypefn Command {} {<control-]>}
+
+Push a tag reference onto the tag stack.
+The tags files (see the
+@OP{tags}
+option for more information) are searched for a tag matching the
+current word.
+The current word begins at the first non-whitespace character on or
+after the current cursor position,
+and extends up to the next non-word character or the end of the line.
+If a matching tag is found, the current file is discarded and the
+file containing the tag reference is edited.
+@sp 1
+If the current file has been modified since it was last completely
+written, the command will fail.
+The
+@CO{<control-]>}
+command is an absolute movement.
+@table @asis
+@item Line:
+Set to the line containing the matching tag string.
+@item Column:
+Set to the start of the matching tag string.
+@item Options:
+Affected by the
+@OP{tags}
+and
+@OP{taglength}
+options.
+@end table
+@end deftypefn
+@cindex <control-^>
+@deftypefn Command {} {<control-^>}
+
+Switch to the most recently edited file.
+@sp 1
+If the file has been modified since it was last completely written,
+and the
+@OP{autowrite}
+option is set, the file is written out.
+If this write fails, the command will fail.
+Otherwise, if the current file has been modified since it was last
+completely written, the command will fail.
+@table @asis
+@item Line:
+Set to the line the cursor was on when the file was last edited.
+@item Column:
+Set to the column the cursor was on when the file was last edited.
+@item Options:
+Affected by the
+@OP{autowrite}
+option.
+@end table
+@end deftypefn
+@cindex <space>
+@deftypefn Command {[count]} {<space>}
+
+@cindex l
+@deftypefnx Command  {[count]} {l}
+Move the cursor forward
+@LI{count}characters without changing the current line.
+It is an error if the cursor is on the last character in the line.
+@sp 1
+The
+@CO{<space>}
+and
+@CO{l}
+commands may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+In addition, these commands may be used as the motion components
+of other commands when the cursor is on the last character in the
+line, without error.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the current character plus the next
+@LI{count}characters, or to the last character on the line if
+@LI{count}is greater than the number of characters in the line after the
+current character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex !
+@deftypefn Command {[count]} {!} {motion shell-argument(s)<carriage-return>}
+
+Replace text with results from a shell command.
+Pass the lines specified by the
+@LI{count}and
+@LI{motion}arguments as standard input to the program named by the
+@OP{shell}
+option, and replace those lines with the output (both
+standard error and standard output) of that command.
+@sp 1
+After the motion is entered,
+@CO{vi}
+prompts for arguments to the shell command.
+@sp 1
+Within those arguments,
+@QT{%}
+and
+@QT{#}
+characters are expanded to the current and alternate pathnames,
+respectively.
+The
+@QT{!}
+character is expanded with the command text of the previous
+@CO{!}
+or
+@CO{:!}
+commands.
+(Therefore, the command
+@CO{!<motion>!}
+repeats the previous
+@CO{!}
+command.)
+The special meanings of
+@QT{%},
+@QT{#}
+and
+@QT{!}
+can be overridden by escaping them with a backslash.
+If no
+@CO{!}
+or
+@CO{:!}
+command has yet been executed,
+it is an error to use an unescaped
+@QT{!}
+character as a shell argument.
+The
+@CO{!}
+command does
+@emph{not}
+do shell expansion on the strings provided as arguments.
+If any of the above expansions change the arguments the user entered,
+the command is redisplayed at the bottom of the screen.
+@sp 1
+@CO{Vi}
+then executes the program named by the
+@OP{shell}
+option, with a
+@strong{-c}
+flag followed by the arguments (which are bundled into a single argument).
+@sp 1
+The
+@CO{!}
+command is permitted in an empty file.
+@sp 1
+If the file has been modified since it was last completely written,
+the
+@CO{!}
+command will warn you.
+@table @asis
+@item Line:
+The first line of the replaced text.
+@item Column:
+The first column of the replaced text.
+@item Options:
+Affected by the
+@OP{shell}
+option.
+@end table
+@end deftypefn
+@cindex #
+@deftypefn Command {[count]} {#} {#|+|-}
+
+Increment or decrement the number referenced by the cursor.
+If the trailing character is a
+@LI{+}or
+@LI{#},
+the number is incremented by
+@LI{count}.
+If the trailing character is a
+@LI{-},
+the number is decremented by
+@LI{count}.
+@sp 1
+A leading
+@QT{0X}
+or
+@QT{0x}
+causes the number to be interpreted as a hexadecimal number.
+Otherwise, a leading
+@QT{0}
+causes the number to be interpreted as an octal number, unless a non-octal
+digit is found as part of the number.
+Otherwise, the number is interpreted as a decimal number, and may
+have a leading
+@LI{+}or
+@LI{-}sign.
+The current number begins at the first non-blank character at or after
+the current cursor position, and extends up to the end of the line or
+the first character that isn't a possible character for the numeric type.
+The format of the number (e.g. leading 0's, signs) is retained unless
+the new value cannot be represented in the previous format.
+@sp 1
+Octal and hexadecimal numbers, and the result of the operation, must fit
+into an
+@QT{unsigned long}.
+Similarly, decimal numbers and their result must fit into a
+@QT{signed long}.
+It is an error to use this command when the cursor is not positioned at
+a number.
+@sp 1
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the first character in the cursor number.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex $
+@deftypefn Command {[count]} {$}
+
+Move the cursor to the end of a line.
+If
+@LI{count}is specified, the cursor moves down
+@LI{count - 1}lines.
+@sp 1
+It is not an error to use the
+@CO{$}
+command when the cursor is on the last character in the line or
+when the line is empty.
+@sp 1
+The
+@CO{$}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the cursor is at, or before the first
+nonblank character in the line, in which case it is line oriented.
+It is not an error to use the
+@CO{$}
+command as a motion component when the cursor is on the last character
+in the line, although it is an error when the line is empty.
+@table @asis
+@item Line:
+Set to the current line plus
+@LI{count}minus 1.
+@item Column:
+Set to the last character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex %
+@deftypefn Command {} {%}
+
+Move to the matching character.
+The cursor moves to the bracket character which
+@emph{matches}
+the bracket found at the current cursor position
+or which is the closest one to the right of the cursor on the line.
+The bracket characters are defined by the
+@OP{matchchars}
+option.
+An error will be reported if none of the
+@OP{matchchars}
+characters is found, or if no matching character is found.
+If the open and close brackes are identical (e.g.: if they are
+@QT{'}
+or
+@QT{"},
+then repeating a
+@CO{%}
+command will perform a backwards search from the original opening bracket.
+Historically, any
+@LI{count}specified to the
+@CO{%}
+command was ignored.
+@sp 1
+The
+@CO{%}
+command is an absolute movement.
+The
+@CO{%}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting point of the region is at
+or before the first nonblank character on its line, and the ending
+point is at or after the last nonblank character on its line, in
+which case it is line oriented.
+@table @asis
+@item Line:
+Set to the line containing the matching character.
+@item Column:
+Set to the matching character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex &
+@deftypefn Command {} {&}
+
+Repeat the previous substitution command on the current line.
+@sp 1
+Historically, any
+@LI{count}specified to the
+@CO{&}
+command was ignored.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged if the cursor was on the last character in the line,
+otherwise, set to the first nonblank character in the line.
+@item Options:
+Affected by the
+@OP{edcompatible},
+@OP{extended},
+@OP{ignorecase}
+and
+@OP{magic}
+options.
+@end table
+@end deftypefn
+@cindex SQUOTE<character>
+@deftypefn Command {} {'<character>}
+
+@cindex `<character>
+@deftypefnx Command {} `<character>
+Return to a context marked by the character
+@LI{<character>}.
+If
+@LI{<character>}is the
+@QT{'}
+or
+@QT{`}
+character, return to the previous context.
+If
+@LI{<character>}is any other character,
+return to the context marked by that character (see the
+@CO{m}
+command for more information).
+If the command is the
+@CO{\'}
+command, only the line value is restored,
+and the cursor is placed on the first nonblank character of that line.
+If the command is the
+@CO{`}
+command, both the line and column values are restored.
+@sp 1
+It is an error if the context no longer exists because of
+line deletion.
+(Contexts follow lines that are moved, or which are deleted
+and then restored.)
+@sp 1
+The
+@CO{\'}
+and
+@CO{`}
+commands are both absolute movements.
+They may be used as a motion component for other
+@CO{vi}
+commands.
+For the
+@CO{\'}
+command, any text copied into a buffer is line oriented.
+For the
+@CO{`}
+command,
+any text copied into a buffer is character oriented,
+unless it both starts and stops at the first character in the line,
+in which case it is line oriented.
+In addition, when using the
+@CO{`}
+command as a motion component,
+commands which move backward and started at the first character in the line,
+or move forward and ended at the first character in the line,
+are corrected to the last character of the line preceding the starting and
+ending lines, respectively.
+@table @asis
+@item Line:
+Set to the line from the context.
+@item Column:
+Set to the first nonblank character in the line, for the
+@CO{\'}
+command, and set to the context's column for the
+@CO{`}
+command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex (
+@deftypefn Command {} {[count] (}
+
+Back up
+@LI{count}sentences.
+@sp 1
+The
+@CO{(}
+command is an absolute movement.
+The
+@CO{(}
+command may be used as the motion component of other
+@CO{vi}
+commands,
+in which case any text copied into a buffer is character oriented,
+unless the starting and stopping points of the region are the first
+character in the line,
+in which case it is line oriented.
+If it is line oriented,
+the starting point of the region is adjusted to be the end of the line
+immediately before the starting cursor position.
+@table @asis
+@item Line:
+Set to the line containing the beginning of the sentence.
+@item Column:
+Set to the first nonblank character of the sentence.
+@item Options:
+Affected by the
+@OP{lisp}
+option.
+@end table
+@end deftypefn
+@cindex )
+@deftypefn Command {[count]} {)}
+
+Move forward
+@LI{count}sentences.
+@sp 1
+The
+@CO{)}
+command is an absolute movement.
+The
+@CO{)}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting point of the region is the
+first character in the line, in which case it is line oriented.
+In the latter case, if the stopping point of the region is also
+the first character in the line, it is adjusted to be the end of the
+line immediately before it.
+@table @asis
+@item Line:
+Set to the line containing the beginning of the sentence.
+@item Column:
+Set to the first nonblank character of the sentence.
+@item Options:
+Affected by the
+@OP{lisp}
+option.
+@end table
+@end deftypefn
+@cindex ,
+@deftypefn Command {[count]} {,}
+
+Reverse find character
+@LI{count}times.
+Reverse the last
+@CO{F},
+@CO{f},
+@CO{T}
+or
+@CO{t}
+command, searching the other way in the line,
+@LI{count}times.
+It is an error if a
+@CO{F},
+@CO{f},
+@CO{T}
+or
+@CO{t}
+command has not been performed yet.
+@sp 1
+The
+@CO{,}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the searched-for character for the
+@CO{F}
+and
+@CO{f}
+commands,
+before the character for the
+@CO{t}
+command
+and after the character for the
+@CO{T}
+command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex MINUSSIGN
+@deftypefn Command {[count]} {-}
+
+Move to the first nonblank of the previous line,
+@LI{count}times.
+@sp 1
+It is an error if the movement is past the beginning of the file.
+@sp 1
+The
+@CO{-}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to the current line minus
+@LI{count}.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex .
+@deftypefn Command {[count]} {.}
+
+Repeat the last
+@CO{vi}
+command that modified text.
+The repeated command may be a command and motion component combination.
+If
+@LI{count}is specified, it replaces
+@emph{both}
+the count specified for the repeated command, and, if applicable, for
+the repeated motion component.
+If
+@LI{count}is not specified, the counts originally specified to the command being
+repeated are used again.
+@sp 1
+As a special case, if the
+@CO{\.}
+command is executed immediately after the
+@CO{u}
+command, the change log is rolled forward or backward, depending on
+the action of the
+@CO{u}
+command.
+@table @asis
+@item Line:
+Set as described for the repeated command.
+@item Column:
+Set as described for the repeated command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex /RE/
+@deftypefn Command {} {/RE<carriage-return>}
+
+@deftypefnx Command {} {/RE/} {[offset]<carriage-return>}
+@cindex ?RE?
+@deftypefnx Command {}  {?RE<carriage-return>}
+@deftypefnx Command {} {?RE?} {[offset]<carriage-return>}
+@cindex N
+@deftypefnx Command  {} N
+@cindex n
+@deftypefnx Command  {} n
+Search forward or backward for a regular expression.
+The commands beginning with a slash
+@PQ{/}
+character are forward searches, the commands beginning with a
+question mark
+@PQ{?}
+are backward searches.
+@CO{Vi}
+prompts with the leading character on the last line of the screen
+for a string.
+It then searches forward or backward in the file for the next
+occurrence of the string, which is interpreted as a Basic Regular
+Expression.
+@sp 1
+The
+@CO{/}
+and
+@CO{?}
+commands are absolute movements.
+They may be used as the motion components of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the search started and ended on
+the first column of a line, in which case it is line oriented.
+In addition, forward searches ending at the first character of a line,
+and backward searches beginning at the first character in the line,
+are corrected to begin or end at the last character of the previous line.
+(Note, forward and backward searches can occur for both
+@CO{/}
+and
+@CO{?}
+commands, if the
+@OP{wrapscan}
+option is set.)
+@sp 1
+If an offset from the matched line is specified (i.e. a trailing
+@QT{/}
+or
+@QT{?}
+character is followed by a signed offset), the buffer will always
+be line oriented (e.g.
+@QT{/string/+0}
+will always guarantee a line orientation).
+@sp 1
+The
+@CO{N}
+command repeats the previous search, but in the reverse direction.
+The
+@CO{n}
+command repeats the previous search.
+If either the
+@CO{N}
+or
+@CO{n}
+commands are used as motion components for the 
+@CO{!}
+command, you will not be prompted for the text of the bang command,
+instead the previous bang command will be executed.
+@sp 1
+Missing RE's (e.g.
+@QT{//<carriage-return>},
+@QT{/<carriage-return>},
+@QT{??<carriage-return>},
+or
+@QT{?<carriage-return>}
+search for the last search RE, in the indicated direction.
+@sp 1
+Searches may be interrupted using the
+@LI{<interrupt>}character.
+@sp 1
+Multiple search patterns may be grouped together by delimiting
+them with semicolons and zero or more whitespace characters, e.g.
+@LI{/foo/ ; ?bar?}searches forward for
+@LI{foo}and then, from that location, backwards for
+@LI{bar}.
+When search patterns are grouped together in this manner,
+the search patterns are evaluated left to right with the
+final cursor position determined by the last search pattern.
+@sp 1
+It is also permissible to append a
+@CO{z}
+command to the search strings, e.g.
+@LI{/foo/ z.}searches forward for the next occurrence of
+@LI{foo},
+and then positions that line in the middle of screen.
+@table @asis
+@item Line:
+Set to the line in which the match occurred.
+@item Column:
+Set to the first character of the matched string.
+@item Options:
+Affected by the
+@OP{edcompatible},
+@OP{extended},
+@OP{ignorecase},
+@OP{magic},
+and
+@OP{wrapscan}
+options.
+@end table
+@end deftypefn
+@cindex 0
+@deftypefn Command {} {0}
+
+Move to the first character in the current line.
+It is not an error to use the
+@CO{0}
+command when the cursor is on the first character in the line,
+@sp 1
+The
+@CO{0}
+command may be used as the motion component of other
+@CO{vi}
+commands,
+in which case it is an error if the cursor is on the first character
+in the line,
+and any text copied into a buffer is character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the first character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex :
+@deftypefn Command {} {:}
+
+Execute an
+@CO{ex}
+command.
+@CO{Vi}
+prompts for an
+@CO{ex}
+command on the last line of the screen, using a colon
+@PQ{:}
+character.
+The command is terminated by a
+@LI{<carriage-return>},
+@LI{<newline>}or
+@LI{<escape>}character; all of these characters may be escaped by using a
+@LI{<literal-next>}character.
+The command is then executed.
+@sp 1
+If the
+@CO{ex}
+command writes to the screen,
+@CO{vi}
+will prompt the user for a
+@LI{<carriage-return>}before continuing
+when the
+@CO{ex}
+command finishes.
+Large amounts of output from the
+@CO{ex}
+command will be paged for the user, and the user prompted for a
+@LI{<carriage-return>}or
+@LI{<space>}key to continue.
+In some cases, a quit (normally a
+@QQ{q}
+character) or
+@LI{<interrupt>}may be entered to interrupt the
+@CO{ex}
+command.
+@sp 1
+When the
+@CO{ex}
+command finishes, and the user is prompted to resume visual mode,
+it is also possible to enter another
+@QT{:}
+character followed by another
+@CO{ex}
+command.
+@table @asis
+@item Line:
+The current line is set as described for the
+@CO{ex}
+command.
+@item Column:
+The current column is set as described for the
+@CO{ex}
+command.
+@item Options:
+Affected as described for the
+@CO{ex}
+command.
+@end table
+@end deftypefn
+@cindex ;
+@deftypefn Command {[count]} {;}
+
+Repeat the last character find
+@LI{count}times.
+The last character find is one of the
+@CO{F},
+@CO{f},
+@CO{T}
+or
+@CO{t}
+commands.
+It is an error if a
+@CO{F},
+@CO{f},
+@CO{T}
+or
+@CO{t}
+command has not been performed yet.
+@sp 1
+The
+@CO{;}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the searched-for character for the
+@CO{F}
+and
+@CO{f}
+commands,
+before the character for the
+@CO{t}
+command
+and after the character for the
+@CO{T}
+command.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex <
+@deftypefn Command {[count]} {< motion}
+
+@cindex >
+@deftypefnx Command  {[count]} {>} {motion}
+Shift lines left or right.
+Shift the number of lines in the region specified by the
+@LI{count}and
+@LI{motion}left (for the
+@CO{<}
+command) or right (for the
+@CO{>}
+command) by the number of columns specified by the
+@OP{shiftwidth}
+option.
+Only whitespace characters are deleted when shifting left.
+Once the first character in the line no longer contains a whitespace
+character, the command will succeed,
+but the line will not be modified.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+Affected by the
+@OP{shiftwidth}
+option.
+@end table
+@end deftypefn
+@cindex @@
+@deftypefn Command {} {@@} {buffer}
+
+Execute a named buffer.
+Execute the named buffer as
+@CO{vi}
+commands.
+The buffer may include
+@CO{ex}
+commands, too, but they must be expressed as a
+@CO{:}
+command.
+If the buffer is line oriented,
+@LI{<newline>}characters are logically appended to each line of the buffer.
+If the buffer is character oriented,
+@LI{<newline>}characters are logically appended to all but the last line in the buffer.
+@sp 1
+If the buffer name is
+@QT{@@},
+or
+@QT{*},
+then the last buffer executed shall be used.
+It is an error to specify
+@QT{@@@@}
+or
+@QT{@@*}
+if there were no previous buffer executions.
+The text of a buffer may contain a
+@CO{@@}
+command,
+and it is possible to create infinite loops in this manner.
+(The
+@LI{<interrupt>}character may be used to interrupt the loop.)
+@table @asis
+@item Line:
+The current line is set as described for the command(s).
+@item Column:
+The current column is set as described for the command(s).
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex A
+@deftypefn Command {[count]} {A}
+
+Enter input mode, appending the text after the end of the line.
+If
+@LI{count}is specified, the text is repeatedly input
+@LI{count - 1}more times after input mode is exited.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex B
+@deftypefn Command {[count]} {B}
+
+Move backward
+@LI{count}bigwords.
+Move the cursor backward to the beginning of a bigword by repeating the
+following algorithm: if the current position is at the beginning of a
+bigword or the character at the current position cannot be part of a bigword,
+move to the first character of the preceding bigword.
+Otherwise, move to the first character of the bigword at the current position.
+If no preceding bigword exists on the current line, move to the first
+character of the last bigword on the first preceding line that contains a
+bigword.
+@sp 1
+The
+@CO{B}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Set to the line containing the word selected.
+@item Column:
+Set to the first character of the word selected.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex C
+@deftypefn Command {[buffer]} {[count] C}
+
+Change text from the current position to the end-of-line.
+If
+@LI{count}is specified, the input text replaces from the current position to
+the end-of-line, plus
+@LI{count - 1}subsequent lines.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex D
+@deftypefn Command {[buffer]} {D}
+
+Delete text from the current position to the end-of-line.
+@sp 1
+It is not an error to execute the
+@CO{D}
+command on an empty line.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the character before the current character, or, column 1 if
+the cursor was on column 1.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex E
+@deftypefn Command {[count]} {E}
+
+Move forward
+@LI{count}end-of-bigwords.
+Move the cursor forward to the end of a bigword by repeating the
+following algorithm: if the current position is the end of a
+bigword or the character at that position cannot be part of a bigword,
+move to the last character of the following bigword.
+Otherwise, move to the last character of the bigword at the current
+position.
+If no succeeding bigword exists on the current line,
+move to the last character of the first bigword on the next following
+line that contains a bigword.
+@sp 1
+The
+@CO{E}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Set to the line containing the word selected.
+@item Column:
+Set to the last character of the word selected.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex F
+@deftypefn Command {[count]} {F} {<character>}
+
+Search
+@LI{count}times backward through the current line for
+@LI{<character>}.
+@sp 1
+The
+@CO{F}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the searched-for character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex G
+@deftypefn Command {[count]} {G}
+
+Move to line
+@LI{count},
+or the last line of the file if
+@LI{count}not specified.
+@sp 1
+The
+@CO{G}
+command is an absolute movement.
+The
+@CO{G}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to
+@LI{count},
+if specified, otherwise, the last line.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex H
+@deftypefn Command {[count]} {H}
+
+Move to the screen line
+@LI{count - 1}lines below the top of the screen.
+@sp 1
+The
+@CO{H}
+command is an absolute movement.
+The
+@CO{H}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to the line
+@LI{count - 1}lines below the top of the screen.
+@item Column:
+Set to the first nonblank character of the
+@emph{screen}
+line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex I
+@deftypefn Command {[count]} {I}
+
+Enter input mode, inserting the text at the beginning of the line.
+If
+@LI{count}is specified, the text input is repeatedly input
+@LI{count - 1}more times.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex J
+@deftypefn Command {[count]} {J}
+
+Join lines.
+If
+@LI{count}is specified,
+@LI{count}lines are joined; a minimum of two lines are always joined,
+regardless of the value of
+@LI{count}.
+@sp 1
+If the current line ends with a whitespace character, all whitespace
+is stripped from the next line.
+Otherwise, if the next line starts with a open parenthesis
+@PQ{(}
+do nothing.
+Otherwise, if the current line ends with a question mark
+@PQ{?},
+period
+@PQ{.}
+or exclamation point
+@PQ{!},
+insert two spaces.
+Otherwise, insert a single space.
+@sp 1
+It is not an error to join lines past the end of the file,
+i.e. lines that do not exist.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the character after the last character of the next-to-last
+joined line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex L
+@deftypefn Command {[count]} {L}
+
+Move to the screen line
+@LI{count - 1}lines above the bottom of the screen.
+@sp 1
+The
+@CO{L}
+command is an absolute movement.
+The
+@CO{L}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@table @asis
+@item Line:
+Set to the line
+@LI{count - 1}lines above the bottom of the screen.
+@item Column:
+Set to the first nonblank character of the
+@emph{screen}
+line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex  M
+@deftypefn Command {} {M}
+
+Move to the screen line in the middle of the screen.
+@sp 1
+The
+@CO{M}
+command is an absolute movement.
+The
+@CO{M}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@sp 1
+Historically, any
+@LI{count}specified to the
+@CO{M}
+command was ignored.
+@table @asis
+@item Line:
+Set to the line in the middle of the screen.
+@item Column:
+Set to the first nonblank character of the
+@emph{screen}
+line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex O
+@deftypefn Command {[count]} {O}
+
+Enter input mode, appending text in a new line above the current line.
+If
+@LI{count}is specified, the text input is repeatedly input
+@LI{count - 1}more times.
+@sp 1
+Historically, any
+@LI{count}specified to the
+@CO{O}
+command was ignored.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex P
+@deftypefn Command {[buffer]} {P}
+
+Insert text from a buffer.
+Text from the buffer (the unnamed buffer by default) is inserted
+before the current column or, if the buffer is line oriented,
+before the current line.
+@table @asis
+@item Line:
+Set to the lowest numbered line insert,
+if the buffer is line oriented, otherwise unchanged.
+@item Column:
+Set to the first nonblank character of the appended text,
+if the buffer is line oriented, otherwise, the last character
+of the appended text.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex Q
+@deftypefn Command {} {Q}
+
+Exit
+@CO{vi}
+(or visual) mode and switch to
+@CO{ex}
+mode.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+No longer relevant.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex R
+@deftypefn Command {[count]} {R}
+
+Enter input mode, replacing the characters in the current line.
+If
+@LI{count}is specified, the text input is repeatedly input
+@LI{count - 1}more times.
+@sp 1
+If the end of the current line is reached, no more characters are
+replaced and any further characters input are appended to the line.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex S
+@deftypefn Command {[buffer] [count]} {S}
+
+Substitute
+@LI{count}lines.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex T
+@deftypefn Command {[count]} {T} {<character>}
+
+Search backward,
+@LI{count}times,
+through the current line for the character
+@emph{after}
+the specified
+@LI{<character>}.
+@sp 1
+The
+@CO{T}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the character
+@emph{after}
+the searched-for character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex U
+@deftypefn Command {} {U}
+
+Restore the current line to its state before the cursor last
+moved to it.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+The first character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex W
+@deftypefn Command {[count]} {W}
+
+Move forward
+@LI{count}bigwords.
+Move the cursor forward to the beginning of a bigword by repeating the
+following algorithm: if the current position is within a bigword or the
+character at that position cannot be part of a bigword, move to the first
+character of the next bigword.
+If no subsequent bigword exists on the current line,
+move to the first character of the first bigword on the first following
+line that contains a bigword.
+@sp 1
+The
+@CO{W}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+The line containing the word selected.
+@item Column:
+The first character of the word selected.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex X
+@deftypefn Command {[buffer] [count]} {X}
+
+Delete
+@LI{count}characters before the cursor.
+If the number of characters to be deleted is greater than or equal to
+the number of characters to the beginning of the line, all of the
+characters before the current cursor position, to the beginning of the
+line, are deleted.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the current character minus
+@LI{count},
+or the first character if count is greater than the number of
+characters in the line before the cursor.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex Y
+@deftypefn Command {[buffer] [count]} {Y}
+
+Copy (or
+@QQ{yank})
+@LI{count}lines into the specified buffer.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex ZZ
+@deftypefn Command {} {ZZ}
+
+Write the file and exit
+@CO{vi}.
+The file is only written if it has been modified since the last
+complete write of the file to any file.
+@sp 1
+The
+@CO{ZZ}
+command will exit the editor after writing the file,
+if there are no further files to edit.
+Entering two
+@QQ{quit}
+commands (i.e.
+@CO{wq},
+@CO{quit},
+@CO{xit}
+or
+@CO{ZZ})
+in a row will override this check and the editor will exit,
+ignoring any files that have not yet been edited.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex [[
+@deftypefn Command {[count]} {[[}
+
+Back up
+@LI{count}section boundaries.
+@sp 1
+The
+@CO{[[}
+command is an absolute movement.
+The
+@CO{[[}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting position is column 0,
+in which case it is line oriented.
+@sp 1
+It is an error if the movement is past the beginning of the file.
+@table @asis
+@item Line:
+Set to the previous line that is
+@LI{count}section boundaries back,
+or the first line of the file if no more section boundaries exist
+preceding the current line.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+Affected by the
+@OP{sections}
+option.
+@end table
+@end deftypefn
+@cindex ]]
+@deftypefn Command {[count]} {]]}
+
+Move forward
+@LI{count}section boundaries.
+@sp 1
+The
+@CO{]]}
+command is an absolute movement.
+The
+@CO{]]}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting position is column 0,
+in which case it is line oriented.
+@sp 1
+It is an error if the movement is past the end of the file.
+@table @asis
+@item Line:
+Set to the line that is
+@LI{count}section boundaries forward,
+or to the last line of the file if no more section
+boundaries exist following the current line.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+Affected by the
+@OP{sections}
+option.
+@end table
+@end deftypefn
+@cindex ^
+@deftypefn Command {} {^}
+
+Move to first nonblank character on the current line.
+@sp 1
+The
+@CO{^}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the first nonblank character of the current line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex _
+@deftypefn Command {[count]} {_}
+
+Move down
+@LI{count - 1}lines, to the first nonblank character.
+The
+@CO{_}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+line oriented.
+@sp 1
+It is not an error to execute the
+@CO{_}
+command when the cursor is on the first character in the line.
+@table @asis
+@item Line:
+The current line plus
+@LI{count - 1}.
+@item Column:
+The first nonblank character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex a
+@deftypefn Command {[count]} {a}
+
+Enter input mode, appending the text after the cursor.
+If
+@LI{count}is specified, the text input is repeatedly input
+@LI{count - 1}more times.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex b
+@deftypefn Command {[count]} {b}
+
+Move backward
+@LI{count}words.
+Move the cursor backward to the beginning of a word by repeating the
+following algorithm: if the current position is at the beginning of a word,
+move to the first character of the preceding word.
+Otherwise, the current position moves to the first character of the word
+at the current position.
+If no preceding word exists on the current line, move to the first
+character of the last word on the first preceding line that contains
+a word.
+@sp 1
+The
+@CO{b}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Set to the line containing the word selected.
+@item Column:
+Set to the first character of the word selected.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex c
+@deftypefn Command {[buffer] [count]} {c} {motion}
+
+Change the region of text specified by the
+@LI{count}and
+@LI{motion}.
+If only part of a single line is affected, then the last character
+being changed is marked with a
+@QT{$}.
+Otherwise, the region of text is deleted, and input mode is entered.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex d
+@deftypefn Command {[buffer] [count]} {d} {motion}
+
+Delete the region of text specified by the
+@LI{count}and
+@LI{motion}.
+@table @asis
+@item Line:
+Set to the line where the region starts.
+@item Column:
+Set to the first character in the line after the last character in the
+region.
+If no such character exists, set to the last character before the region.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex e
+@deftypefn Command {[count]} {e}
+
+Move forward
+@LI{count}end-of-words.
+Move the cursor forward to the end of a word by repeating the following
+algorithm: if the current position is the end of a word,
+move to the last character of the following word.
+Otherwise, move to the last character of the word at the current position.
+If no succeeding word exists on the current line, move to the last character
+of the first word on the next following line that contains a word.
+@sp 1
+The
+@CO{e}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Set to the line containing the word selected.
+@item Column:
+Set to the last character of the word selected.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex f
+@deftypefn Command {[count]} {f} {<character>}
+
+Search forward,
+@LI{count}times, through the rest of the current line for
+@LI{<character>}.
+@sp 1
+The
+@CO{f}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the searched-for character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex i
+@deftypefn Command {[count]} {i}
+
+Enter input mode, inserting the text before the cursor.
+If
+@LI{count}is specified, the text input is repeatedly input
+@LI{count - 1}more times.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex m
+@deftypefn Command {} {m} {<character>}
+
+Save the current context (line and column) as
+@LI{<character>}.
+The exact position is referred to by
+@QT{`<character>}.
+The line is referred to by
+@QT{'<character>}.
+@sp 1
+Historically,
+@LI{<character>}was restricted to lower-case letters.
+@CO{Nvi}
+permits the use of any character.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex o
+@deftypefn Command {[count]} {o}
+
+Enter input mode, appending text in a new line under the current line.
+If
+@LI{count}is specified, the text input is repeatedly input
+@LI{count - 1}more times.
+@sp 1
+Historically, any
+@LI{count}specified to the
+@CO{o}
+command was ignored.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex p
+@deftypefn Command {[buffer]} {p}
+
+Append text from a buffer.
+Text from the buffer (the unnamed buffer by default) is appended
+after the current column or, if the buffer is line oriented,
+after the current line.
+@table @asis
+@item Line:
+Set to the first line appended, if the buffer is line oriented,
+otherwise unchanged.
+@item Column:
+Set to the first nonblank character of the appended text if the buffer
+is line oriented, otherwise, the last character of the appended text.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex r
+@deftypefn Command {[count]} {r} {<character>}
+
+Replace characters.
+The next
+@LI{count}characters in the line are replaced with
+@LI{<character>}.
+Replacing characters with
+@LI{<newline>}characters results in creating new, empty lines into the file.
+@sp 1
+If
+@LI{<character>}is
+@LI{<escape>},
+the command is cancelled.
+@table @asis
+@item Line:
+Unchanged unless the replacement character is a
+@LI{<newline>},
+in which case it is set to the current line plus
+@LI{count - 1}.
+@item Column:
+Set to the last character replaced,
+unless the replacement character is a
+@LI{<newline>},
+in which case the cursor is in column 1 of the last line inserted.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex s
+@deftypefn Command {[buffer] [count]} {s}
+
+Substitute
+@LI{count}characters in the current line starting with the current character.
+@table @asis
+@item Line:
+Set to the last line upon which characters were entered.
+@item Column:
+Set to the last character entered.
+@item Options:
+Affected by the
+@OP{altwerase},
+@OP{autoindent},
+@OP{beautify},
+@OP{showmatch},
+@OP{ttywerase}
+and
+@OP{wrapmargin}
+options.
+@end table
+@end deftypefn
+@cindex t
+@deftypefn Command {[count]} {t} {<character>}
+
+Search forward,
+@LI{count}times, through the current line for the character immediately
+@emph{before}
+@LI{<character>}.
+@sp 1
+The
+@CO{t}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the character
+@emph{before}
+the searched-for character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex u
+@deftypefn Command {} {u}
+
+Undo the last change made to the file.
+If repeated, the
+@CO{u}
+command alternates between these two states, and is its own inverse.
+When used after an insert that inserted text on more than one line,
+the lines are saved in the numeric buffers.
+@sp 1
+The
+@CO{.}
+command, when used immediately after the
+@CO{u}
+command, causes the change log to be rolled forward or backward,
+depending on the action of the
+@CO{u}
+command.
+@table @asis
+@item Line:
+Set to the position of the first line changed, if the reversal affects
+only one line or represents an addition or change; otherwise, the line
+preceding the deleted text.
+@item Column:
+Set to the cursor position before the change was made.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex w
+@deftypefn Command {[count]} {w}
+
+Move forward
+@LI{count}words.
+Move the cursor forward to the beginning of a word by repeating the
+following algorithm: if the current position is at the
+beginning of a word, move to the first character of the next word.
+If no subsequent word exists on the current line, move to the first
+character of the first word on the first following line that contains
+a word.
+@sp 1
+The
+@CO{w}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+@table @asis
+@item Line:
+Set to the line containing the word selected.
+@item Column:
+Set to the first character of the word selected.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex x
+@deftypefn Command {[buffer] [count]} {x}
+
+Delete
+@LI{count}characters.
+The deletion is at the current character position.
+If the number of characters to be deleted is greater than or equal to
+the number of characters to the end of the line, all of the characters
+from the current cursor position to the end of the line are deleted.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Unchanged unless the last character in the line is deleted and the cursor
+is not already on the first character in the line, in which case it is
+set to the previous character.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex y
+@deftypefn Command {[buffer] [count]} y {motion}
+
+Copy (or
+@QQ{yank})
+the text region specified by the
+@LI{count}and
+@LI{motion},
+into a buffer.
+@table @asis
+@item Line:
+Unchanged, unless the region covers more than a single line,
+in which case it is set to the line where the region starts.
+@item Column:
+Unchanged, unless the region covers more than a single line,
+in which case it is set to the character were the region starts.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex z
+@deftypefn Command {[count1]} {z} {[count2] type}
+
+Redraw the screen with a window
+@LI{count2}lines long, with line
+@LI{count1}placed as specified by the
+@LI{type}character.
+If
+@LI{count1}is not specified, it defaults to the current line.
+If
+@LI{count2}is not specified, it defaults to the current window size.
+@sp 1
+The following
+@LI{type}characters may be used:
+@table @asis
+@item +
+If
+@LI{count1}is specified, place the line
+@LI{count1}at the top of the screen.
+Otherwise, display the screen after the current screen, similarly to the
+@CO{<control-F>}
+command.
+@item <carriage-return>
+Place the line
+@LI{count1}at the top of the screen.
+@item .
+Place the line
+@LI{count1}in the center of the screen.
+@item -
+Place the line
+@LI{count1}at the bottom of the screen.
+@item ^
+If
+@LI{count1}is specified, place the line that is at the top of the screen 
+when
+@LI{count1}is at the bottom of the screen, at the bottom of the screen,
+i.e. display the screen before the screen before
+@LI{count1}.
+Otherwise, display the screen before the current screen, similarly to the
+@CO{<control-B>}
+command.
+@end table
+@table @asis
+@item Line:
+Set to
+@LI{count1}unless
+@LI{count1}is not specified and the
+@LI{type}character was either
+@QT{^}
+or
+@QT{+},
+in which case it is set to the line before the first line on the
+previous screen or the line after the last line on the previous
+screen, respectively.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex @{
+@deftypefn Command {[count]} @{
+
+Move backward
+@LI{count}paragraphs.
+@sp 1
+The
+@strong{@{}
+command is an absolute movement.
+The
+@strong{@{}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting character is the first
+character on its line, in which case it is line oriented.
+@table @asis
+@item Line:
+Set to the line containing the beginning of the previous paragraph.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+Affected by the
+@OP{paragraph}
+option.
+@end table
+@end deftypefn
+@cindex |
+@deftypefn Command {[count]} {|}
+
+Move to a specific
+@emph{column}
+position on the current line.
+@sp 1
+The
+@CO{|}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented.
+It is an error to use the
+@CO{|}
+command as a motion component and for the cursor not to move.
+@table @asis
+@item Line:
+Unchanged.
+@item Column:
+Set to the character occupying the column position identified by
+@LI{count},
+if the position exists in the line.
+If the column length of the current line is less than
+@LI{count},
+the cursor is moved to the last character in the line.
+@item Options:
+None.
+@end table
+@end deftypefn
+@cindex @}
+@deftypefn Command {[count]} @}
+
+Move forward
+@LI{count}paragraphs.
+@sp 1
+The
+@strong{@}}
+command is an absolute movement.
+The
+@strong{@}}
+command may be used as the motion component of other
+@CO{vi}
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting character is at or
+before any nonblank characters in its line,
+in which case it is line oriented.
+@table @asis
+@item Line:
+Set to the line containing the beginning of the next paragraph.
+@item Column:
+Set to the first nonblank character in the line.
+@item Options:
+Affected by the
+@OP{paragraph}
+option.
+@end table
+@end deftypefn
+@cindex ~
+@deftypefn Command {[count]} {~}
+
+Reverse the case of the next
+@LI{count}character(s).
+This is the historic semantic for the
+@CO{~}
+command and it is only in effect if the
+@OP{tildeop}
+option is not set.
+@sp 1
+Lowercase alphabetic characters are changed to uppercase,
+and uppercase characters are changed to lowercase.
+No other characters are affected.
+@sp 1
+Historically, the
+@CO{~}
+command did not take an associated count, nor did it move past the
+end of the current line.
+As it had no associated motion it was difficult to change the case
+of large blocks of text.
+In
+@CO{nvi},
+if the cursor is on the last character of a line, and there are
+more lines in the file, the cursor moves to the next line.
+@sp 1
+It is not an error to specify a count larger than the number of
+characters between the cursor and the end of the file.
+@table @asis
+@item Line:
+Set to the line of the character after
+@LI{count}characters, or, end of file.
+@item Column:
+Set to the character after
+@LI{count}characters, or, end-of-file.
+@item Options:
+Affected by the
+@OP{tildeop}
+option.
+@end table
+@end deftypefn
+@cindex ~
+@deftypefn Command {[count]} {~} {motion}
+
+Reverse the case of the characters in a text region specified by the
+@LI{count}and
+@LI{motion}.
+Only in effect if the
+@OP{tildeop}
+option is set.
+@sp 1
+Lowercase characters are changed to uppercase,
+and uppercase characters are changed to lowercase.
+No other characters are affected.
+@table @asis
+@item Line:
+Set to the line of the character after the last character in the region.
+@item Column:
+Set to the character after the last character in the region.
+@item Options:
+Affected by the
+@OP{tildeop}
+option.
+@end table
+@end deftypefn
+@cindex <interrupt>
+@deftypefn Command {} {<interrupt>}
+
+Interrupt the current operation.
+Many of the potentially long-running
+@CO{vi}
+commands may be interrupted using the terminal interrupt character.
+These operations include searches, file reading and writing, filter
+operations and map character expansion.
+Interrupts are also enabled when running commands outside of
+@CO{vi}.
+@sp 1
+If the
+@LI{<interrupt>}character is used to interrupt while entering an
+@CO{ex}
+command, the command is aborted, the cursor returns to its previous
+position, and
+@CO{vi}
+remains in command mode.
+@sp 1
+Generally, if the
+@LI{<interrupt>}character is used to interrupt any
+operation, any changes made before the interrupt are left in place.
+@table @asis
+@item Line:
+Dependent on the operation being interrupted.
+@item Column:
+Dependent on the operation being interrupted.
+@item Options:
+None.
+@end table
+@end deftypefn
+@chapter Vi Text Input Commands
+
+The following section describes the commands available in the text
+input mode of the
+@CO{vi}
+editor.
+
+Historically,
+@CO{vi}
+implementations only permitted the characters inserted on the current
+line to be erased.
+In addition, only the
+@LI{<control-D>}erase character and the
+@QT{0<control-D>}
+and
+@QT{^<control-D>}
+erase strings could erase autoindent characters.
+(Autoindent characters include both the characters inserted automatically
+at the beginning of an input line as well as characters inserted using the
+@LI{<control-T>}command.)
+This implementation permits erasure to continue past the beginning
+of the current line, and back to where text input mode was entered.
+In addition, autoindent characters may be erased using the standard
+erase characters.
+For the line and word erase characters, reaching the autoindent
+characters forms a
+@QQ{soft}
+boundary, denoting the end of the current word or line erase.
+Repeating the word or line erase key will erase the autoindent characters.
+
+Historically,
+@CO{vi}
+always used
+@LI{<control-H>}and
+@LI{<control-W>}as character and word erase characters, respectively, regardless of
+the current terminal settings.
+This implementation accepts, in addition to these two characters,
+the current terminal characters for those operations.
+@cindex <nul>
+@deftypefn Input {} {<nul>}
+
+If the first character of the input is a
+@LI{<nul>},
+the previous input is replayed, as if just entered.
+@end deftypefn
+@cindex <control-D>
+@deftypefn Input {} {<control-D>}
+
+If the previous character on the line was an autoindent character,
+erase characters to move the cursor back to the column immediately
+after the previous (1-based) column which is a multiple of the
+@OP{shiftwidth}
+edit option.
+This may result in any number of
+@LI{<tab>}and
+@LI{<space>}characters preceding the cursor being changed.
+@sp 1
+Otherwise, if the
+@OP{autoindent}
+option is set and the user is entering the first character in the line,
+@LI{<control-D>}is ignored.
+Otherwise, a literal
+@LI{<control-D>}character is entered.
+@end deftypefn
+@cindex ^<control-D>
+@deftypefn Input {} {^<control-D>}
+
+If the previous character on the line was an autoindent character,
+erase all of the autoindent characters on the line.
+In addition, the autoindent level is reset to 0.
+@end deftypefn
+@cindex 0<control-D>
+@deftypefn Input {} {0<control-D>}
+
+If the previous character on the line was an autoindent character,
+erase all of the autoindent characters on the line.
+The autoindent level is not altered.
+@end deftypefn
+@cindex <control-T>
+@deftypefn Input {} {<control-T>}
+
+Insert sufficient
+@LI{<tab>}and
+@LI{<space>}characters to move the cursor forward to the column immediately
+after the next (1-based) column which is a multiple of the
+@OP{shiftwidth}
+edit option.
+This may result in any number of
+@LI{<tab>}and
+@LI{<space>}characters preceding the cursor being changed.
+@sp 1
+Historically,
+@CO{vi}
+did not permit the
+@LI{<control-T>}command to be used unless the cursor was at the first column of a new
+line or it was preceded only by autoindent characters.
+@CO{Nvi}
+permits it to be used at any time during insert mode.
+@end deftypefn
+@cindex <erase>
+@deftypefn Input {} {<erase>}
+
+@cindex <control-H>
+@deftypefnx Input {} {<control-H>}
+Erase the last character.
+@end deftypefn
+@cindex "<literal-next>"
+@deftypefn Input {} {<literal-next>}
+
+Quote the next character.
+The next character will not be mapped (see the
+@CO{map}
+command for more information)
+or interpreted specially.
+A carat
+@PQ{^}
+character will be displayed immediately as a placeholder,
+but will be replaced by the next character.
+@end deftypefn
+@cindex <escape>
+@deftypefn Input {} {<escape>}
+
+If on the colon command line, and the
+@OP{filec}
+edit option is set, behave as described for that option.
+Otherwise, if on the colon command line,
+execute the command.
+Otherwise, if not on the colon command line,
+resolve all text input into the file, and return to command mode.
+@end deftypefn
+@cindex "<line erase>"
+@deftypefn Input {} {<line erase>}
+
+Erase the current line.
+@end deftypefn
+@cindex "<control-W>"
+@deftypefn Input {} {<control-W>}
+
+@cindex "<word erase>"
+@deftypefnx Input {}  {<word erase>}
+Erase the last word.
+The definition of word is dependent on the
+@OP{altwerase}
+and
+@OP{ttywerase}
+options.
+@end deftypefn
+@cindex "<control-X>"
+@deftypefn Input {} {<control-X>[0-9A-Fa-f]+}
+
+Insert a character with the specified hexadecimal value into the text.
+The value is delimited by any non-hexadecimal character or the input
+of the maximum number of characters that can be translated into a single
+character value.
+@end deftypefn
+@cindex <interrupt>
+@deftypefn Input {} {<interrupt>}
+
+Interrupt text input mode, returning to command mode.
+If the
+@LI{<interrupt>}character is used to interrupt inserting text into the file,
+it is as if the
+@LI{<escape>}character was used; all text input up to the interruption is
+resolved into the file.
+@end deftypefn
diff --git a/dist/nvi/docs/vi.ref/vi.texi b/dist/nvi/docs/vi.ref/vi.texi
new file mode 100644 (file)
index 0000000..964f2ba
--- /dev/null
@@ -0,0 +1,1829 @@
+\input texinfo
+@c $NetBSD: vi.texi,v 1.3 2011/11/13 19:53:53 wiz Exp $
+@setfilename vi.ref.info
+
+@setchapternewpage off
+@syncodeindex fn cp
+
+@comment  Copyright (c) 1994
+@comment      The Regents of the University of California.  All rights reserved.
+@comment  Copyright (c) 1994, 1995, 1996
+@comment       Keith Bostic.  All rights reserved.
+@comment 
+@comment  This document may not be republished without written permission from
+@comment  Keith Bostic. 
+@comment 
+@comment  See the LICENSE file for redistribution information.
+@comment 
+@comment      Id: vi.texi,v 8.1 2001/08/18 20:43:50 skimo Exp (Berkeley) Date: 2001/08/18 20:43:50
+@comment 
+@comment 
+
+@dircategory Editors
+@direntry
+* vi: (vi.info).                The vi editor.
+@end direntry
+
+@node Top,(dir),(dir),(dir)
+@menu
+* Vi Commands::
+* Ex Commands::
+@end menu
+@include ref.texi
+@titlepage
+@center @titlefont{Vi/Ex Reference Manual}
+@sp 1
+@center @emph{Keith Bostic}
+@sp 1
+@center Computer Science Division
+@center Department of Electrical Engineering and Computer Science
+@center University of California, Berkeley
+@center Berkeley, California  94720
+@sp 1
+@center @emph{Sven Verdoolaege}
+@sp 1
+@center @today
+@sp 3
+@center @emph{Abstract}
+
+This document is the reference guide for the 4.4BSD
+implementations of
+@EV{nex,nvi},
+which are implementations of the historic Berkeley
+@EV{ex,vi}
+editors.
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991, 1992, 1993, 1994@*
+@hskip 2cm The Regents of the University of California.  All Rights Reserved.@*
+Copyright @copyright{} 1991, 1992, 1993, 1994, 1995, 1996@*
+@hskip 2cm Keith Bostic.  All Rights Reserved.@*
+Copyright @copyright{} 2001@*
+@hskip 2cm Sven Verdoolaege.  All Rights Reserved.@*
+@page
+@center@emph{Acknowledgements}
+@sp 1
+
+Bruce Englar encouraged the early development of the historic
+@EV{ex,vi}
+editor.
+Peter Kessler helped bring sanity to version 2's command layout.
+Bill Joy wrote versions 1 and 2.0 through 2.7,
+and created the framework that users see in the present editor.
+Mark Horton added macros and other features and made
+@EV{ex,vi}
+work on a large number of terminals and Unix systems.
+
+@CO{Nvi}
+ is originally derived from software contributed to the University of
+California, Berkeley by Steve Kirkendall, the author of the
+@CO{vi}
+ clone
+@CO{elvis}.
+
+IEEE Standard Portable Operating System Interface for Computer
+Environments (POSIX) 1003.2 style Regular Expression support was
+done by Henry Spencer.
+
+The curses library was originally done by Ken Arnold.
+Scrolling and reworking for
+@CO{nvi}
+ was done by Elan Amir.
+
+George Neville-Neil added the Tcl interpreter,
+and Sven Verdoolaege added the Perl interpreter.
+
+Rob Mayoff added Cscope support.
+
+The Institute of Electrical and Electronics Engineers has
+given us permission to reprint portions of their documentation.
+Portions of this document are reprinted and reproduced from
+IEEE Std 1003.2-1992, IEEE Standard Portable Operating
+System Interface for Computer Environments (POSIX),
+copyright 1992 by the Institute of Electrical and Electronics
+Engineers, Inc.
+
+The financial support of UUNET Communications Services is gratefully
+acknowledged.
+@end titlepage
+@contents
+@chapter Description
+
+@CO{Vi}
+ is a screen oriented text editor.
+@CO{Ex}
+ is a line-oriented text editor.
+@CO{Ex}
+ and
+@CO{vi}
+ are different interfaces to the same program,
+and it is possible to switch back and forth during an edit session.
+@CO{View}
+ is the equivalent of using the
+@strong{-R}
+(read-only) option of
+@CO{vi}  .
+
+This reference manual is the one provided with the
+@EV{nex,nvi}
+versions of the
+@EV{ex,vi}
+text editors.
+@EV{Nex,nvi}
+are intended as bug-for-bug compatible replacements for the original
+Fourth Berkeley Software Distribution (4BSD)
+@EV{ex,vi}
+programs.
+This reference manual is accompanied by a traditional-style manual page.
+That manual page describes the functionality found in
+@EV{ex,vi}
+in far less detail than the description here.
+In addition, it describes the system interface to
+@EV{ex,vi},
+e.g. command line options, session recovery, signals,
+environmental variables, and similar things.
+
+This reference is intended for users already familiar with
+@EV{ex,vi}.
+Anyone else should almost certainly read a good tutorial on the
+editor first.
+If you are in an unfamiliar environment,
+and you absolutely have to get work done immediately,
+see the section entitled
+@QB{Fast Startup}
+in the manual page.
+It is probably enough to get you started.
+
+There are a few features in
+@EV{nex,nvi}
+that are not found in historic versions of
+@EV{ex,vi}.
+Some of the more interesting of those features are briefly described
+in the next section, entitled
+@QB{Additional Features} .
+For the rest of this document,
+@EV{nex,nvi}
+is used only when it is necessary to distinguish it from the historic
+implementations of
+@EV{ex,vi}.
+
+Future versions of this software will be periodically made available
+by anonymous ftp, and can be retrieved from
+@LI{ftp.cs.berkeley.edu},
+in the directory
+@LI{ucb/4bsd}.
+@chapter Additional Features in Nex/Nvi
+
+There are a few features in
+@EV{nex,nvi}
+that are not found in historic versions of
+@EV{ex,vi}.
+Some of the more interesting of these are as follows:
+@itemize @bullet
+@IP{8-bit clean data, large lines, files}
+
+@EV{Nex,nvi}
+will edit any format file.
+Line lengths are limited by available memory,
+and file sizes are limited by available disk space.
+The
+@CO{vi}
+ text input mode command
+@CO{<control-X>}
+ can insert any possible character value into the text.
+@IP{Background and foreground screens}
+
+The
+@CO{bg}
+ command backgrounds the current screen, and the
+@CO{fg}
+ command foregrounds backgrounded screens.
+The
+@CO{display}
+ command can be used to list the background screens.
+@IP{Command Editing}
+
+You can enter a normal editing window on the collected commands that
+you've entered on the
+@CO{vi}
+ colon command-line,
+and then modify and/or execute the commands.
+See the
+@OP{cedit}
+edit option for more information.
+@IP{Displays}
+
+The
+@CO{display}
+ command can be used to display the current buffers, the backgrounded
+screens, and the tags stack.
+@IP{Extended Regular Expressions}
+
+The
+@CO{extended}
+ option causes Regular Expressions to be interpreted as as Extended
+Regular Expressions, (i.e.@: @command{egrep}(1) style Regular Expressions).
+@IP{File Name Completion}
+
+It is possible to do file name completion and file name displays when
+entering commands on the
+@CO{vi}
+ colon command-line.
+See the
+@OP{filec}
+option for more information.
+@IP{Infinite undo}
+
+Changes made during an edit session may be rolled backward and forward.
+A
+@CO{.}
+ command immediately after a
+@CO{u}
+ command continues either forward or backward depending on whether the
+@CO{u}
+ command was an undo or a redo.
+@IP{Left-right scrolling}
+
+The
+@CO{leftright}
+ option causes
+@CO{nvi}
+ to do left-right screen scrolling, instead of the traditional
+@CO{vi}
+ line wrapping.
+@IP{Message Catalogs}
+
+It is possible to display informational and error messages in different
+languages by providing a catalog of messages.
+See the
+@OP{msgcat}
+option and the file
+@LI{catalog/README}for more information.
+@IP{Incrementing numbers}
+
+The
+@CO{#}
+ command increments or decrements the number referenced by the cursor.
+@IP{Previous file}
+
+The
+@CO{previous}
+ command edits the previous file from the argument list.
+@IP{Scripting languages}
+
+The
+@CO{:pe[rl] cmd},
+@CO{:perld[o] cmd}
+and
+@CO{:tc[l] cmd}
+commands execute Perl and Tcl/Tk commands, respectively,
+on lines from the edit buffer.
+See the
+@QB{Scripting Languages}
+section and the specific commands for more information.
+@comment @IP{Shell screens}
+
+@comment The
+@comment @CO{:sc[ript] [file ...]}
+@comment command runs a shell in the screen.
+@comment Editing is unchanged, with the exception that a \fC<carriage-return>\fP
+@comment enters the current line (stripped of any prompt) as input to the
+@comment shell.
+@IP{Split screens}
+
+The
+@CO{Edit}  ,
+@CO{Ex}  ,
+@CO{Next}  ,
+@CO{Previous}  ,
+@CO{Tag}
+ and
+@CO{Visual}
+ (in
+@CO{vi}
+ mode) commands divide the screen into multiple editing regions and
+then perform their normal function in a new screen area.
+The
+@CO{<control-W>}
+ command rotates between the foreground screens.
+The
+@CO{resize}
+ command can be used to grow or shrink a particular screen.
+@IP{Tag stacks}
+
+Tags are now maintained in a stack.
+The
+@CO{<control-T>}
+ command returns to the previous tag location.
+The
+@CO{tagpop}
+ command returns to the most recent tag location by default, or,
+optionally to a specific tag number in the tag stack,
+or the most recent tag from a specified file.
+The
+@CO{display}
+ command can be used to list the tags stack.
+The
+@CO{tagtop}
+ command returns to the top of the tag stack.
+@IP{Usage information}
+
+The
+@CO{exusage}
+ and
+@CO{viusage}
+ commands provide usage information for all of the
+@CO{ex}
+ and
+@CO{vi}
+ commands by default, or, optionally, for a specific command or key.
+@IP{Word search}
+
+The
+@CO{<control-A>}
+ command searches for the word referenced by the cursor.
+@end itemize
+@chapter Startup Information
+
+@EV{Ex,vi}
+interprets one of two possible environmental variables and reads up to
+three of five possible files during startup.
+The variables and files are expected to contain
+@CO{ex}
+ commands, not
+@CO{vi}
+ commands.
+In addition, they are interpreted
+@emph{before}
+the file to be edited is read, and therefore many
+@CO{ex}
+ commands may not be used.
+Generally, any command that requires output to the screen or that
+needs a file upon which to operate, will cause an error if included
+in a startup file or environmental variable.
+
+Because the
+@CO{ex}
+ command set supported by
+@EV{nex,nvi}
+is a superset of the command set supported by historical implementations of
+@CO{ex}  ,
+@EV{nex,nvi}
+can use the startup files created for the historical implementations,
+but the converse may not be true.
+
+If the
+@strong{-s}
+(the historic - option)
+is specified, or if standard input is redirected from a file,
+all environmental variables and startup files are ignored.
+
+Otherwise, startup files and environmental variables are handled
+in the following order:
+@enumerate
+@item
+The file
+@LI{/etc/vi.exrc}is read,
+as long as it is owned by root or the effective user ID of the user.
+@item
+The environmental variable
+@LI{NEXINIT}(or the variable
+@LI{EXINIT},
+if
+@LI{NEXINIT}is not set) is interpreted.
+@item
+If neither
+@LI{NEXINIT}or
+@LI{EXINIT}was set, and the
+@LI{HOME}environmental variable is set, the file
+@LI{$HOME/.nexrc}(or the file
+@LI{$HOME/.exrc},
+if
+@LI{$HOME/.nexrc}does not exist) is read,
+as long as the effective user ID of the user is root or is the same as
+the owner of the file.
+@sp 1
+When the $HOME directory is being used for both
+@EV{nex,nvi}
+and an historic implementation of
+@EV{ex,vi},
+a possible solution is to put
+@EV{nex,nvi}
+specific commands in the
+@LI{.nexrc}file, along with a
+@CO{:source $HOME/.exrc}
+command to read in the commands common to both implementations.
+@item
+If the
+@OP{exrc}
+option was turned on by one of the previous startup information
+sources, the file
+@LI{.nexrc}(or the file
+@LI{.exrc},
+if
+@LI{.nexrc}does not exist) is read, as long as the effective user ID of the user
+is the same as the owner of the file.
+@end enumerate
+
+No startup file is read if it is writable by anyone other than its owner.
+
+It is not an error for any of the startup environmental variables or files
+not to exist.
+
+Once all environmental variables are interpreted,
+and all startup files are read,
+the first file to be edited is read in (or a temporary file is created).
+Then, any commands specified using the
+@strong{-c}
+option are executed, in the context of that file.
+@chapter Recovery
+
+There is no recovery program for
+@EV{nex,nvi},
+nor does
+@EV{nex,nvi}
+run setuid.
+Recovery files are created readable and writable by the owner only.
+Users may recover any file which they can read,
+and the superuser may recover any edit session.
+
+Edit sessions are backed by files in the directory named by the
+@OP{recdir}
+option (the directory
+@LI{/var/tmp/vi.recover}by default), and are named
+@QC{vi.XXXXXX},
+where
+@QC{XXXXXX}
+is a number related to the process ID.
+When a file is first modified,
+a second recovery file containing an email message for the user is created,
+and is named
+@QC{recover.XXXXXX},
+where, again,
+@QC{XXXXXX}
+is associated with the process ID.
+Both files are removed at the end of a normal edit session,
+but will remain if the edit session is abnormally terminated
+or the user runs the
+@CO{ex}
+ @CO{preserve}
+ command.
+
+The
+@OP{recdir}
+option may be set in either the user's or system's startup information,
+changing the recovery directory.
+(Note, however, that if a memory based file system is used as the backup
+directory, each system reboot will delete all of the recovery files!
+The same caution applies to directories such as
+@LI{/tmp}which are cleared of their contents by a system reboot, or
+@LI{/usr/tmp}which is periodically cleared of old files on many systems.)
+
+The recovery directory should be owned by root, or at least by a pseudo-user.
+In addition, if directory
+@QQ{sticky-bit}
+semantics are available, the directory should have the sticky-bit
+set so that files may only be removed by their owners.
+The recovery directory must be read, write, and executable by any user,
+i.e.@: mode 1777.
+
+If the recovery directory does not exist,
+@EV{ex,vi}
+will attempt to create it.
+This can result in the recovery directory being owned by a normal user,
+which means that that user will be able to remove other user's recovery
+and backup files.
+This is annoying, but is not a security issue as the user cannot
+otherwise access or modify the files.
+
+The recovery file has all of the necessary information in it to enable the
+user to recover the edit session.
+In addition, it has all of the necessary email headers for
+@XR{sendmail,8}.
+When the system is rebooted, all of the files in
+@LI{/var/tmp/vi.recover}named
+@QC{recover.XXXXXX}
+should be sent to their owners, by email, using the
+@strong{-t}
+option of
+@CO{sendmail}
+ (or a similar mechanism in other mailers).
+If
+@EV{ex,vi}
+receives a hangup (SIGHUP) signal, or the user executes the
+@CO{ex}
+ @CO{preserve}
+ command,
+@EV{ex,vi}
+will automatically email the recovery information to the user.
+
+If your system does not have the
+@CO{sendmail}
+ utility (or a mailer program which supports its interface)
+the source file
+@LI{nvi/common/recover.c}will have to be modified to use your local mail delivery programs.
+Note, if
+@EV{nex,nvi}
+is changed to use another mailer,
+it is important to remember that the owner of the file given to
+the mailer is the
+@EV{nex,nvi}
+user, so nothing in the file should be trusted as it may have been
+modified in an effort to compromise the system.
+
+Finally, the owner execute bit is set on backup files when they are
+created, and unset when they are first modified, e.g. backup files
+that have no associated email recovery file will have this bit set.
+(There is also a small window where empty files can be created and
+not yet have this bit set.
+This is due to the method in which the files are created.)
+Such files should be deleted when the system reboots.
+
+A simple way to do this cleanup is to run the Bourne shell script
+@CO{recover}  ,
+from your
+@LI{/etc/rc.local}(or other system startup) file.
+The script should work with the historic Bourne shell,
+a POSIX 1003.2 shell or the Korn shell.
+The
+@CO{recover}
+ script is installed as part of the
+@EV{nex,nvi}
+installation process.
+
+Consult the manual page for details on recovering preserved or
+aborted editing sessions.
+@chapter Sizing the Screen
+
+The size of the screen can be set in a number of ways.
+@EV{Ex,vi}
+takes the following steps until values are obtained for both the
+number of rows and number of columns in the screen.
+@enumerate
+@item
+If the environmental variable
+@LI{LINES}exists,
+it is used to specify the number of rows in the screen.
+@item
+If the environmental variable
+@LI{COLUMNS}exists,
+it is used to specify the number of columns in the screen.
+@item
+The TIOCGWINSZ
+@XR{ioctl,2}
+is attempted on the standard error file descriptor.
+@item
+The termcap entry (or terminfo entry on System V machines)
+is checked for the
+@QQ{li}
+entry (rows) and the
+@QQ{co}
+entry (columns).
+@item
+The number of rows is set to 24, and the number of columns is set to 80.
+@end enumerate
+
+If a window change size signal (SIGWINCH) is received,
+the new window size is retrieved using the TIOCGWINSZ
+@XR{ioctl,2}
+call, and all other information is ignored.
+@chapter Character Display
+
+In both
+@CO{ex}
+ and
+@CO{vi}
+ printable characters as defined by
+@XR{isprint,3}
+are displayed using the local character set.
+
+Non-printable characters, for which
+@XR{iscntrl,3}
+returns true, and which are less than octal \e040,
+are displayed as the string
+@QT{^<character>},
+where
+@LI{<character>}is the character that is the original character's value offset from the
+@QT{@@}
+character.
+For example, the octal character \e001 is displayed as
+@QT{^A}.
+If
+@XR{iscntrl,3}
+returns true for the octal character \e177,
+it is displayed as the string
+@QT{^?}.
+All other characters are displayed as either hexadecimal values,
+in the form
+@QT{0x<high-halfbyte> ... 0x<low-halfbyte>},
+or as octal values, in the form
+@QT{\e<high-one-or-two-bits> ... \e<low-three-bits>}.
+The display of unknown characters is based on the value of the
+@OP{octal}
+option.
+
+In
+@CO{vi}
+ command mode, the cursor is always positioned on the last column of
+characters which take up more than one column on the screen.
+In
+@CO{vi}
+ text input mode, the cursor is positioned on the first column of
+characters which take up more than one column on the screen.
+@chapter Multiple Screens
+
+@CO{Nvi}
+ supports multiple screens by dividing the window into regions.
+It also supports stacks of screens by permitting the user to change
+the set of screens that are currently displayed.
+
+The
+@CO{Edit}  ,
+@CO{Ex}  ,
+@CO{Fg}  ,
+@CO{Next}  ,
+@CO{Previous}  ,
+@CO{Tag}
+ and
+@CO{Visual}
+ (in
+@CO{vi}
+ mode)
+commands divide the current screen into two regions of approximately
+equal size and then perform their usual action in a new screen area.
+If the cursor is in the lower half of the screen, the screen will split
+up, i.e.@: the new screen will be above the old one.
+If the cursor is in the upper half of the screen, the new screen will be
+below the old one.
+
+When more than one screen is editing a file, changes in any screen are
+reflected in all other screens editing the same file.
+Exiting a screen without saving any changes (or explicitly discarding
+them) is permitted until the last screen editing the file is exited,
+at which time the changes must be saved or discarded.
+
+The
+@CO{resize}
+ command permits resizing of individual screens.
+Screens may be grown, shrunk or set to an absolute number of rows.
+
+The
+@CO{^W}
+ command is used to switch between screens.
+Each
+@CO{^W}
+ moves to the next lower screen in the window, or to the first screen
+in the window if there are no lower screens.
+
+The
+@CO{bg}
+ command
+@QQ{backgrounds}
+the current screen.
+The screen disappears from the window,
+and the rows it occupied are taken over by a neighboring screen.
+It is an error to attempt to background the only screen in the window.
+
+The
+@CO{display screens}
+command displays the names of the files associated with the current
+backgrounded screens in the window.
+
+The
+@CO{fg [file]}
+command moves the specified screen from the list of backgrounded screens
+to the foreground.
+If no file argument is specified, the first screen on the list is
+foregrounded.
+By default,
+foregrounding consists of backgrounding the current screen,
+and replacing its space in the window with the foregrounded screen.
+
+Capitalizing the first letter of the command, i.e.@:
+@CO{Fg}  ,
+will foreground the backgrounded screen in a new screen instead of
+swapping it with the current screen.
+
+If the last foregrounded screen in the window is exited,
+and there are backgrounded screens,
+the first screen on the list of backgrounded screens takes over the window.
+@chapter Tags, Tag Stacks, and Cscope
+
+@CO{Nvi}
+ supports the historic
+@CO{vi}
+ tag command
+@CO{<control-]>}  ,
+and the historic
+@CO{ex}
+ tag command
+@CO{tag}  .
+These commands change the current file context to a new location,
+based on information found in the
+@LI{tags}files.
+If you are unfamiliar with these commands,
+you should review their description in the
+@CO{ex}
+ and
+@CO{vi}
+ commands section of this manual.
+For additional information on tags files,
+see the discussion of the
+@OP{tags}
+edit option and the system
+@XR{ctags,1}
+manual page.
+
+In addition,
+@CO{nvi}
+ supports the notion of
+@QQ{tags stacks},
+using the
+@CO{<control-T>}
+ command.
+The
+@CO{<control-T>}
+ command returns the user to the previous context, i.e.,
+the last place from which a
+@CO{<control-]>}
+ or
+@CO{tag}
+command was entered.
+These three commands provide the basic functionality which allows you
+to use
+@CO{vi}
+ to review source code in a structured manner.
+
+@CO{Nvi}
+ also provides two other basic
+@CO{ex}
+ commands for tag support:
+@CO{tagpop}
+ and
+@CO{tagtop}  .
+The
+@CO{tagpop}
+ command is identical to the
+@CO{<control-T>}
+ command,
+with the additional functionality that you may specify that modifications
+to the current file are to be discarded.
+This cannot be done using the
+@CO{<control-T>}
+ command.
+The
+@CO{tagtop}
+ command discards all of the contexts that have been pushed onto the tag
+stack, returning to the context from which the first
+@CO{<control-]>}
+ or
+@CO{tag}
+ command was entered.
+
+The historic
+@XR{ctags,1}
+tags file format supports only a single location per tag,
+normally the function declaration or structure or string definition.
+More sophisticated source code tools often provide multiple locations
+per tag, e.g.,
+a list of the places from which a function is called or a string
+definition is used.
+An example of this functionality is the System V source code tool,
+@CO{cscope}  .
+@sp 1
+@CO{Cscope}
+ creates a database of information on source code files,
+and supports a query language for that information as described in the
+@XR{cscope,1}
+manual page.
+@CO{Nvi}
+ contains an interface to the
+@CO{cscope}
+ query language which permits you to query
+@CO{cscope}
+ and then sequentially step through the locations in the sources files which
+@CO{cscope}
+ returns.
+There are two
+@CO{nvi}
+ commands which support this ability to step through multiple locations.
+They are the
+@CO{ex}
+ commands
+@CO{tagnext}
+ and
+@CO{tagprev}  .
+The
+@CO{tagnext}
+ command moves to the next location for the current tag.
+The
+@CO{tagprev}
+ command moves to the previous location for the current tag.
+(See the
+@CO{tagnext}
+ and
+@CO{tagprev}
+ command discussion in the
+@CO{ex}
+ commands section of this manual for more information.)
+At any time during this sequential walk,
+you may use the
+@CO{<control-]>}  ,
+@CO{tag}
+ or
+@CO{cscope}
+ commands to move to a new tag context, and then use the
+@CO{<control-T>}
+ or
+@CO{tagpop}
+ commands to return and continue stepping through the locations for this
+tag.
+This is similar to the previous model of a simple tag stack,
+except that each entry in the tag stack may have more than one file context
+that is of interest.
+
+Although there is no widely distributed version of
+@XR{ctags,1}
+that creates tags files with multiple locations per tag,
+@CO{nvi}
+ has been written to understand the obvious extension to the historic
+tags file format, i.e., more than a single line in the tags file with
+the same initial tag name.
+If you wish to extend your
+@CO{ctags}  
+implementation or other tool with which you build tags files,
+this extension should be simple and will require no changes to
+@CO{nvi}  .
+
+The
+@CO{nvi}
+ and
+@CO{cscope}
+ interface is based on the new
+@CO{ex}
+ command
+@CO{cscope}  ,
+which has five subcommands:
+@CO{add}  ,
+@CO{find}  ,
+@CO{help}  ,
+@CO{kill}
+ and
+@CO{reset}  .
+The subcommand
+@CO{find}
+ itself has eight subcommands:
+@CO{c}  ,
+@CO{d}  ,
+@CO{e}  ,
+@CO{f}  ,
+@CO{g}  ,
+@CO{i}  ,
+@CO{s}
+ and
+@CO{t}  .
+
+@itemize @bullet
+@IP{cs[cope] a[dd] file}
+
+The
+@CO{add}
+ command attaches to the specified
+@CO{cscope}
+ database.
+The file name is expanded using the standard filename expansions.
+If
+@CO{file}
+ is a directory, the file
+@QQ{cscope.out}
+in that directory is used as the database.
+
+After
+@CO{nvi}
+ attaches to a new database,
+all subsequent
+@CO{cscope}
+ queries will be asked of that database.
+The result of any single query is the collection of response to the query
+from all of the attached databases.
+@sp 1
+If the
+@QQ{CSCOPE_DIRS}
+environmental variable is set when
+@CO{nvi}
+ is run,
+it is expected to be a <colon> or <blank>-separated list of
+@CO{cscope}
+ databases or directories containing
+@CO{cscope}
+ databases, to which the user wishes to attach.
+@IP{:cs[cope] f[ind] c|d|e|f|g|i|s|t buffer|pattern}
+
+The
+@CO{find}
+ command is the
+@CO{cscope}
+ query command for
+@CO{nvi}  .
+For this command,
+@CO{nvi}
+ queries all attached
+@CO{cscope}
+ databases for the pattern.
+If the pattern is a double-quote character followed by a valid buffer
+name (e.g.,
+@LI{}"<character>" ), 
+then the contents of the named buffer are used as the pattern.
+Otherwise, the pattern is a Regular Expression.
+@sp 1
+The
+@CO{find}
+ command pushes the current location onto the tags stack,
+and switches to the first location resulting from the query,
+if the query returned at least one result.
+@sp 1
+File names returned by the
+@CO{cscope}
+ query, if not absolute paths, are searched for relative to the directory
+where the
+@CO{cscope}
+ database is located.
+In addition, if the file
+@QQ{cscope.tpath}
+appears in the same directory as the
+@CO{cscope}
+ database,
+it is expected to contain a colon-separated list of directory names
+where files referenced by its associated
+@CO{cscope}
+ database may be found.
+@sp 1
+The
+@CO{find}
+ subcommand is one of the following:
+@table @asis
+@item c
+Find callers of the name.
+@item d
+Find all function calls made from name.
+@item e
+Find pattern.
+@item f
+Find files with name as substring.
+@item g
+Find definition of name.
+@item i
+Find files #including name.
+@item s
+Find all uses of name.
+@item t
+Find assignments to name.
+@end table
+@IP{:cs[cope] h[elp] [command]}
+
+List the
+@CO{cscope}
+ commands,
+or optionally list usage help for any single
+@CO{cscope}
+ command.
+@IP{:display c[onnections]}
+
+Display the list of
+@CO{cscope}
+ databases to which
+@CO{nvi}
+ is currently connected.
+@IP{:cs[cope] k[ill] #}
+
+Disconnect from a specific
+@CO{cscope}
+ database.
+The connection number is the one displayed by the
+@CO{ex}
+ @CO{display connections}
+command.
+@IP{:cs[cope] r[eset]}
+
+Disconnect from all attached
+@CO{cscope}
+ databases.
+@end itemize
+
+Cscope is not freely redistributable software,
+but is fairly inexpensive and easily available.
+To purchase a copy of
+@CO{cscope}  ,
+see http://www.att.com/ssg/products/toolchest.html.
+@chapter Regular Expressions and Replacement Strings
+
+Regular expressions are used in line addresses,
+as the first part of the
+@CO{ex}
+ @CO{substitute}  ,
+@CO{global}  ,
+and
+@CO{v}
+ commands, and in search patterns.
+
+The regular expressions supported by
+@EV{ex,vi}
+are, by default, the Basic Regular Expressions (BRE's) described in the
+IEEE POSIX Standard 1003.2.
+The
+@OP{extended}
+option causes all regular expressions to be interpreted as the Extended
+Regular Expressions (ERE's) described by the same standard.
+(See
+@XR{re_format,7}
+for more information.)
+Generally speaking, BRE's are the Regular Expressions found in
+@XR{ed,1}
+and
+@XR{grep,1},
+and ERE's are the Regular Expressions found in
+@XR{egrep,1}.
+
+The following is not intended to provide a description of Regular
+Expressions.
+The information here only describes strings and characters which
+have special meanings in the
+@EV{ex,vi}
+version of RE's,
+or options which change the meanings of characters that normally
+have special meanings in RE's.
+@enumerate
+@item
+An empty RE (e.g.
+@QT{//}
+or
+@QT{??}
+is equivalent to the last RE used.
+@item
+The construct
+@QT{\e<}
+matches the beginning of a word.
+@item
+The construct
+@QT{\e>}
+matches the end of a word.
+@item
+The character
+@QT{~}
+matches the replacement part of the last
+@CO{substitute}
+ command.
+@end enumerate
+
+When the
+@OP{magic}
+option is
+@emph{not}
+set, the only characters with special meanings are a
+@QT{^}
+character at the beginning of an RE, a
+@QT{$}
+character at the end of an RE, and the escaping character
+@QT{\e}.
+The characters
+@QT{.},
+@QT{*},
+@QT{[}
+and
+@QT{~}
+are treated as ordinary characters unless preceded by a
+@QT{\e};
+when preceded by a
+@QT{\e}
+they regain their special meaning.
+
+Replacement strings are the second part of a
+@CO{substitute}
+ command.
+
+The character
+@QT{&}
+(or
+@QT{\e&}
+if the
+@OP{magic}
+option is
+@emph{not}
+set) in the replacement string stands for the text matched by the RE
+that is being replaced.
+The character
+@QT{~}
+(or
+@QT{\e~}
+if the
+@OP{magic}
+option is
+@emph{not}
+set) stands for the replacement part of the previous
+@CO{substitute}
+ command.
+It is only valid after a
+@CO{substitute}
+ command has been performed.
+
+The string
+@QT{\e#},
+where
+@QT{#}
+is an integer value from 1 to 9, stands for the text matched by
+the portion of the RE enclosed in the
+@QT{#}'th
+set of escaped parentheses, e.g.
+@QT{\e(}
+and
+@QT{\e)}.
+For example,
+@QT{s/abc\e(.*\e)def/\e1/}
+deletes the strings
+@QT{abc}
+and
+@QT{def}
+from the matched pattern.
+
+The strings
+@QT{\el},
+@QT{\eu},
+@QT{\eL}
+and
+@QT{\eU}
+can be used to modify the case of elements in the replacement string.
+The string
+@QT{\el}
+causes the next character to be converted to lowercase;
+the string
+@QT{\eu}
+behaves similarly, but converts to uppercase
+(e.g.
+@LI{s/abc/\eU&/}replaces the string
+@LI{abc}with
+@LI{ABC}).
+The string
+@QT{\eL}
+causes characters up to the end of the string or the next occurrence
+of the strings
+@QT{\ee}
+or
+@QT{\eE}
+to be converted to lowercase;
+the string
+@QT{\eU}
+behaves similarly, but converts to uppercase.
+
+If the entire replacement pattern is
+@QT{%},
+then the last replacement pattern is used again.
+
+In
+@CO{vi}  ,
+inserting a
+@LI{<control-M>}into the replacement string will cause
+the matched line to be split into two lines at that point.
+(The
+@LI{<control-M>}will be discarded.)
+@chapter Scripting Languages
+
+The
+@CO{nvi}
+ editor currently supports two scripting languages, Tcl/Tk and Perl.
+(Note that Perl4 isn't sufficient, and that the Perl5 used must be
+version 5.002 or later.
+See the
+@QB{Building Nvi}
+section for more information.
+
+The scripting language interface is still being worked on,
+therefore the following information is probably incomplete,
+probably wrong in cases, and likely to change.
+See the
+@LI{perl_api}and
+@LI{tcl_api}source directories for more information.
+As a quick reference, the following function calls are provided for
+both the Perl and Tcl interfaces.
+The Perl interface uses a slightly different naming convention,
+e.g. ``viFindScreen'' is named ``VI::FindScreen''.
+@itemize @bullet
+@IP{viFindScreen file}
+
+Return the
+@LI{screenId}associated with
+@LI{file}.
+@IP{viAppendLine screenId lineNumber text}
+
+Append
+@LI{text}as a new line after line number
+@LI{lineNumber},
+in the screen
+@LI{screenId}.
+@IP{viDelLine screenId lineNum}
+
+Delete the line
+@LI{lineNumber}from the screen
+@LI{screenId}.
+@IP{viGetLine screenId lineNumber}
+
+Return the line
+@LI{lineNumber}from the screen
+@LI{screenId}.
+@IP{viInsertLine screenId lineNumber text}
+
+Insert
+@LI{text}as a new line before line number
+@LI{lineNumber}in the screen
+@LI{screenId}.
+@IP{viLastLine screenId}
+
+Return the line number of the last line in the screen
+@LI{screenId}.
+@IP{viSetLine screenId lineNumber text}
+
+Change the line
+@LI{lineNumber}in the screen
+@LI{screenId}to match the specified
+@LI{text}.
+@IP{viGetMark screenId mark}
+
+Return the current line and column for the specified
+@LI{mark}from the screen
+@LI{screenId}.
+@IP{viSetMark screenId mark line column}
+
+Set the specified
+@LI{mark}to be at line
+@LI{line},
+column
+@LI{column},
+in the screen
+@LI{screenId}.
+@IP{viGetCursor screenId}
+
+Return the current line and column for the cursor in the screen
+@LI{screenId}.
+@IP{viSetCursor screenId line column}
+
+Set the cursor in the screen
+@LI{screenId}to the specified
+@LI{line}and
+@LI{column}.
+@IP{viMsg screenId text}
+
+Display the specified
+@LI{text}as a vi message in the screen
+@LI{screenId}.
+@IP{viNewScreen screenId [file]}
+
+Create a new screen.
+@IP{viEndScreen screenId}
+
+Exit the screen 
+@LI{screenId}.
+@IP{viSwitchScreen screenId screenId}
+
+Switch from the screen
+@LI{screenId}to the screen
+@LI{screenId}.
+@IP{viMapKey screenId key tclproc}
+
+Map the specified
+@LI{key}in the screen
+@LI{screenId}to the Tcl procedure
+@LI{tclproc}.
+@IP{viUnmMapKey screenId key}
+
+Unmap the specified
+@LI{key}in the screen
+@LI{screenId}@IP{viGetOpt screenId option}
+
+Return the value of the specified
+@LI{option}from the screen
+@LI{screenId}.
+@IP{viSetOpt screenId command}
+
+Set one or more options in the screen
+@LI{screenId}.
+@end itemize
+@chapter General Editor Description
+
+When
+@CO{ex}
+ or
+@CO{vi}
+ are executed,
+the text of a file is read (or a temporary file is created),
+and then all editing changes happen within the context of the
+copy of the file.
+@emph{No changes affect the actual file until the file is written out},
+either using a write command or another command which is affected by the
+@OP{autowrite}
+option.
+
+All files are locked (using the
+@XR{flock,2}
+or
+@XR{fcntl,2}
+interfaces) during the edit session,
+to avoid inadvertently making modifications to multiple copies of the file.
+If a lock cannot be obtained for a file because it is locked by another
+process, the edit session is read-only (as if the
+@OP{readonly}
+option or the
+@strong{-R}
+flag had been specified).
+If a lock cannot be obtained for other reasons, the edit session will
+continue, but the file status information
+(see the
+@CO{<control-G>}
+ command) will reflect this fact.
+
+Both
+@CO{ex}
+ and
+@CO{vi}
+ are modeful editors, i.e.@: they have two modes,
+@QQ{command}
+mode and
+@QQ{text input}
+mode.
+The former is intended to permit you to enter commands which modifies
+already existing text.
+The latter is intended to permit you to enter new text.
+When
+@CO{ex}
+ first starts running, it is in command mode, and usually displays a prompt
+(see the
+@OP{prompt}
+option for more information).
+The prompt is a single colon
+@PQ{:}
+character.
+There are three commands that switch
+@CO{ex}
+ into text input mode:
+@CO{append}  ,
+@CO{change}
+ and
+@CO{insert}  .
+Once in input mode, entering a line containing only a single period
+@PQ{.}
+ends text input mode and returns to command mode,
+where the prompt is redisplayed.
+
+When
+@CO{vi}
+ first starts running, it is in command mode as well.
+There are eleven commands that switch
+@CO{vi}
+ into text input mode:
+@CO{A}  ,
+@CO{a}  ,
+@CO{C}  ,
+@CO{c}  ,
+@CO{I}  ,
+@CO{i}  ,
+@CO{O}  ,
+@CO{o}  ,
+@CO{R}  ,
+@CO{S}
+ and
+@CO{s}  .
+Once in input mode, entering an
+@LI{<escape>}character ends text input mode and returns to command mode.
+
+@EV{Ex,vi}
+present three different interfaces to editing a file.
+@CO{Ex}
+ presents a line oriented interface.
+@CO{Vi}
+ presents a full screen display oriented interface,
+also known as
+@QQ{visual mode}.
+In addition, there is a third mode,
+@QQ{open mode},
+which is line oriented,
+but supports cursor movement and editing within the displayed line,
+similarly to visual mode.
+Open mode is not yet implemented in
+@CO{nvi}  .
+
+The following words have special meanings in both the
+@CO{ex}
+ and
+@CO{vi}
+ command descriptions:
+@itemize @bullet
+@cindex <interrupt>
+@IP{<interrupt>}
+
+The interrupt character is used to interrupt the current operation.
+Normally
+@LI{<control-C>},
+whatever character is set for the current terminal is used.
+@cindex "<literal-next>"
+@IP{<literal-next>}
+
+The literal next character is used to escape the subsequent character
+from any special meaning.
+This character is always
+@LI{<control-V>}.
+If the terminal is not set up to do XON/XOFF flow control,
+then
+@LI{<control-Q>}is used to mean literal next as well.
+@cindex "current pathname"
+@IP{current pathname}
+
+The pathname of the file currently being edited by vi.
+When the percent character
+@PQ{%}
+appears in a file name entered as part of an
+@CO{ex}
+ command argument, it is replaced by the current pathname.
+(The
+@QT{%}
+character can be escaped by preceding it with a backslash.)
+@cindex "alternate pathname"
+@IP{alternate pathname}
+
+The name of the last file name mentioned in an
+@CO{ex}
+ command, or,
+the previous current pathname if the last file mentioned
+becomes the current file.
+When the hash mark character
+@PQ{#}
+appears in a file name entered as part of an
+@CO{ex}
+ command argument, it is replaced by the alternate pathname.
+(The
+@QT{#}
+character can be escaped by preceding it with a backslash.)
+@cindex buffer
+@IP{buffer}
+
+One of a number of named areas for saving copies of text.
+Commands that change or delete text can save the changed or deleted
+text into a specific buffer, for later use, if the command allows
+it (i.e.@: the
+@CO{ex}
+ @CO{change}
+ command cannot save the changed text in a named buffer).
+Buffers are named with a single character, preceded by a double quote,
+e.g.
+@LI{}"<character>"
+in
+@CO{vi}
+ and
+without the double quote, e.g.
+@LI{<character>},
+in
+@CO{ex}  .
+(The double quote isn't necessary for
+@CO{ex}
+ because buffers names are denoted by their position in the command line.)
+Historic implementations of
+@EV{ex,vi}
+limited
+@LI{<character>}to the alphanumeric characters;
+@EV{nex,nvi}
+permits the use of any character without another meaning in the position
+where a buffer name is expected.
+@sp 1
+Buffers named by uppercase characters are the same as buffers
+named by lowercase characters, e.g. the buffer named by the
+English character
+@QT{A}
+is the same as the buffer named by the character
+@QT{a},
+with the exception that, if the buffer contents are being changed (as
+with a text deletion or
+@CO{vi}
+ @CO{change}
+ command), the text is
+@emph{appended}
+to the buffer, instead of replacing the current contents.
+@sp 1
+The buffers named by the numeric characters (in English,
+@QT{1}
+through
+@QT{9}),
+are special.
+If a region of text including characters from more than one line,
+or a single line of text specified by using a line-oriented motion,
+is changed or deleted in the file using the
+@CO{vi}
+ @CO{change}
+ or
+@CO{delete}
+ commands, a copy of the text is placed into the numeric buffer
+@QT{1},
+regardless of the user specifying another buffer in which to save it.
+In addition, there are a few commands which, when used as a
+@LI{motion}with the
+@CO{vi}
+ @CO{change}
+ and
+@CO{delete}
+ commands,
+@emph{always}
+copy the specified region of text into the numeric buffers regardless
+of the region including characters from more than one line.
+These commands are:
+@sp 1
+@multitable {@CO{'<character>}} {@CO{AA}} {@CO{AA}} {@CO{AA}}
+@item @CO{<control-A>} @tab @CO{%} @tab @CO{(} @tab @CO{)}
+@item @CO{`<character>} @tab @CO{/} @tab @CO{?} @tab @CO{N}
+@item @CO{n} @tab @strong{@{} @tab @strong{@}}
+@end multitable
+@sp 1
+Before this copy is done, the previous contents of buffer
+@QT{1}
+are moved into buffer
+@QT{2},
+@QT{2}
+into buffer
+@QT{3},
+and so on.
+The contents of buffer
+@QT{9}
+are discarded.
+In
+@CO{vi}  ,
+text may be explicitly stored into the numeric buffers.
+In this case, the buffer rotation described above occurs before the
+replacement of the buffer's contents.
+The numeric buffers are only available in
+@LI{visual}and
+@LI{open}modes,
+and are not accessible by
+@CO{ex}
+ in any way, although changed and deleted text is still stored there
+while in
+@CO{ex}
+ mode.
+@sp 1
+When a
+@CO{vi}
+ command synopsis shows both a
+@LI{[buffer]}and a
+@LI{[count]},
+they may be presented in any order.
+@sp 1
+Finally, all buffers are either
+@QQ{line}
+or
+@QQ{character}
+oriented.
+All
+@CO{ex}
+ commands which store text into buffers are line oriented.
+Some
+@CO{vi}
+ commands which store text into buffers are line oriented,
+and some are character oriented; the description for each applicable
+@CO{vi}
+ command notes whether text copied into buffers using the command
+is line or character oriented.
+In addition, the
+@CO{vi}
+ command
+@CO{display buffers}
+displays the current orientation for each buffer.
+Generally, the only importance attached to this orientation is that
+if the buffer is subsequently inserted into the text, line oriented
+buffers create new lines for each of the lines they contain, and
+character oriented buffers create new lines for any lines
+@emph{other}
+than the first and last lines they contain.
+The first and last lines are inserted into the text at the current
+cursor position, becoming part of the current line.
+If there is more than one line in the buffer, however, the current
+line itself will be split.
+@cindex "unnamed buffer"
+@IP{unnamed buffer}
+
+The unnamed buffer is a text storage area which is used by commands
+that use or operate on a buffer when no buffer is specified by the user.
+If the command stores text into a buffer,
+the text is stored into the unnamed buffer even if a buffer is also
+specified by the user.
+It is not possible to append text to the unnamed buffer.
+If text is appended to a named buffer,
+the named buffer contains both the old and new text,
+while the unnamed buffer contains only the new text.
+There is no way to explicitly reference the unnamed buffer.
+@sp 1
+Historically, the contents of the unnamed buffer were discarded by many
+different commands, even ones that didn't store text into it.
+@EV{Nex,nvi}
+never discards the contents of the unnamed buffer until new text
+replaces them.
+@cindex whitespace
+@IP{whitespace}
+
+The characters <tab> and <space>.
+@cindex "<carriage-return>"
+@IP{<carriage-return>}
+
+The character represented by an ASCII
+@LI{<control-M>}.
+This character is almost always treated identically to a
+@LI{<newline>}character, but differs in that it can be escaped into the file text or
+into a command.
+@cindex <newline>
+@IP{<newline>}
+
+The character represented by an ASCII
+@LI{<control-J>}.
+This character is almost always treated identically to a
+@LI{<control-M>}character, but differs in that it cannot be escaped into the file text or
+into a command.
+@end itemize
+@comment .oh 'Vi/Ex Reference (Vi Commands)''USD:13-%'
+@comment .eh 'USD:13-%''Vi/Ex Reference (Vi Commands)'
+@node Vi Commands,(dir),(dir),(dir)
+@include vi.cmd.texi
+@comment .oh 'Vi/Ex Reference''USD:13-%'
+@comment .eh 'USD:13-%''Vi/Ex Reference'
+@chapter Ex Addressing
+
+Addressing in
+@CO{ex}
+ (and when
+@CO{ex}
+ commands are executed from
+@CO{vi}  )
+relates to the current line.
+In general, the current line is the last line affected by a command.
+The exact effect on the current line is discussed under the description
+of each command.
+When the file contains no lines, the current line is zero.
+
+Addresses are constructed by one or more of the following methods:
+@enumerate
+@item
+The address
+@QT{.}
+refers to the current line.
+@item
+The address
+@QT{$}
+refers to the last line of the file.
+@item
+The address
+@QT{N},
+where
+@LI{N}is a positive number, refers to the N-th line of the file.
+@item
+The address
+@QT{'<character>}
+or
+@QT{`<character>}
+refers to the line marked with the name
+@LI{<character>}.
+(See the
+@CO{k}
+ or
+@CO{m}
+ commands for more information on how to mark lines.)
+@item
+A regular expression (RE) enclosed by slashes
+@PQ{/}
+is an address,
+and it refers to the first line found by searching forward from the line
+@emph{after}
+the current line toward the end of the file, and stopping at the
+first line containing a string matching the RE.
+(The trailing slash can be omitted at the end of the command line.)
+@sp 1
+If no RE is specified, i.e.@: the pattern is
+@QT{//},
+the last RE used in any command is used in the search.
+@sp 1
+If the
+@OP{extended}
+option is set, the RE is handled as an extended RE, not a basic RE.
+If the
+@OP{wrapscan}
+option is set, the search wraps around to the beginning of the file
+and continues up to and including the current line, so that the entire
+file is searched.
+@sp 1
+The form
+@QT{\e/}
+is accepted for historic reasons,
+and is identical to
+@QT{//}.
+@item
+An RE enclosed in question marks
+@PQ{?}
+addresses the first line found by searching backward from the line
+@emph{preceding}
+the current line, toward the beginning of the file and stopping at the
+first line containing a string matching the RE.
+(The trailing question mark can be omitted at the end of a command line.)
+@sp 1
+If no RE is specified, i.e.@: the pattern is
+@QT{??},
+the last RE used in any command is used in the search.
+@sp 1
+If the
+@OP{extended}
+option is set, the RE is handled as an extended RE, not a basic RE.
+If the
+@OP{wrapscan}
+option is set, the search  wraps around from the beginning of the file to
+the end of the file and continues up to and including the current line,
+so that the entire file is searched.
+@sp 1
+The form
+@QT{\e?}
+is accepted for historic reasons, and is identical to
+@QT{??}.
+@item
+An address followed by a plus sign
+@PQ{+}
+or a minus sign
+@PQ{-}
+followed by a number is an offset address and refers to the address
+plus (or minus) the indicated number of lines.
+If the address is omitted, the addition or subtraction is done with
+respect to the current line.
+@item
+An address of
+@QT{+}
+or
+@QT{-}
+followed by a number is an offset from the current line.
+For example,
+@QT{-5}
+is the same as
+@QT{.-5}.
+@item
+An address ending with
+@QT{+}
+or
+@QT{-}
+has 1 added to or subtracted from the address, respectively.
+As a consequence of this rule and of the previous rule, the address
+@QT{-}
+refers to the line preceding the current line.
+Moreover, trailing
+@QT{+}
+and
+@QT{-}
+characters have a cumulative effect.
+For example,
+@QT{++-++}
+refers to the current line plus 3.
+@item
+A percent sign
+@PQ{%}
+is equivalent to the address range
+@QT{1,$}.
+@end enumerate
+
+@CO{Ex}
+ commands require zero, one, or two addresses.
+It is an error to specify an address to a command which requires zero
+addresses.
+
+If the user provides more than the expected number of addresses to any
+@CO{ex}
+ command, the first addresses specified are discarded.
+For example,
+@QT{1,2,3,5}print
+prints lines 3 through 5, because the
+@CO{print}
+ command only takes two addresses.
+
+The addresses in a range are separated from each other by a comma
+@PQ{,}
+or a semicolon
+@PQ{;}.
+In the latter case, the current line
+@PQ{.}
+is set to the first address, and only then is the second address calculated.
+This feature can be used to determine the starting line for forward and
+backward searches (see rules (5) and (6) above).
+The second address of any two-address sequence corresponds to a line that
+follows, in the file, the line corresponding to the first address.
+The first address must be less than or equal to the second address.
+The first address must be greater than or equal to the first line of the
+file, and the last address must be less than or equal to the last line
+of the file.
+@comment .oh 'Vi/Ex Reference (Ex Commands)''USD:13-%'
+@comment .eh 'USD:13-%''Vi/Ex Reference (Ex Commands)'
+@node Ex Commands,(dir),(dir),(dir)
+@include ex.cmd.texi
+@comment .oh 'Vi/Ex Reference (Options)''USD:13-%'
+@comment .eh 'USD:13-%''Vi/Ex Reference (Options)'
+@include set.opt.texi
+@comment .oh 'Vi/Ex Reference''USD:13-%'
+@comment .eh 'USD:13-%''Vi/Ex Reference'
+@page
+@chapter Index
+@printindex cp
+@comment  Force the TOC to an odd page, in case it's a duplex printer.
+@bye
diff --git a/dist/nvi/docs/vitut/Makefile b/dist/nvi/docs/vitut/Makefile
new file mode 100644 (file)
index 0000000..5a1f195
--- /dev/null
@@ -0,0 +1,43 @@
+#      Id: Makefile,v 8.10 2001/01/28 15:50:08 skimo Exp (Berkeley) Date: 2001/01/28 15:50:08
+
+MACROS=        -ms
+ROFF=  groff
+TBL=   tbl
+
+all: vitut.ps summary.ps viapwh.ps ../html/vitut.html ../html/vi-summary.html \
+       ../html/viapwh.html
+
+vitut.ps: vi.in vi.chars
+       ${TBL} vi.in vi.chars | ${ROFF} ${MACROS} > $@
+       chmod 444 $@
+
+summary.ps: vi.summary
+       ${TBL} vi.summary | ${ROFF}  ${MACROS} > $@
+       chmod 444 $@
+
+viapwh.ps: vi.apwh.ms
+       ${TBL} vi.apwh.ms | ${ROFF} ${MACROS} > $@
+       chmod 444 $@
+
+../html/vitut.html: vi.in vi.chars
+       test -d ../html || mkdir ../html
+       ${TBL} $+ | ${ROFF} -ms -Thtml | \
+           sed 's/<img src=".*png">//' > $@
+       rm -f *png
+       chmod 444 $@
+
+../html/vi-summary.html: vi.summary
+       ${TBL} $< | ${ROFF} -ms -Thtml | \
+           sed 's/<img src="$<.*png">//' > $@
+       rm -f "$<"*png
+       chmod 444 $@
+
+../html/viapwh.html: vi.apwh.ms
+       ${TBL} $< | ${ROFF} -ms -Thtml | \
+           sed 's/<img src="$<.*png">//' > $@
+       rm -f "$<"*png
+       chmod 444 $@
+
+clean:
+       rm -f vitut.ps summary.ps viapwh.ps ../html/vitut.html \
+       ../html/vi-summary.html ../html/viapwh.html
diff --git a/dist/nvi/docs/vitut/vi.apwh.ms b/dist/nvi/docs/vitut/vi.apwh.ms
new file mode 100644 (file)
index 0000000..ac722ea
--- /dev/null
@@ -0,0 +1,1032 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: vi.apwh.ms,v 8.3 2001/01/28 13:48:01 skimo Exp (Berkeley) Date: 2001/01/28 13:48:01
+.\"
+.nr LL 6.5i
+.nr FL 6.5i
+.TL
+Vi Command & Function Reference
+.AU
+Alan P.W. Hewett
+.sp
+Revised for version 2.12 by Mark Horton
+.NH 1
+Author's Disclaimer
+.LP
+This document does not claim to be 100% complete.  There are a
+few commands listed in the original document that I was unable
+to test either because I do not speak \fBlisp\fR, because they
+required programs we don't have, or because I wasn't able to make
+them work.  In these cases I left the command out.  The commands
+listed in this document have been tried and are known to work.
+It is expected that prospective users of this document will read
+it once to get the flavor of everything that \fBvi\fR can do
+and then use it as a reference document.  Experimentation is
+recommended.  If you don't understand a command, try it and
+see what happens.
+.LP
+[Note: In revising this document, I have attempted to make it
+completely reflect version 2.12 of
+.B vi .
+It does not attempt to document the VAX version (version 3),
+but with one or two exceptions (wrapmargin, arrow keys)
+everything said about 2.12 should apply to 3.1.
+.I "Mark Horton" ]
+.NH 1
+Notation
+.LP
+\fB[option]\fR is used to denote optional parts of a command.
+Many \fBvi\fR commands have an optional count.  \fB[cnt]\fR
+means that an optional number may precede the command to
+multiply or iterate the command.
+\fB{variable item}\fR is used to denote parts of the command
+which must appear, but can take a number of different values.
+\fB<character [-character]>\fR means that the character or
+one of the characters in the range described between the
+two angle brackets is to be typed.
+For example \fB<esc>\fR means
+the \fBescape\fR key is to be typed.  \fB<a-z>\fR means that a
+lower case letter is to be typed.  \fB^<character>\fR means that
+the character is to be typed as a \fBcontrol\fR character, that is,
+with the \fB<cntl>\fR key held down while simultaneously typing
+the specified character.  In this document control characters will
+be denoted using the \fIupper case\fR character, but
+^<uppercase chr> and ^<lowercase chr> are equivalent.  That is, for
+example, \fB<^D>\fR is equal to \fB<^d>\fR.
+The most common character abbreviations
+used in this list are as follows:
+.IP <esc> 8
+escape, octal 033
+.IP <cr> 8
+carriage return, ^M, octal 015
+.IP <lf> 8
+linefeed ^J, octal 012
+.IP <nl> 8
+newline, ^J, octal 012 (same as linefeed)
+.IP <bs> 8
+backspace, ^H, octal 010
+.IP <tab> 8
+tab, ^I, octal 011
+.IP <bell> 8
+bell, ^G, octal 07
+.IP <ff> 8
+formfeed, ^L, octal 014
+.IP <sp> 8
+space, octal 040
+.IP <del> 8
+delete, octal 0177
+.sp 1
+.NH 1
+Basics
+.LP
+To run \fBvi\fR the shell variable \fBTERM\fR must be defined and
+exported to your environment.
+How you do this depends on which shell you are using.
+You can tell which shell you have by the character it
+prompts you for commands with.
+The Bourne shell prompts with `$', and the C shell prompts with `%'.
+For these examples, we will suppose
+that you are using an HP 2621 terminal, whose termcap name is ``2621''.
+.NH 2
+Bourne Shell
+.LP
+To manually set your terminal type to 2621 you would type:
+.DS
+TERM=2621
+export TERM
+.DE
+.PP
+There are various ways of having this automatically or
+semi-automatically done when you log in.
+Suppose you usually dial in on a 2621.
+You want to tell this to the machine, but still have it
+work when you use a hardwired terminal.
+The recommended way, if you have the
+.B tset
+program, is to use the sequence
+.DS
+tset \-s \-d 2621 > tset$$
+\&. tset$$
+rm tset$$
+.DE
+in your .login (for csh) or the same thing using `.' instead of `source'
+in your .profile (for sh).
+The above line says that if you are dialing in you are on a 2621,
+but if you are on a hardwired terminal it figures out your terminal
+type from an on-line list.
+.NH 2
+The C Shell
+.LP
+To manually set your terminal type to 2621 you would type:
+.DS
+setenv TERM 2621
+.DE
+.PP
+There are various ways of having this automatically or
+semi-automatically done when you log in.
+Suppose you usually dial in on a 2621.
+You want to tell this to the machine, but still have it
+work when you use a hardwired terminal.
+The recommended way, if you have the
+.B tset
+program, is to use the sequence
+.DS
+tset \-s \-d 2621 > tset$$
+source tset$$
+rm tset$$
+.DE
+in your .login.*
+.FS
+* On a version 6 system
+without environments, the invocation of tset
+is simpler, just add the line ``tset \-d 2621''
+to your .login or .profile.
+.FE
+The above line says that if you are dialing in you are on a 2621,
+but if you are on a hardwired terminal it figures out your terminal
+type from an on-line list.
+.NH 1
+Normal Commands
+.LP
+\fBVi\fR is a visual editor with a window on the file.  What
+you see on the screen is \fBvi\fR's current notion of
+what your file will contain,
+(at this point in the file),
+when it is written out.
+Most commands do not cause any change in the screen until the
+complete command is typed.  Should you get confused while
+typing a command, you can abort the command by typing an
+<del> character.  You will know you are back to command level
+when you hear a <bell>.  Usually typing an <esc> will produce the
+same result.  When \fBvi\fR gets an improperly formatted command
+it rings the <bell>.
+Following are the \fBvi\fR commands broken down by function.
+.NH 2
+Entry and Exit
+.LP
+To enter
+.B vi
+on a particular
+.I file ,
+type
+.DS
+\fBvi\fP \fIfile\fP
+.DE
+The file will be read in and the cursor will be placed at the beginning
+of the first line.
+The first screenfull of the file will be displayed on the terminal.
+.PP
+To get out of the editor, type
+.DS
+ZZ
+.DE
+If you are in some special mode, such as input mode
+or the middle of a multi-keystroke command, it may
+be necessary to type <esc> first.
+.NH 2
+Cursor and Page Motion
+.LP
+.B NOTE:
+The arrow keys (see the next four commands)
+on certain kinds of terminals will not work with the
+PDP-11 version of vi.  The control versions or the hjkl versions will
+work on any terminal.  Experienced users prefer the hjkl keys because
+they are always right under their fingers.  Beginners often prefer
+the arrow keys, since they do not require memorization of which hjkl
+key is which.
+The mnemonic value of hjkl is clear from looking at the keyboard of an adm3a.
+.sp
+.IP "[cnt]<bs> or [cnt]h or [cnt]\(<-" 16
+.br
+Move the cursor to the left one character.  Cursor stops at the left
+margin of the page.
+If cnt is given, these commands move that many spaces.
+.IP "[cnt]^N or [cnt]j or [cnt]\(da or [cnt]<lf>" 16
+.br
+Move down one line.
+Moving off the screen scrolls the window to force a new line
+onto the screen.
+Mnemonic: \fBN\fRext
+.IP "[cnt]^P or [cnt]k or [cnt]\(ua" 16
+.br
+Move up one line.
+Moving off the top of the screen forces new text onto the screen.
+Mnemonic: \fBP\fRrevious
+.IP "[cnt]<sp> or [cnt]l or [cnt]\(->" 16
+.br
+Move to the right one character.
+Cursor will not go beyond the end of the line.
+.IP [cnt]- 16
+Move the cursor up the screen to the beginning of the next line.
+Scroll if necessary.
+.IP "[cnt]+ or [cnt]<cr>" 16
+.sp 1
+Move the cursor down the screen to the beginning of the next line.
+Scroll up if necessary.
+.IP "[cnt]$" 16
+Move the cursor to the end of the line.
+If there is a count, move to the end of the line "cnt" lines
+forward in the file.
+.IP "^" 16
+Move the cursor to the beginning of the first word on the line.
+.IP "0" 16
+Move the cursor to the left margin of the current line.
+.IP "[cnt]|" 16
+Move the cursor to the column specified by the count.  The default is
+column zero.
+.IP "[cnt]w" 16
+Move the cursor to the beginning of the next word. If there
+is a count, then move forward that many words and
+position the cursor at the beginning of the word.
+Mnemonic: next-\fBw\fRord
+.IP "[cnt]W" 16
+Move the cursor to the beginning of the next word which follows
+a "white space" (<sp>,<tab>, or <nl>).  Ignore other punctuation.
+.IP "[cnt]b" 16
+Move the cursor to the preceding word.  Mnemonic: \fBb\fRackup-word
+.IP "[cnt]B" 16
+Move the cursor to the preceding word that is separated from the
+current word by a "white space" (<sp>,<tab>, or <nl>).
+.IP "[cnt]e" 16
+Move the cursor to the end of the current word or the end of the
+"cnt"'th word hence.  Mnemonic: \fBe\fRnd-of-word
+.IP "[cnt]E" 16
+Move the cursor to the end of the current word which is delimited by
+"white space" (<sp>,<tab>, or <nl>).
+.IP "[line number]G" 16
+.br
+Move the cursor to the line specified.  Of particular use are the
+sequences "1G" and "G", which move the cursor to the beginning and
+the end of the file respectively.  Mnemonic: \fBG\fRo-to
+.LP
+.B NOTE:
+The next four commands (^D, ^U, ^F, ^B)
+are not true motion commands, in that they
+cannot be used as the object of commands such as delete or change.
+.IP "[cnt]^D" 16
+Move the cursor down in the file by "cnt" lines (or the last "cnt"
+if a new count isn't given.  The initial default is half a page.)  The
+screen is simultaneously scrolled up.  Mnemonic: \fBD\fRown
+.IP "[cnt]^U" 16
+Move the cursor up in the file by "cnt" lines.  The screen is simultaneously
+scrolled down.  Mnemonic: \fBU\fRp
+.IP "[cnt]^F" 16
+Move the cursor to the next page.  A count moves that many pages.
+Two lines of the previous page are kept on the screen for continuity if
+possible.  Mnemonic: \fBF\fRorward-a-page
+.IP "[cnt]^B" 16
+Move the cursor to the previous page.  Two lines of the current page
+are kept if possible.  Mnemonic: \fBB\fRackup-a-page
+.IP "[cnt](" 16
+Move the cursor to the beginning of the next sentence.
+A sentence is defined as ending with a ".", "!", or "?"
+followed by two spaces or a <nl>.
+.IP "[cnt])" 16
+Move the cursor backwards to the beginning of a sentence.
+.IP "[cnt]}" 16
+Move the cursor to the beginning of the next paragraph.  This command
+works best inside \fBnroff\fR documents.  It understands two sets of
+\fBnroff\fR macros, \fB\-ms\fR and \fB\-mm\fR, for which the
+commands ".IP", ".LP", ".PP", ".QP", "P", as well as the nroff command ".bp"
+are considered to be paragraph delimiters.
+A blank line also delimits a paragraph.
+The \fBnroff\fR macros that it accepts as paragraph delimiters is
+adjustable.  See \fBparagraphs\fR under the \fBSet Commands\fR section.
+.IP "[cnt]{" 16
+Move the cursor backwards to the beginning of a paragraph.
+.IP "]]" 16
+Move the cursor to the next "section", where a section is defined by
+two sets of \fBnroff\fR macros, \fB\-ms\fR and \fB\-mm\fR, in which
+".NH", ".SH", and ".H" delimit a section.  A line beginning with a <ff><nl>
+sequence, or a line beginning with a "{" are also considered to
+be section delimiters.  The last option makes it
+useful for finding the beginnings of C functions.
+The \fBnroff\fR macros that are used for section delimiters can be adjusted.
+See \fBsections\fR under the \fBSet Commands\fR section.
+.IP "[[" 16
+Move the cursor backwards to the beginning of a section.
+.IP "%" 16
+Move the cursor to the matching parenthesis
+or brace.  This is very useful in C or lisp code.  If the
+cursor is sitting on a \fB( ) {\fR or \fB}\fR the cursor
+is moved to the matching character at the other end of the
+section.  If the cursor is not sitting on a brace or a
+parenthesis, \fBvi\fR searches forward until it finds one
+and then jumps to the match mate.
+.IP "[cnt]H" 16
+If there is no count move the cursor to the top left position on the screen.
+If there is a count, then move the cursor to the beginning of the line
+"cnt" lines from the top of the screen.  Mnemonic:  \fBH\fRome
+.IP "[cnt]L" 16
+If there is no count move the cursor to the beginning
+of the last line on the screen.
+If there is a count, then move the cursor to the beginning of the line
+"cnt" lines from the bottom of the screen.  Mnemonic: \fBL\fRast
+.IP "M" 16
+Move the cursor to the beginning of the middle line on the screen.
+Mnemonic: \fBM\fRiddle
+.IP "m<a-z>" 16
+This command does not move the cursor, but it \fBmarks\fR the place
+in the file and the character "<a-z>" becomes the label for referring
+to this location in the file.  See the next two commands.  Mnemonic:
+\fBm\fRark
+.B NOTE:
+The mark command is not a motion, and cannot be used as the target
+of commands such as delete.
+.IP "\(aa<a-z>" 16
+Move the cursor to the beginning of the line that is marked with the label
+"<a-z>".
+.IP "\(ga<a-z>" 16
+Move the cursor to the exact position on the line that was marked with
+with the label "<a-z>".
+.IP "\(aa\(aa" 16
+Move the cursor back to the beginning of the line where it was before the
+last "non-relative" move.  A "non-relative" move is something such as a
+search or a jump to a specific line in the file, rather than moving the
+cursor or scrolling the screen.
+.IP "\(ga\(ga" 16
+Move the cursor back to the exact spot on the line where it was located
+before the last "non-relative" move.
+.NH 2
+Searches
+.LP
+The following commands allow you to search for items in a file.
+.IP [cnt]f{chr} 16
+.sp 1
+Search forward on the line for the next or "cnt"'th occurrence of
+the character "chr".  The cursor is placed \fBat\fR the character
+of interest.  Mnemonic: \fBf\fRind character
+.IP [cnt]F{chr} 16
+.sp 1
+Search backwards on the line for the next or "cnt"'th occurrence of
+the character "chr".  The cursor is placed \fBat\fR the character
+of interest.
+.IP [cnt]t{chr} 16
+.sp 1
+Search forward on the line for the next or "cnt"'th occurrence of
+the character "chr".  The cursor is placed \fBjust preceding\fR
+the character of interest.  Mnemonic: move cursor up \fBt\fRo character
+.IP [cnt]T{chr} 16
+.sp 1
+Search backwards on the line for the next or "cnt"'th occurrence of
+the character "chr".  The cursor is placed \fBjust preceding\fR
+the character of interest.
+.IP "[cnt];" 16
+Repeat the last "f", "F", "t" or "T" command.
+.IP "[cnt]," 16
+Repeat the last "f", "F", "t" or "T" command, but in the opposite
+search direction.  This is useful if you overshoot.
+.IP "[cnt]/[string]/<nl>" 16
+.br
+Search forward for the next occurrence of "string".
+Wrap around at the end of the file
+does occur.
+The final \fB</>\fR is not required.
+.IP "[cnt]?[string]?<nl>" 16
+.br
+Search backwards for the next occurrence of "string".  If a count is
+specified, the count becomes the new window size.  Wrap around at the beginning
+of the file does occur.
+The final \fB<?>\fR is not required.
+.IP n 16
+Repeat the last /[string]/ or ?[string]? search.  Mnemonic: \fBn\fRext
+occurrence.
+.IP N 16
+Repeat the last /[string]/ or ?[string]? search, but in the reverse
+direction.
+.IP ":g/[string]/[editor command]<nl>" 16
+.sp 1
+Using the \fB:\fR syntax it is possible to do global searches ala the
+standard UNIX "ed" editor.
+.NH 2
+Text Insertion
+.LP
+The following commands allow for the insertion of text.  All multicharacter
+text insertions are terminated with an <esc> character.
+The last change
+can always be \fBundone\fR by typing a \fBu\fR.
+The text insert in insertion mode can contain newlines.
+.IP a{text}<esc> 16
+Insert text immediately following the cursor position.
+Mnemonic: \fBa\fRppend
+.IP A{text}<esc> 16
+Insert text at the end of the current line.
+Mnemonic: \fBA\fRppend
+.IP i{text}<esc> 16
+Insert text immediately preceding the cursor position.
+Mnemonic: \fBi\fRnsert
+.IP I{text}<esc> 16
+Insert text at the beginning of the current line.
+.IP o{text}<esc> 16
+Insert a new line after the line on which the cursor appears and
+insert text there.  Mnemonic:  \fBo\fRpen new line
+.IP O{text}<esc> 16
+Insert a new line preceding the line on which the cursor appears
+and insert text there.
+.NH 2
+Text Deletion
+.LP
+The following commands allow the user to delete text in various ways.
+All changes can always be \fBundone\fR by typing the \fBu\fR command.
+.IP "[cnt]x" 16
+Delete the character or characters starting at the cursor position.
+.IP "[cnt]X" 16
+Delete the character or characters starting at the character preceding
+the cursor position.
+.IP "D" 16
+Deletes the remainder of the line starting at the cursor.
+Mnemonic: \fBD\fRelete the rest of line
+.IP "[cnt]d{motion}" 16
+.br
+Deletes one or more occurrences of the specified motion.
+Any motion from sections 4.1 and 4.2 can be used here.
+The d can be stuttered (e.g. [cnt]dd) to delete cnt lines.
+.NH 2
+Text Replacement
+.LP
+The following commands allow the user to simultaneously delete and
+insert new text.  All such actions can be \fBundone\fR by typing
+\fBu\fR following the command.
+.IP "r<chr>" 16
+Replaces the character at the current cursor position with <chr>.  This
+is a one character replacement.  No <esc> is required for termination.
+Mnemonic:  \fBr\fReplace character
+.IP "R{text}<esc>" 16
+Starts overlaying the characters on the screen with whatever you type.
+It does not stop until an <esc> is typed.
+.IP "[cnt]s{text}<esc>" 16
+Substitute for "cnt" characters beginning at the current cursor
+position.  A "$" will appear at the position in the text where the
+"cnt"'th character appears so you will know how much you are erasing.
+Mnemonic: \fBs\fRubstitute
+.IP "[cnt]S{text}<esc>" 16
+Substitute for the entire current line (or lines).  If no count is given,
+a "$" appears at the end of the current line.  If a count of more than
+1 is given, all the lines to be replaced are deleted before the insertion
+begins.
+.IP "[cnt]c{motion}{text}<esc>" 16
+.br
+Change the specified "motion" by replacing it with the
+insertion text.  A "$" will appear at the end of the last item
+that is being deleted unless the deletion involves whole lines.
+Motion's can be any motion from sections 4.1 or 4.2.
+Stuttering the c (e.g. [cnt]cc) changes cnt lines.
+.NH 2
+Moving Text
+.LP
+\fBVi\fR provides a number of ways of moving chunks of text around.
+There are nine buffers into which each piece of text which is deleted
+or "yanked" is put in addition to the "undo" buffer.
+The most recent deletion or yank is in the "undo" buffer and also
+usually in buffer
+1, the next most recent in buffer 2, and so forth.  Each new deletion
+pushes down all the older deletions.  Deletions older than 9
+disappear.  There is also
+a set of named registers, a-z, into which text can optionally
+be placed.  If any delete or replacement type command is preceded
+by \fB"<a-z>\fR, that named buffer will contain the text deleted
+after the command is executed.  For example, \fB"a3dd\fR will delete
+three lines starting at the current line and put them in buffer \fB"a\fR.*
+.FS
+* Referring to an upper case letter as a buffer name (A-Z) is the
+same as referring to the lower case letter, except that text placed
+in such a buffer is appended to it instead of replacing it.
+.FE
+There are two more basic commands and
+some variations useful in getting and putting text into a file.
+.IP ["<a-z>][cnt]y{motion} 16
+.sp 1
+Yank the specified item or "cnt" items and put in the "undo" buffer or
+the specified buffer.  The variety of "items" that can be yanked
+is the same as those that can be deleted with the "d" command or
+changed with the "c" command.  In the same way that "dd" means
+delete the current line and "cc" means replace the current line,
+"yy" means yank the current line.
+.IP ["<a-z>][cnt]Y 16
+Yank the current line or the "cnt" lines starting from the current
+line.  If no buffer is specified, they will go into the "undo" buffer,
+like any delete would.  It is equivalent to "yy".
+Mnemonic:  \fBY\fRank
+.IP ["<a-z>]p 16
+Put "undo" buffer or the specified buffer down \fBafter\fR the cursor.
+If whole lines were yanked or deleted into the buffer, then they will be
+put down on the line following the line the cursor is on.  If
+something else was deleted, like a word or sentence, then it will
+be inserted immediately following the cursor.
+Mnemonic:  \fBp\fRut buffer
+.IP
+It should be noted that text in the named buffers remains there when you
+start editing a new file with the \fB:e file<esc>\fR command.  Since
+this is so, it is possible to copy or delete text from one file and
+carry it over to another file in the buffers.
+However, the undo buffer and the ability to undo are lost when
+changing files.
+.IP ["<a-z>]P 16
+Put "undo" buffer or the specified buffer down \fBbefore\fR the cursor.
+If whole lines where yanked or deleted into the buffer, then they will be
+put down on the line preceding the line the cursor is on.  If
+something else was deleted, like a word or sentence, then it will
+be inserted immediately preceding the cursor.
+.IP [cnt]>{motion} 16
+The shift operator will right shift all the text from the line on which
+the cursor is located to the line where the \fBmotion\fR is located.
+The text is shifted by one \fBshiftwidth\fR.  (See section 6.)
+\fB>>\fR means right shift the current line or lines.
+.IP [cnt]<{motion} 16
+The shift operator will left shift all the text from the line on which
+the cursor is located to the line where the \fBitem\fR is located.
+The text is shifted by one \fBshiftwidth\fR.  (See section 6.)
+\fB<<\fR means left shift the current line or lines.
+Once the line has reached the left margin it is not further affected.
+.IP [cnt]={motion} 16
+Prettyprints the indicated area according to
+.B lisp
+conventions.
+The area should be a lisp s-expression.
+.NH 2
+Miscellaneous Commands
+.LP
+\fBVi\fR has a number of miscellaneous commands that are very
+useful.  They are:
+.IP ZZ 16
+This is the normal way to exit from vi.
+If any changes have been made, the file is written out.
+Then you are returned to the shell.
+.IP ^L 16
+Redraw the current screen.  This is useful if someone "write"s you
+while you are in "vi" or if for any reason garbage gets onto the
+screen.
+.IP ^R 16
+On dumb terminals, those not having the "delete line" function
+(the vt100 is such a terminal), \fBvi\fR saves redrawing the
+screen when you delete a line by just marking the line with an
+"@" at the beginning and blanking the line.  If you want to
+actually get rid of the lines marked with "@" and see what the
+page looks like, typing a ^R will do this.
+.IP \s+4.\s0 16
+"Dot" is a particularly useful command.  It repeats the last
+text modifying command.  Therefore you can type a command once and
+then to another place and repeat it by just typing ".".
+.IP u 16
+Perhaps the most important command in the editor,
+u undoes the last command that changed the buffer.
+Mnemonic:  \fBu\fRndo
+.IP U 16
+Undo all the text modifying commands performed on the current line
+since the last time you moved onto it.
+.IP [cnt]J 16
+Join the current line and the following line.  The <nl> is deleted
+and the two lines joined, usually with a space between the
+end of the first line and the beginning of what was the second
+line.  If the first line ended with a "period", then two spaces
+are inserted.
+A count joins the next cnt lines.
+Mnemonic: \fBJ\fRoin lines
+.IP Q 16
+Switch to \fBex\fR editing mode.
+In this mode \fBvi\fR will behave very much like \fBed\fR.
+The editor in this mode will operate on single lines normally and
+will not attempt to keep the "window" up to date.
+Once in this mode it is also possible to switch to the \fBopen\fR
+mode of editing.  By entering the command \fB[line number]open<nl>\fR
+you enter this mode.  It is similar to the normal visual mode
+except the window is only \fBone\fR line long.
+Mnemonic: \fBQ\fRuit visual mode
+.IP ^] 16
+An abbreviation for a tag command.
+The cursor should be positioned at the beginning of a word.
+That word is taken as a tag name, and the tag with that
+name is found as if it had been typed in a :tag command.
+.IP [cnt]!{motion}{UNIX\ cmd}<nl> 16
+.br
+Any UNIX filter
+(e.g. command that reads the standard input and outputs something
+to the standard output) can be sent a section of the current file and
+have the output of the command replace the original text.  Useful
+examples are programs like \fBcb\fR, \fBsort\fR, and
+\fBnroff\fR.  For instance, using \fBsort\fR it would be possible to
+sort a section of the current file into a new list.
+Using \fB!!\fR means take a line or lines starting at the line the
+cursor is currently on and pass them to the UNIX command.
+.B NOTE:
+To just escape to the shell for one command,
+use :!{cmd}<nl>, see section 5.
+.IP z{cnt}<nl> 16
+This resets the current window size to "cnt" lines and redraws the screen.
+.NH 2
+Special Insert Characters
+.LP
+There are some characters that have special meanings during
+insert modes.  They are:
+.IP ^V 16
+During inserts, typing a ^V allows you to quote control characters
+into the file.  Any character typed after the ^V will be inserted
+into the file.
+.IP [^]^D\ or\ [0]^D 16
+<^D> without any argument backs up one \fBshiftwidth\fR.  This is necessary
+to remove indentation that was inserted by the \fBautoindent\fR feature.
+^<^D> temporarily removes all the autoindentation, thus placing the cursor
+at the left margin.  On the next line, the previous indent level will be
+restored.  This is useful for putting "labels" at the left margin.
+0<^D> says remove all autoindents and stay that way.  Thus the cursor
+moves to the left margin and stays there on successive lines until
+<tab>'s are typed.  As with the <tab>, the <^D> is only effective before
+any other "non-autoindent" controlling characters are typed.
+Mnemonic: \fBD\fRelete a shiftwidth
+.IP ^W 16
+If the cursor is sitting on a word, <^W> moves the cursor back to the beginning
+of the word, thus erasing the word from the insert.
+Mnemonic: erase \fBW\fRord
+.IP <bs> 16
+The backspace always serves as an erase during insert modes in addition
+to your normal "erase" character.  To insert a <bs> into your file, use
+the <^V> to quote it.
+.NH 1
+\fB:\fR Commands
+.LP
+Typing a ":" during command mode causes \fBvi\fR to put the cursor at
+the bottom on the screen in preparation for a command.  In the
+":" mode, \fBvi\fR can be given most \fBed\fR commands.  It is
+also from this mode that you exit from \fBvi\fR or switch to different
+files.  All commands of this variety are terminated by a <nl>, <cr>,
+or <esc>.
+.IP ":w[!] [file]" 16
+Causes \fBvi\fR to write out the current text to the disk.  It is
+written to the file you are editing unless "file" is supplied.  If
+"file" is supplied, the write is directed to that file instead.  If
+that file already exists, \fBvi\fR will not perform the write unless
+the "!" is supplied indicating you
+.I really
+want to destroy the older copy of the file.
+.IP :q[!] 16
+Causes \fBvi\fR to exit.  If you have modified the file you are
+looking at currently and haven't written it out, \fBvi\fR will
+refuse to exit unless the "!" is supplied.
+.IP ":e[!] [+[cmd]] [file]" 16
+.sp 1
+Start editing a new file called "file" or start editing the current
+file over again.  The command ":e!" says "ignore the changes I've made
+to this file and start over from the beginning".  It is useful if
+you really mess up the file.  The optional "+" says instead of starting
+at the beginning, start at the "end", or,
+if "cmd" is supplied, execute "cmd" first.
+Useful cases of this are where cmd is "n" (any integer) which starts
+at line number n,
+and "/text", which searches for "text" and starts at the line where
+it is found.
+.IP "^^" 16
+Switch back to the place you were before your last tag command.
+If your last tag command stayed within the file, ^^ returns to that tag.
+If you have no recent tag command, it will return to the
+same place in the previous file that it was showing when you switched
+to the current file.
+.IP ":n[!]" 16
+Start editing the next file in the argument list.  Since \fBvi\fR
+can be called with multiple file names, the ":n" command tells it to
+stop work on the current file and switch to the next file.  If the
+current file was modifies, it has to be written out before the ":n"
+will work or else the "!" must be supplied, which says discard the
+changes I made to the current file.
+.IP ":n[!] file [file file ...]" 16
+.sp
+Replace the current argument list with a new list of files and start
+editing the first file in this new list.
+.IP ":r file" 16
+Read in a copy of "file" on the line after the cursor.
+.IP ":r !cmd" 16
+Execute the "cmd" and take its output and put it into the file after
+the current line.
+.IP ":!cmd" 16
+Execute any UNIX shell command.
+.IP ":ta[!] tag" 16
+.B Vi
+looks in the file named
+.B tags
+in the current directory.
+.B Tags
+is a file of lines in the format:
+.sp 1
+.ti +8
+tag filename \fBvi\fR-search-command
+.sp 1
+If \fBvi\fR finds the tag you specified in the \fB:ta\fR command,
+it stops editing the current file if necessary and if the current file is
+up to date on the disk and switches to the file specified and uses the
+search pattern specified to find the "tagged" item of interest.  This
+is particularly useful when editing multi-file C programs such as the
+operating system.  There is a program called \fBctags\fR which will
+generate an appropriate \fBtags\fR file for C and f77
+programs so that by saying
+\fB:ta function<nl>\fR you will be switched to that function.
+It could also be useful when editing multi-file documents, though the
+\fBtags\fR file would have to be generated manually.
+.NH 1
+Special Arrangements for Startup
+.PP
+\fBVi\fR takes the value of \fB$TERM\fR and looks up the characteristics
+of that terminal in the file \fB/etc/termcap\fR.
+If you don't know \fBvi\fR's name for the terminal you are working
+on, look in \fB/etc/termcap\fR.
+.PP
+When \fBvi\fR starts, it attempts to read the variable EXINIT
+from your environment.*
+If that exists, it takes the values in it as the default values
+for certain of its internal constants.  See the section on "Set Values"
+for further details.
+If EXINIT doesn't exist you will get all the normal defaults.
+.FS
+* On version 6 systems
+Instead of EXINIT, put the startup commands in the file .exrc
+in your home directory.
+.FE
+.PP
+Should you inadvertently hang up the phone while inside
+.B vi ,
+or should the computer crash,
+all may not be lost.
+Upon returning to the system, type:
+.DS
+vi \-r file
+.DE
+This will normally recover the file.  If there is more than one
+temporary file for a specific file name, \fBvi\fR recovers the
+newest one.  You can get an older version by recovering the
+file more than once.
+The command "vi -r" without a file name gives you the list of files
+that were saved in the last system crash
+(but
+.I not
+the file just saved when the phone was hung up).
+.NH 1
+Set Commands
+.LP
+\fBVi\fR has a number of internal variables and switches which can be
+set to achieve special affects.
+These options come in three forms, those that are switches, which toggle
+from off to on and back, those that require a numeric value, and those
+that require an alphanumeric string value.
+The toggle options are set by a command of the form:
+.DS
+:set option<nl>
+.DE
+and turned off with the command:
+.DS
+:set nooption<nl>
+.DE
+Commands requiring a value are set with a command of the form:
+.DS
+:set option=value<nl>
+.DE
+To display the value of a specific option type:
+.DS
+:set option?<nl>
+.DE
+To display only those that you have changed type:
+.DS
+:set<nl>
+.DE
+and to display the long table of all the settable parameters and
+their current values type:
+.DS
+:set all<nl>
+.DE
+.PP
+Most of the options have a long form and an abbreviation.  Both are
+listed in the following table as well as the normal default value.
+.PP
+To arrange to have values other than the default used every time you
+enter
+.B vi ,
+place the appropriate
+.B set
+command in EXINIT in your environment, e.g.
+.DS
+EXINIT='set ai aw terse sh=/bin/csh'
+export EXINIT
+.DE
+or
+.DS
+setenv EXINIT 'set ai aw terse sh=/bin/csh'
+.DE
+for
+.B sh
+and
+.B csh ,
+respectively.
+These are usually placed in your .profile or .login.
+If you are running a system without environments (such as version 6)
+you can place the set command in the file .exrc in your home
+directory.
+.IP autoindent\ ai 16
+Default: noai Type: toggle
+.br
+When in autoindent mode, vi helps you indent code by starting each
+line in the same column as the preceding line.
+Tabbing to the right with <tab> or <^T> will move this boundary to
+the right, and it can be moved to the left with <^D>.
+.IP autoprint\ ap 16
+Default: ap Type: toggle
+.br
+Causes the current line to be printed after each ex text modifying command.
+This is not of much interest in the normal \fBvi\fR visual mode.
+.IP autowrite\ aw 16
+Default: noaw type: toggle
+.br
+Autowrite causes an automatic write to be done if there are unsaved
+changes before certain commands which change files or otherwise
+interact with the outside world.
+These commands are :!, :tag, :next, :rewind, ^^, and ^].
+.IP beautify\ bf 16
+Default: nobf Type: toggle
+.br
+Causes all control characters except <tab>, <nl>, and <ff> to be discarded.
+.IP directory\ dir 16
+Default: dir=/tmp Type: string
+.br
+This is the directory in which \fBvi\fR puts its temporary file.
+.IP errorbells\ eb 16
+Default: noeb Type: toggle
+.br
+Error messages are preceded by a <bell>.
+.IP hardtabs\ ht 16
+Default: hardtabs=8 Type: numeric
+.br
+This option contains the value of hardware tabs in your terminal, or
+of software tabs expanded by the Unix system.
+.IP ignorecase\ ic 16
+Default: noic Type: toggle
+.br
+All upper case characters are mapped to lower case in regular expression
+matching.
+.IP lisp 16
+Default: nolisp Type: toggle
+.br
+Autoindent for \fBlisp\fR code.  The commands \fB( ) [[\fR and \fB]]\fR
+are modified appropriately to affect s-expressions and functions.
+.IP list 16
+Default: nolist Type: toggle
+.br
+All printed lines have the <tab> and <nl> characters displayed visually.
+.IP magic 16
+Default: magic Type: toggle
+.br
+Enable the metacharacters for matching.  These include \fB. * < > [string]
+[^string]\fR and \fB[<chr>-<chr>]\fR.
+.IP number\ nu 16
+Default: nonu Type: toggle
+.br
+Each line is displayed with its line number.
+.IP open 16
+Default: open Type: toggle
+.br
+When set, prevents entering open or visual modes from ex or edit.
+Not of interest from vi.
+.IP optimize\ opt 16
+Default: opt Type: toggle
+.br
+Basically of use only when using the \fBex\fR capabilities.  This
+option prevents automatic <cr>s from taking place,
+and speeds up output of indented lines,
+at the expense of losing typeahead on some versions of UNIX.
+.IP paragraphs\ para 16
+Default: para=IPLPPPQPP\ bp Type: string
+.br
+Each pair of characters in the string indicate \fBnroff\fR macros
+which are to be treated as the beginning of a paragraph for the
+\fB{\fR and \fB}\fR commands.  The default string is for the \fB-ms\fR
+and \fB-mm\fR macros.
+To indicate one letter \fBnroff\fR macros, such as \fB.P\fR or \fB.H\fR,
+quote a space in for the second character position.  For example:
+.sp 1
+.ti +8
+:set paragraphs=P\e bp<nl>
+.sp 1
+would cause \fBvi\fR to consider \fB.P\fR and \fB.bp\fR as paragraph
+delimiters.
+.IP prompt 16
+Default: prompt Type: toggle
+.br
+In
+.B ex
+command mode the prompt character \fB:\fR will be printed when
+\fBex\fR is waiting for a command.  This is not of interest from vi.
+.IP redraw 16
+Default: noredraw Type: toggle
+.br
+On dumb terminals, force the screen to always be up to date,
+by sending great amounts of output.  Useful only at high speeds.
+.IP report 16
+Default: report=5 Type: numeric
+.br
+This sets the threshold for the number of lines modified.  When
+more than this number of lines are modified, removed, or yanked,
+\fBvi\fR will report the number of lines changed at the bottom of
+the screen.
+.IP scroll 16
+Default: scroll={1/2 window} Type: numeric
+.br
+This is the number of lines that the screen scrolls up or down when
+using the <^U> and <^D> commands.
+.IP sections 16
+Default: sections=SHNHH HU Type: string
+.br
+Each two character pair of this string specify \fBnroff\fR macro names
+which are to be treated as the beginning of a section by the
+\fB]]\fR and \fB[[\fR commands.  The default string is for the \fB-ms\fR
+and \fB-mm\fR macros.
+To enter one letter \fBnroff\fR macros, use a quoted space as the
+second character.
+See \fBparagraphs\fR for a fuller explanation.
+.IP shell\ sh 16
+Default: sh=from environment SHELL or /bin/sh   Type: string
+.br
+This is the name of the \fBsh\fR to be used for "escaped" commands.
+.IP shiftwidth\ sw 16
+Default: sw=8 Type: numeric
+.br
+This is the number of spaces that a <^T> or <^D> will move over for
+indenting, and the amount < and > shift by.
+.IP showmatch\ sm 16
+Default: nosm Type: toggle
+.br
+When a \fB)\fR or \fB}\fR is typed, show the matching \fB(\fR or \fB{\fR
+by moving the cursor to it for one second if it is on the current screen.
+.IP slowopen\ slow 16
+Default: terminal dependent Type: toggle
+.br
+On terminals that are slow and unintelligent, this option prevents the
+updating of the screen some of the time to improve speed.
+.IP tabstop\ ts 16
+Default: ts=8 Type: numeric
+.br
+<tab>s are expanded to boundaries that are multiples of this value.
+.IP taglength\ tl 16
+Default: tl=0 Type: numeric
+.br
+If nonzero, tag names are only significant to this many characters.
+.IP term 16
+Default: (from environment \fBTERM\fP, else dumb) Type: string
+.br
+This is the terminal and controls the visual displays.  It cannot be
+changed when in "visual" mode,
+you have to Q to command mode, type a
+set term command, and do ``vi.'' to get back into visual.
+Or exit vi, fix $TERM, and reenter.
+The definitions that drive a particular
+terminal type are found in the file \fB/etc/termcap\fR.
+.IP terse 16
+Default: terse Type: toggle
+.br
+When set, the error diagnostics are short.
+.IP warn 16
+Default: warn Type: toggle
+.br
+The user is warned if she/he tries to escape to
+the shell without writing out the current changes.
+.IP window 16
+Default: window={8 at 600 baud or less, 16 at 1200 baud, and screen
+size \- 1 at 2400 baud or more} Type: numeric
+.br
+This is the number of lines in the window whenever \fBvi\fR must redraw
+an entire screen.  It is useful to make this size smaller if you are
+on a slow line.
+.IP w300,\ w1200,\ w9600
+.br
+These set window, but only within the corresponding speed ranges.
+They are useful in an EXINIT to fine tune window sizes.
+For example,
+.DS
+set w300=4 w1200=12
+.DE
+causes a 4 lines window at speed up to 600 baud, a 12 line window at 1200
+baud, and a full screen (the default) at over 1200 baud.
+.IP wrapscan\ ws 16
+Default: ws Type: toggle
+.br
+Searches will wrap around the end of the file when is option is set.  When
+it is off, the search will terminate when it reaches the end or the
+beginning of the file.
+.IP wrapmargin\ wm 16
+Default: wm=0 Type: numeric
+.br
+\fBVi\fR will automatically insert a <nl> when it finds a natural
+break point (usually a <sp> between words) that occurs within
+"wm" spaces of the right margin.
+Therefore with "wm=0" the option is off.  Setting it to 10 would
+mean that any time you are within 10 spaces of the right margin
+\fBvi\fR would be looking for a <sp> or <tab> which it could
+replace with a <nl>.  This is convenient for people who forget
+to look at the screen while they type.
+(In version 3, wrapmargin behaves more like nroff, in that the
+boundary specified by the distance from the right edge of the screen
+is taken as the rightmost edge of the area where a break is allowed,
+instead of the leftmost edge.)
+.IP writeany\ wa 16
+Default: nowa Type: toggle
+.br
+\fBVi\fR normally makes a number of checks before it writes out a file.
+This prevents the user from inadvertently destroying a file.  When the
+"writeany" option is enabled, \fBvi\fR no longer makes these checks.
diff --git a/dist/nvi/docs/vitut/vi.chars b/dist/nvi/docs/vitut/vi.chars
new file mode 100644 (file)
index 0000000..f246b66
--- /dev/null
@@ -0,0 +1,619 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: vi.chars,v 8.3 1996/06/27 19:53:17 bostic Exp (Berkeley) Date: 1996/06/27 19:53:17
+.\"
+.bd S 3
+.pn 21
+.de iP
+.IP "\fB\\$1\fR" \\$2
+..
+.SH
+Appendix: character functions
+.PP
+This appendix gives the uses the editor makes of each character.  The
+characters are presented in their order in the \s-2ASCII\s0 character
+set:  Control characters come first, then most special characters, then
+the digits, upper and then lower case characters.
+.PP
+For each character we tell a meaning it has as a command and any meaning it
+has during an insert.
+If it has only meaning as a command, then only this is discussed.
+Section numbers in parentheses indicate where the character is discussed;
+a `f' after the section number means that the character is mentioned
+in a footnote.
+.iP "^@" 15
+Not a command character.
+If typed as the first character of an insertion it is replaced with the
+last text inserted, and the insert terminates.  Only 128 characters are
+saved from the last insert; if more characters were inserted the mechanism
+is not available.
+A \fB^@\fR cannot be part of the file due to the editor implementation
+(7.5f).
+.iP "^A" 15
+Unused.
+.iP "^B" 15
+Backward window.
+A count specifies repetition.
+Two lines of continuity are kept if possible (2.1, 6.1, 7.2).
+.iP "^C" 15
+Unused.
+.iP "^D" 15
+As a command, scrolls down a half-window of text.  
+A count gives the number of (logical) lines to scroll, and is remembered
+for future \fB^D\fR and \fB^U\fR commands (2.1, 7.2).
+During an insert, backtabs over \fIautoindent\fR white space at the beginning
+of a line (6.6, 7.5); this white space cannot be backspaced over.
+.iP "^E" 15
+Exposes one more line below the current screen in the file, leaving
+the cursor where it is if possible.
+(Version 3 only.)
+.iP "^F" 15
+Forward window.  A count specifies repetition.
+Two lines of continuity are kept if possible (2.1, 6.1, 7.2).
+.iP "^G" 15
+Equivalent to \fB:f\fR\s-2CR\s0, printing the current file, whether
+it has been modified, the current line number and the number of lines
+in the file, and the percentage of the way through the file that you
+are.
+.iP "^H (\fR\s-2BS\s0\fP)" 15
+Same as
+.B "left arrow" .
+(See
+.B h ).
+During an insert, eliminates the last input character, backing over it
+but not erasing it; it remains so you can see what you typed if you
+wish to type something only slightly different (3.1, 7.5).
+.iP "^I\ (\fR\s-2TAB\s0\fP)" 15
+Not a command character.
+When inserted it prints as some
+number of spaces.
+When the cursor is at a tab character it rests at the last of the spaces
+which represent the tab.
+The spacing of tabstops is controlled by the \fItabstop\fR option (4.1, 6.6).
+.iP "^J\ (\fR\s-2LF\s0\fP)" 15
+Same as
+.B "down arrow"
+(see
+.B j ).
+.iP "^K" 15
+Unused.
+.iP "^L" 15
+The \s-2ASCII\s0 formfeed character, this causes the screen to be cleared
+and redrawn.  This is useful after a transmission error, if characters
+typed by a program other than the editor scramble the screen,
+or after output is stopped by an interrupt (5.4, 7.2f).
+.ne 1i
+.iP "^M\ (\fR\s-2CR\s0\fP)" 15
+A carriage return advances to the next line, at the first non-white position
+in the line.  Given a count, it advances that many lines (2.3).
+During an insert, a \s-2CR\s0 causes the insert to continue onto
+another line (3.1).
+.iP "^N" 15
+Same as
+.B "down arrow"
+(see
+.B j ).
+.iP "^O" 15
+Unused.
+.iP "^P" 15
+Same as
+.B "up arrow"
+(see
+.B k ).
+.iP "^Q" 15
+Not a command character.
+In input mode,
+.B ^Q
+quotes the next character, the same as
+.B ^V ,
+except that some teletype drivers will eat the
+.B ^Q
+so that the editor never sees it.
+.iP "^R" 15
+Redraws the current screen, eliminating logical lines not corresponding
+to physical lines (lines with only a single @ character on them).
+On hardcopy terminals in \fIopen\fR mode, retypes the current line
+(5.4, 7.2, 7.8).
+.iP "^S" 15
+Unused.  Some teletype drivers use
+.B ^S
+to suspend output until
+.B ^Q is pressed.
+.iP "^T" 15
+Not a command character.
+During an insert, with \fIautoindent\fR set and at the beginning of the
+line, inserts \fIshiftwidth\fR white space.
+.iP "^U" 15
+Scrolls the screen up, inverting \fB^D\fR which scrolls down.  Counts work as
+they do for \fB^D\fR, and the previous scroll amount is common to both.
+On a dumb terminal, \fB^U\fR will often necessitate clearing and redrawing
+the screen further back in the file (2.1, 7.2).
+.iP "^V" 15
+Not a command character.
+In input mode, quotes the next character so that it is possible
+to insert non-printing and special characters into the file (4.2, 7.5).
+.iP "^W" 15
+Not a command character.
+During an insert, backs up as \fBb\fR would in command mode; the deleted
+characters remain on the display (see \fB^H\fR) (7.5).
+.iP "^X" 15
+Unused.
+.iP "^Y" 15
+Exposes one more line above the current screen, leaving the cursor where
+it is if possible.  (No mnemonic value for this key; however, it is next
+to \fB^U\fR which scrolls up a bunch.)
+(Version 3 only.)
+.iP "^Z" 15
+If supported by the Unix system,
+stops the editor, exiting to the top level shell.
+Same as \fB:stop\fP\s-2CR\s0.
+Otherwise, unused.
+.iP "^[\ (\fR\s-2ESC\s0\fP)" 15
+Cancels a partially formed command, such as a \fBz\fR when no following
+character has yet been given; terminates inputs on the last line (read
+by commands such as \fB: /\fR and \fB?\fR); ends insertions of new text
+into the buffer.
+If an \s-2ESC\s0 is given when quiescent in command state, the editor
+rings the bell or flashes the screen.  You can thus hit \s-2ESC\s0 if
+you don't know what is happening till the editor rings the bell.
+If you don't know if you are in insert mode you can type \s-2ESC\s0\fBa\fR,
+and then material to be input; the material will be inserted correctly
+whether or not you were in insert mode when you started (1.5, 3.1, 7.5).
+.iP "^\e" 15
+Unused.
+.iP "^]" 15
+Searches for the word which is after the cursor as a tag.  Equivalent
+to typing \fB:ta\fR, this word, and then a \s-2CR\s0.
+Mnemonically, this command is ``go right to'' (7.3).
+.iP "^\(ua" 15
+Equivalent to \fB:e #\fR\s-2CR\s0, returning to the previous position
+in the last edited file, or editing a file which you specified if you
+got a `No write since last change diagnostic' and do not want to have
+to type the file name again (7.3).
+(You have to do a \fB:w\fR before \fB^\(ua\fR
+will work in this case.  If you do not wish to write the file you should
+do \fB:e!\ #\fR\s-2CR\s0 instead.)
+.iP "^_" 15
+Unused.
+Reserved as the command character for the
+Tektronix 4025 and 4027 terminal.
+.iP "\fR\s-2SPACE\s0\fP" 15
+Same as
+.B "right arrow"
+(see
+.B l ).
+.iP "!" 15
+An operator, which processes lines from the buffer with reformatting commands.
+Follow \fB!\fR with the object to be processed, and then the command name
+terminated by \s-2CR\s0.  Doubling \fB!\fR and preceding it by a count
+causes count lines to be filtered; otherwise the count
+is passed on to the object after the \fB!\fR.  Thus \fB2!}\fR\fIfmt\fR\s-2CR\s0
+reformats the next two paragraphs by running them through the program
+\fIfmt\fR.  If you are working on \s-2LISP\s0,
+the command \fB!%\fR\fIgrind\fR\s-2CR\s0,*
+.FS
+*Both
+.I fmt
+and
+.I grind
+are Berkeley programs and may not be present at all installations.
+.FE
+given at the beginning of a
+function, will run the text of the function through the \s-2LISP\s0 grinder
+(6.7, 7.3).
+To read a file or the output of a command into the buffer use \fB:r\fR (7.3).
+To simply execute a command use \fB:!\fR (7.3).
+.tr \a"
+.iP \a 15
+Precedes a named buffer specification.  There are named buffers \fB1\-9\fR
+used for saving deleted text and named buffers \fBa\-z\fR into which you can
+place text (4.3, 6.3)
+.tr \a\a
+.iP "#" 15
+The macro character which, when followed by a number, will substitute
+for a function key on terminals without function keys (6.9).
+In input mode, 
+if this is your erase character, it will delete the last character
+you typed in input mode, and must be preceded with a \fB\e\fR to insert
+it, since it normally backs over the last input character you gave.
+.iP "$" 15
+Moves to the end of the current line.  If you \fB:se list\fR\s-2CR\s0,
+then the end of each line will be shown by printing a \fB$\fR after the
+end of the displayed text in the line.  Given a count, advances to the
+count'th following end of line; thus \fB2$\fR advances to the end of the
+following line.
+.iP "%" 15
+Moves to the parenthesis or brace \fB{ }\fR which balances the parenthesis
+or brace at the current cursor position.
+.iP "&" 15
+A synonym for \fB:&\fR\s-2CR\s0, by analogy with the
+.I ex
+.B &
+command.
+.iP "\(aa" 15
+When followed by a \fB\(aa\fR returns to the previous context at the
+beginning of a line.  The previous context is set whenever the current
+line is moved in a non-relative way.
+When followed by a letter \fBa\fR\-\fBz\fR, returns to the line which
+was marked with this letter with a \fBm\fR command, at the first non-white
+character in the line. (2.2, 5.3).
+When used with an operator such as \fBd\fR, the operation takes place
+over complete lines; if you use \fB\(ga\fR, the operation takes place
+from the exact marked place to the current cursor position within the
+line.
+.iP "(" 15
+Retreats to the beginning of a
+sentence, or to the beginning of a \s-2LISP\s0 s-expression
+if the \fIlisp\fR option is set.
+A sentence ends at a \fB. !\fR or \fB?\fR which is followed by either
+the end of a line or by two spaces.  Any number of closing \fB) ] "\fR
+and \fB\(aa\fR characters may appear after the \fB. !\fR or \fB?\fR,
+and before the spaces or end of line.  Sentences also begin
+at paragraph and section boundaries
+(see \fB{\fR and \fB[[\fR below).
+A count advances that many sentences (4.2, 6.8).
+.iP ")" 15
+Advances to the beginning of a sentence.
+A count repeats the effect.
+See \fB(\fR above for the definition of a sentence (4.2, 6.8).
+.iP "*" 15
+Unused.
+.iP "+" 15
+Same as \s-2CR\s0 when used as a command.
+.iP "," 15
+Reverse of the last \fBf F t\fR or \fBT\fR command, looking the other way
+in the current line.  Especially useful after hitting too many \fB;\fR
+characters.  A count repeats the search.
+.iP "\-" 15
+Retreats to the previous line at the first non-white character.
+This is the inverse of \fB+\fR and \s-2RETURN\s0.
+If the line moved to is not on the screen, the screen is scrolled, or
+cleared and redrawn if this is not possible.
+If a large amount of scrolling would be required the screen is also cleared
+and redrawn, with the current line at the center (2.3).
+.iP "\&." 15
+Repeats the last command which changed the buffer.  Especially useful
+when deleting words or lines; you can delete some words/lines and then
+hit \fB.\fR to delete more and more words/lines.
+Given a count, it passes it on to the command being repeated.  Thus after
+a \fB2dw\fR, \fB3.\fR deletes three words (3.3, 6.3, 7.2, 7.4).
+.iP "/" 15
+Reads a string from the last line on the screen, and scans forward for
+the next occurrence of this string.  The normal input editing sequences may
+be used during the input on the bottom line; an returns to command state
+without ever searching.
+The search begins when you hit \s-2CR\s0 to terminate the pattern;
+the cursor moves to the beginning of the last line to indicate that the search
+is in progress; the search may then
+be terminated with a \s-2DEL\s0 or \s-2RUB\s0, or by backspacing when
+at the beginning of the bottom line, returning the cursor to
+its initial position.
+Searches normally wrap end-around to find a string
+anywhere in the buffer.
+.IP
+When used with an operator the enclosed region is normally affected.
+By mentioning an
+offset from the line matched by the pattern you can force whole lines
+to be affected.  To do this give a pattern with a closing
+a closing \fB/\fR and then an offset \fB+\fR\fIn\fR or \fB\-\fR\fIn\fR.
+.IP
+To include the character \fB/\fR in the search string, you must escape
+it with a preceding \fB\e\fR.
+A \fB\(ua\fR at the beginning of the pattern forces the match to occur
+at the beginning of a line only; this speeds the search.  A \fB$\fR at
+the end of the pattern forces the match to occur at the end of a line
+only.
+More extended pattern matching is available, see section 7.4;
+unless you set \fBnomagic\fR in your \fI\&.exrc\fR file you will have
+to preceed the characters \fB. [ *\fR and \fB~\fR in the search pattern
+with a \fB\e\fR to get them to work as you would naively expect (1.5, 2,2,
+6.1, 7.2, 7.4).
+.iP "0" 15
+Moves to the first character on the current line.
+Also used, in forming numbers, after an initial \fB1\fR\-\fB9\fR.
+.iP "1\-9" 15
+Used to form numeric arguments to commands (2.3, 7.2).
+.iP ":" 15
+A prefix to a set of commands for file and option manipulation and escapes
+to the system.  Input is given on the bottom line and terminated with
+an \s-2CR\s0, and the command then executed.  You can return to where
+you were by hitting \s-2DEL\s0 or \s-2RUB\s0 if you hit \fB:\fR accidentally
+(see primarily 6.2 and 7.3).
+.iP ";" 15
+Repeats the last single character find which used \fBf F t\fR or \fBT\fR.
+A count iterates the basic scan (4.1).
+.iP "<" 15
+An operator which shifts lines left one \fIshiftwidth\fR, normally 8
+spaces.  Like all operators, affects lines when repeated, as in
+\fB<<\fR.  Counts are passed through to the basic object, thus \fB3<<\fR
+shifts three lines (6.6, 7.2).
+.iP "=" 15
+Reindents line for \s-2LISP\s0, as though they were typed in with \fIlisp\fR
+and \fIautoindent\fR set (6.8).
+.iP ">" 15
+An operator which shifts lines right one \fIshiftwidth\fR, normally 8
+spaces.  Affects lines when repeated as in \fB>>\fR.  Counts repeat the
+basic object (6.6, 7.2).
+.iP "?" 15
+Scans backwards, the opposite of \fB/\fR.  See the \fB/\fR description
+above for details on scanning (2.2, 6.1, 7.4).
+.iP "@" 15
+A macro character (6.9).  If this is your kill character, you must escape it with a \e
+to type it in during input mode, as it normally backs over the input you
+have given on the current line (3.1, 3.4, 7.5).
+.iP "A" 15
+Appends at the end of line, a synonym for \fB$a\fR (7.2).
+.iP "B" 15
+Backs up a word, where words are composed of non-blank sequences, placing
+the cursor at the beginning of the word.  A count repeats the effect
+(2.4).
+.iP "C" 15
+Changes the rest of the text on the current line; a synonym for \fBc$\fR.
+.iP "D" 15
+Deletes the rest of the text on the current line; a synonym for \fBd$\fR.
+.iP "E" 15
+Moves forward to the end of a word, defined as blanks and non-blanks,
+like \fBB\fR and \fBW\fR.  A count repeats the effect.
+.iP "F" 15
+Finds a single following character, backwards in the current line.
+A count repeats this search that many times (4.1).
+.iP "G" 15
+Goes to the line number given as preceding argument, or the end of the
+file if no preceding count is given.  The screen is redrawn with the
+new current line in the center if necessary (7.2).
+.iP "H" 15
+.B "Home arrow" .
+Homes the cursor to the top line on the screen.  If a count is given,
+then the cursor is moved to the count'th line on the screen.
+In any case the cursor is moved to the first non-white character on the
+line.  If used as the target of an operator, full lines are affected
+(2.3, 3.2).
+.iP "I" 15
+Inserts at the beginning of a line; a synonym for \fB\(uai\fR.
+.iP "J" 15
+Joins together lines, supplying appropriate white space: one space between
+words, two spaces after a \fB.\fR, and no spaces at all if the first
+character of the joined on line is \fB)\fR.  A count causes that many
+lines to be joined rather than the default two (6.5, 7.1f).
+.iP "K" 15
+Unused.
+.iP "L" 15
+Moves the cursor to the first non-white character of the last line on
+the screen.  With a count, to the first non-white of the count'th line
+from the bottom.  Operators affect whole lines when used with \fBL\fR
+(2.3).
+.iP "M" 15
+Moves the cursor to the middle line on the screen, at the first non-white
+position on the line (2.3).
+.iP "N" 15
+Scans for the next match of the last pattern given to
+\fB/\fR or \fB?\fR, but in the reverse direction; this is the reverse
+of \fBn\fR.
+.iP "O" 15
+Opens a new line above the current line and inputs text there up to an
+\s-2ESC\s0.  A count can be used on dumb terminals to specify a number
+of lines to be opened; this is generally obsolete, as the \fIslowopen\fR
+option works better (3.1).
+.iP "P" 15
+Puts the last deleted text back before/above the cursor.  The text goes
+back as whole lines above the cursor if it was deleted as whole lines.
+Otherwise the text is inserted between the characters before and at the
+cursor.  May be preceded by a named buffer specification \fB"\fR\fIx\fR
+to retrieve the contents of the buffer; buffers \fB1\fR\-\fB9\fR contain
+deleted material, buffers \fBa\fR\-\fBz\fR are available for general
+use (6.3).
+.iP "Q" 15
+Quits from \fIvi\fR to \fIex\fR command mode.  In this mode, whole lines
+form commands, ending with a \s-2RETURN\s0.  You can give all the \fB:\fR
+commands; the editor supplies the \fB:\fR as a prompt (7.7).
+.iP "R" 15
+Replaces characters on the screen with characters you type (overlay fashion).
+Terminates with an \s-2ESC\s0.
+.iP "S" 15
+Changes whole lines, a synonym for \fBcc\fR.  A count substitutes for
+that many lines.  The lines are saved in the numeric buffers, and erased
+on the screen before the substitution begins.
+.iP "T" 15
+Takes a single following character, locates the character before the
+cursor in the current line, and places the cursor just after that character.
+A count repeats the effect.  Most useful with operators such as \fBd\fR
+(4.1).
+.iP "U" 15
+Restores the current line to its state before you started changing it
+(3.5).
+.iP "V" 15
+Unused.
+.iP "W" 15
+Moves forward to the beginning of a word in the current line,
+where words are defined as sequences of blank/non-blank characters.
+A count repeats the effect (2.4).
+.iP "X" 15
+Deletes the character before the cursor.  A count repeats the effect,
+but only characters on the current line are deleted.
+.iP "Y" 15
+Yanks a copy of the current line into the unnamed buffer, to be put back
+by a later \fBp\fR or \fBP\fR; a very useful synonym for \fByy\fR. 
+A count yanks that many lines.  May be preceded by a buffer name to put
+lines in that buffer (7.4).
+.iP "ZZ" 15
+Exits the editor.
+(Same as \fB:x\fP\s-2CR\s0.)
+If any changes have been made, the buffer is written out to the current file.
+Then the editor quits.
+.iP "[[" 15
+Backs up to the previous section boundary.  A section begins at each
+macro in the \fIsections\fR option,
+normally a `.NH' or `.SH' and also at lines which which start
+with a formfeed \fB^L\fR.  Lines beginning with \fB{\fR also stop \fB[[\fR;
+this makes it useful for looking backwards, a function at a time, in C
+programs.  If the option \fIlisp\fR is set, stops at each \fB(\fR at the
+beginning of a line, and is thus useful for moving backwards at the top
+level \s-2LISP\s0 objects. (4.2, 6.1, 6.6, 7.2).
+.iP "\e" 15
+Unused.
+.iP "]]" 15
+Forward to a section boundary, see \fB[[\fR for a definition (4.2, 6.1,
+6.6, 7.2).
+.iP "\(ua" 15
+Moves to the first non-white position on the current line (4.4).
+.iP "_" 15
+Unused.
+.iP "\(ga" 15
+When followed by a \fB\(ga\fR returns to the previous context.
+The previous context is set whenever the current
+line is moved in a non-relative way.
+When followed by a letter \fBa\fR\-\fBz\fR, returns to the position which
+was marked with this letter with a \fBm\fR command.
+When used with an operator such as \fBd\fR, the operation takes place
+from the exact marked place to the current position within the line;
+if you use \fB\(aa\fR, the operation takes place over complete lines
+(2.2, 5.3).
+.iP "a" 15
+Appends arbitrary text after the current cursor position; the insert
+can continue onto multiple lines by using \s-2RETURN\s0 within the insert.
+A count causes the inserted text to be replicated, but only if the inserted
+text is all on one line.
+The insertion terminates with an \s-2ESC\s0 (3.1, 7.2).
+.iP "b" 15
+Backs up to the beginning of a word in the current line.  A word is a
+sequence of alphanumerics, or a sequence of special characters.
+A count repeats the effect (2.4).
+.iP "c" 15
+An operator which changes the following object, replacing it with the
+following input text up to an \s-2ESC\s0.  If more than part of a single
+line is affected, the text which is changed away is saved in the numeric named
+buffers.  If only part of the current line is affected, then the last
+character to be changed away is marked with a \fB$\fR.
+A count causes that many objects to be affected, thus both
+\fB3c)\fR and \fBc3)\fR change the following three sentences (7.4).
+.iP "d" 15
+An operator which deletes the following object.  If more than part of
+a line is affected, the text is saved in the numeric buffers.
+A count causes that many objects to be affected; thus \fB3dw\fR is the
+same as \fBd3w\fR (3.3, 3.4, 4.1, 7.4).
+.iP "e" 15
+Advances to the end of the next word, defined as for \fBb\fR and \fBw\fR.
+A count repeats the effect (2.4, 3.1).
+.iP "f" 15
+Finds the first instance of the next character following the cursor on
+the current line.  A count repeats the find (4.1).
+.iP "g" 15
+Unused.
+.sp
+Arrow keys
+.B h ,
+.B j ,
+.B k ,
+.B l ,
+and
+.B H .
+.iP "h" 15
+.B "Left arrow" .
+Moves the cursor one character to the left.
+Like the other arrow keys, either
+.B h ,
+the
+.B "left arrow"
+key, or one of the synonyms (\fB^H\fP) has the same effect.
+On v2 editors, arrow keys on certain kinds of terminals
+(those which send escape sequences, such as vt52, c100, or hp)
+cannot be used.
+A count repeats the effect (3.1, 7.5).
+.iP "i" 15
+Inserts text before the cursor, otherwise like \fBa\fR (7.2).
+.iP "j" 15
+.B "Down arrow" .
+Moves the cursor one line down in the same column.
+If the position does not exist,
+.I vi
+comes as close as possible to the same column.
+Synonyms include
+.B ^J
+(linefeed) and
+.B ^N .
+.iP "k" 15
+.B "Up arrow" .
+Moves the cursor one line up.
+.B ^P
+is a synonym.
+.iP "l" 15
+.B "Right arrow" .
+Moves the cursor one character to the right.
+\s-2SPACE\s0 is a synonym.
+.iP "m" 15
+Marks the current position of the cursor in the mark register which is
+specified by the next character \fBa\fR\-\fBz\fR.  Return to this position
+or use with an operator using \fB\(ga\fR or \fB\(aa\fR (5.3).
+.iP "n" 15
+Repeats the last \fB/\fR or \fB?\fR scanning commands (2.2).
+.iP "o" 15
+Opens new lines below the current line; otherwise like \fBO\fR (3.1).
+.iP "p" 15
+Puts text after/below the cursor; otherwise like \fBP\fR (6.3).
+.iP "q" 15
+Unused.
+.iP "r" 15
+Replaces the single character at the cursor with a single character you
+type.  The new character may be a \s-2RETURN\s0; this is the easiest
+way to split lines.  A count replaces each of the following count characters
+with the single character given; see \fBR\fR above which is the more
+usually useful iteration of \fBr\fR (3.2).
+.iP "s" 15
+Changes the single character under the cursor to the text which follows
+up to an \s-2ESC\s0; given a count, that many characters from the current
+line are changed.  The last character to be changed is marked with \fB$\fR
+as in \fBc\fR (3.2).
+.iP "t" 15
+Advances the cursor upto the character before the next character typed.
+Most useful with operators such as \fBd\fR and \fBc\fR to delete the
+characters up to a following character.  You can use \fB.\fR to delete
+more if this doesn't delete enough the first time (4.1).
+.iP "u" 15
+Undoes the last change made to the current buffer.  If repeated, will
+alternate between these two states, thus is its own inverse. When used
+after an insert which inserted text on more than one line, the lines are
+saved in the numeric named buffers (3.5).
+.iP "v" 15
+Unused.
+.iP "w" 15
+Advances to the beginning of the next word, as defined by \fBb\fR (2.4).
+.iP "x" 15
+Deletes the single character under the cursor.  With a count deletes
+deletes that many characters forward from the cursor position, but only
+on the current line (6.5).
+.iP "y" 15
+An operator, yanks the following object into the unnamed temporary buffer.
+If preceded by a named buffer specification, \fB"\fR\fIx\fR, the text
+is placed in that buffer also.  Text can be recovered by a later \fBp\fR
+or \fBP\fR (7.4).
+.iP "z" 15
+Redraws the screen with the current line placed as specified by the following
+character: \s-2RETURN\s0 specifies the top of the screen, \fB.\fR the
+center of the screen, and \fB\-\fR at the bottom of the screen.
+A count may be given after the \fBz\fR and before the following character
+to specify the new screen size for the redraw.
+A count before the \fBz\fR gives the number of the line to place in the
+center of the screen instead of the default current line. (5.4)
+.iP "{" 15
+Retreats to the beginning of the beginning of the preceding paragraph.
+A paragraph begins at each macro in the \fIparagraphs\fR option, normally
+`.IP', `.LP', `.PP', `.QP' and `.bp'.
+A paragraph also begins after a completely
+empty line, and at each section boundary (see \fB[[\fR above) (4.2, 6.8,
+7.6).
+.iP "|" 15
+Places the cursor on the character in the column specified
+by the count (7.1, 7.2).
+.iP "}" 15
+Advances to the beginning of the next paragraph.  See \fB{\fR for the
+definition of paragraph (4.2, 6.8, 7.6).
+.iP "~" 15
+Unused.
+.iP "^?\ (\s-2\fRDEL\fP\s0)" 15
+Interrupts the editor, returning it to command accepting state (1.5,
+7.5)
+.bp
+\&.
diff --git a/dist/nvi/docs/vitut/vi.in b/dist/nvi/docs/vitut/vi.in
new file mode 100644 (file)
index 0000000..845099a
--- /dev/null
@@ -0,0 +1,2048 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: vi.in,v 8.5 1996/08/18 11:35:55 bostic Exp (Berkeley) Date: 1996/08/18 11:35:55
+.\"
+.nr LL 6.5i
+.nr FL 6.5i
+.EH 'USD:11-%''An Introduction to Display Editing with Vi'
+.OH 'An Introduction to Display Editing with Vi''USD:11-%'
+.bd S 3
+.if t .ds dg \(dg
+.if n .ds dg +
+.if t .ds dd \(dd
+.if n .ds dd ++
+.\".RP
+.TL
+An Introduction to Display Editing with Vi
+.AU
+William Joy
+.AU
+Mark Horton
+.AI
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, Ca.  94720
+.AB
+.PP
+.I Vi
+(visual) is a display oriented interactive text editor.
+When using
+.I vi
+the screen of your terminal acts as a window into the file which you
+are editing.  Changes which you make to the file are reflected
+in what you see.
+.PP
+Using
+.I vi
+you can insert new text any place in the file quite easily.
+Most of the commands to
+.I vi
+move the cursor around in the file.
+There are commands to move the cursor
+forward and backward in units of characters, words,
+sentences and paragraphs.
+A small set of operators, like
+.B d
+for delete and
+.B c
+for change, are combined with the motion commands to form operations
+such as delete word or change paragraph, in a simple and natural way.
+This regularity and the mnemonic assignment of commands to keys makes the
+editor command set easy to remember and to use.
+.PP
+.I Vi
+will work on a large number of display terminals,
+and new terminals are easily driven after editing a terminal description file.
+While it is advantageous to have an intelligent terminal which can locally
+insert and delete lines and characters from the display, the editor will
+function quite well on dumb terminals over slow phone lines.
+The editor makes allowance for the low bandwidth in these situations
+and uses smaller window sizes and
+different display updating algorithms to make best use of the
+limited speed available.
+.PP
+It is also possible to use the command set of
+.I vi
+on hardcopy terminals, storage tubes and ``glass tty's'' using a one line
+editing window; thus
+.I vi's
+command set is available on all terminals.
+The full command set of the more traditional, line
+oriented editor
+.I ex
+is available within
+.I vi;
+it is quite simple to switch between the two modes of editing.
+.AE
+.NH 1
+Getting started
+.PP
+.FS
+The financial support of an \s-2IBM\s0 Graduate Fellowship and the
+National Science Foundation under grants MCS74-07644-A03 and MCS78-07291
+is gratefully acknowledged.
+.FE
+This document provides a quick introduction to
+.I vi.
+(Pronounced \fIvee-eye\fP.)
+You should be running
+.I vi
+on a file you are familiar with while you are reading this.
+The first part of this document (sections 1 through 5)
+describes the basics of using
+.I vi.
+Some topics of special interest are presented in section 6, and 
+some nitty-gritty details of how the editor functions are saved for section
+7 to avoid cluttering the presentation here.
+.PP
+There is also a short appendix here, which gives for each character the
+special meanings which this character has in \fIvi\fR.  Attached to
+this document should be a quick reference card.
+This card summarizes the commands of
+.I vi
+in a very compact format.  You should have the card handy while you are
+learning
+.I vi.
+.NH 2
+Specifying terminal type
+.PP
+Before you can start
+.I vi
+you must tell the system what kind of terminal you are using.
+Here is a (necessarily incomplete) list of terminal type codes.
+If your terminal does not appear here, you should consult with one of
+the staff members on your system to find out the code for your terminal.
+If your terminal does not have a code, one can be assigned and a description
+for the terminal can be created.
+.LP
+.TS
+center;
+ab ab ab
+a a a.
+Code   Full name       Type
+_
+2621   Hewlett-Packard 2621A/P Intelligent
+2645   Hewlett-Packard 264x    Intelligent
+act4   Microterm ACT-IV        Dumb
+act5   Microterm ACT-V Dumb
+adm3a  Lear Siegler ADM-3a     Dumb
+adm31  Lear Siegler ADM-31     Intelligent
+c100   Human Design Concept 100        Intelligent
+dm1520 Datamedia 1520  Dumb
+dm2500 Datamedia 2500  Intelligent
+dm3025 Datamedia 3025  Intelligent
+fox    Perkin-Elmer Fox        Dumb
+h1500  Hazeltine 1500  Intelligent
+h19    Heathkit h19    Intelligent
+i100   Infoton 100     Intelligent
+mime   Imitating a smart act4  Intelligent
+t1061  Teleray 1061    Intelligent
+vt52   Dec VT-52       Dumb
+.TE
+.PP
+Suppose for example that you have a Hewlett-Packard HP2621A
+terminal.  The code used by the system for this terminal is `2621'.
+In this case you can use one of the following commands to tell the system
+the type of your terminal:
+.DS
+% \fBsetenv TERM\fP 2621
+.DE
+This command works with the
+.I csh
+shell.
+If you are using the standard Bourne shell
+.I sh
+then you should give the commands
+.DS
+$ \fBTERM=\fP2621
+$ \fBexport TERM\fP
+.DE
+.PP
+If you want to arrange to have your terminal type set up automatically
+when you log in, you can use the
+.I tset
+program.
+If you dial in on a
+.I mime ,
+but often use hardwired ports, a typical line for your
+.I .login
+file (if you use csh) would be
+.DS
+\fBsetenv TERM \(gatset\fP \- \-d mime\(ga
+.DE
+or for your
+.I .profile
+file (if you use sh)
+.DS
+\fBTERM=\(gatse\fPt \- \-d mime\(ga
+.DE
+.I Tset
+knows which terminals are hardwired to each port
+and needs only to be told that when you dial in you
+are probably on a
+.I mime .
+.I Tset
+is usually used to change the erase and kill characters, too.
+.NH 2
+Editing a file
+.PP
+After telling the system which kind of terminal you have, you should
+make a copy of a file you are familiar with, and run
+.I vi
+on this file, giving the command
+.DS
+% \fBvi\fR \fIname\fR
+.DE
+replacing \fIname\fR with the name of the copy file you just created.
+The screen should clear and the text of your file should appear on the
+screen.  If something else happens refer to the footnote.\*(dd
+.FS
+\*(dd If you gave the system an incorrect terminal type code then the
+editor may have just made a mess out of your screen.  This happens when
+it sends control codes for one kind of terminal to some other
+kind of terminal.  In this case hit
+the keys \fB:q\fR (colon and the q key) and then hit the \s-2RETURN\s0 key.
+This should get you back to the command level interpreter.
+Figure out what you did wrong (ask someone else if necessary) and try again.
+     Another thing which can go wrong is that you typed the wrong file name and
+the editor just printed an error diagnostic.  In this case you should
+follow the above procedure for getting out of the editor, and try again
+this time spelling the file name correctly.
+     If the editor doesn't seem to respond to the commands which you type
+here, try sending an interrupt to it by hitting the \s-2DEL\s0 or \s-2RUB\s0
+key on your terminal, and then hitting the \fB:q\fR command again followed
+by a carriage return.
+.sp
+.FE
+.NH 2
+The editor's copy: the buffer
+.PP
+The editor does not directly modify the file which you are editing. 
+Rather, the editor makes a copy of this file, in a place called the
+.I buffer,
+and remembers the file's
+name.  You do not affect the contents of the file unless and until you
+write the changes you make back into the original file.
+.NH 2
+Notational conventions
+.PP
+In our examples, input which must be typed as is will be presented in
+\fBbold face\fR. Text which should be replaced with appropriate input
+will be given in \fIitalics\fR.  We will represent special characters
+in \s-2SMALL CAPITALS\s0.
+.NH 2
+Arrow keys
+.PP
+The editor command set is independent of the terminal
+you are using.  On most terminals with cursor positioning keys, these keys
+will also work within the editor.
+If you don't have cursor positioning keys, or even if you do, you can use
+the \fBh j k\fR and \fBl\fR keys as cursor positioning
+keys (these are labelled with arrows on an
+.I adm3a).*
+.PP
+(Particular note for the HP2621: on this terminal the function keys
+must be \fIshifted\fR (ick) to send to the machine, otherwise they
+only act locally.  Unshifted use will leave the cursor positioned
+incorrectly.)
+.FS
+* As we will see later,
+.I h
+moves back to the left (like control-h which is a backspace),
+.I j
+moves down (in the same column),
+.I k
+moves up (in the same column),
+and
+.I l
+moves to the right.
+.FE
+.NH 2
+Special characters: \s-2ESC\s0, \s-2CR\s0 and \s-2DEL\s0
+.PP
+Several of these special characters are very important, so be sure to
+find them right now.  Look on your keyboard for a key labelled \s-2ESC\s0
+or \s-2ALT\s0.  It should be near the upper left corner of your terminal.
+Try hitting this key a few times.  The editor will ring the bell
+to indicate that it is in a quiescent state.\*(dd
+.FS
+\*(dd On smart terminals where it is possible, the editor will quietly
+flash the screen rather than ringing the bell.
+.FE
+Partially formed commands are cancelled by \s-2ESC\s0, and when you insert
+text in the file you end the text insertion
+with \s-2ESC\s0.  This key is a fairly
+harmless one to hit, so you can just hit it if you don't know
+what is going on until the editor rings the bell.
+.PP
+The \s-2CR\s0 or \s-2RETURN\s0 key is important because it is used
+to terminate certain commands.
+It is usually at the right side of the keyboard,
+and is the same command used at the end of each shell command.
+.PP
+Another very useful key is the \s-2DEL\s0 or \s-2RUB\s0 key, which generates
+an interrupt, telling the editor to stop what it is doing.
+It is a forceful way of making the editor listen
+to you, or to return it to the quiescent state if you don't know or don't
+like what is going on.  Try hitting the `/' key on your terminal.  This
+key is used when you want to specify a string to be searched for.  The
+cursor should now be positioned at the bottom line of the terminal after
+a `/' printed as a prompt.  You can get the cursor back to the current
+position by hitting the \s-2DEL\s0 or \s-2RUB\s0 key; try this now.*
+.FS
+* Backspacing over the `/' will also cancel the search.
+.FE
+From now on we will simply refer to hitting the \s-2DEL\s0 or \s-2RUB\s0
+key as ``sending an interrupt.''**
+.FS
+** On some systems, this interruptibility comes at a price: you cannot type
+ahead when the editor is computing with the cursor on the bottom line.
+.FE
+.PP
+The editor often echoes your commands on the last line of the terminal.
+If the cursor is on the first position of this last line, then the editor
+is performing a computation, such as computing a new position in the
+file after a search or running a command to reformat part of the buffer.
+When this is happening you can stop the editor by
+sending an interrupt.
+.NH 2
+Getting out of the editor
+.PP
+After you have worked with this introduction for a while, and you wish
+to do something else, you can give the command \fBZZ\fP
+to the editor.
+This will write the contents of the editor's buffer back into
+the file you are editing, if you made any changes, and then quit from
+the editor.  You can also end an editor
+session by giving the command \fB:q!\fR\s-2CR\s0;\*(dg
+.FS
+\*(dg All commands which read from the last display line can also be
+terminated with a \s-2ESC\s0 as well as an \s-2CR\s0.
+.FE
+this is a dangerous but occasionally essential
+command which ends the editor session and discards all your changes.
+You need to know about this command in case you change the editor's
+copy of a file you wish only to look at.  Be very careful
+not to give this command when you really want to save
+the changes you have made.
+.NH 1
+Moving around in the file
+.NH 2
+Scrolling and paging
+.PP
+The editor has a number of commands for moving around in the file.
+The most useful of these is generated by hitting the control and D keys
+at the same time, a control-D or `^D'.  We will use this two character
+notation for referring to these control keys from now on.  You may have
+a key labelled `^' on your terminal.  This key will be represented as `\(ua'
+in this document; `^' is exclusively used as part of the `^x' notation
+for control characters.\*(dd
+.FS
+\*(dd If you don't have a `^' key on your terminal
+then there is probably a key labelled `\(ua'; in any case these characters
+are one and the same.
+.FE
+.PP
+As you know now if you tried hitting \fB^D\fR, this command scrolls down in
+the file.  The \fBD\fR thus stands for down.  Many editor commands are mnemonic
+and this makes them much easier to remember.  For instance the command
+to scroll up is \fB^U\fR.  Many dumb terminals can't scroll up at all, in which
+case hitting \fB^U\fR clears the screen and refreshes it
+with a line which is farther back in the file at the top.
+.PP
+If you want to see more of the file below where you are, you can
+hit \fB^E\fR to expose one more line at the bottom of the screen,
+leaving the cursor where it is.
+The command \fB^Y\fR (which is hopelessly non-mnemonic, but next to \fB^U\fR
+on the keyboard) exposes one more line at the top of the screen.
+.PP
+There are other ways to move around in the file; the keys \fB^F\fR and \fB^B\fR
+move forward and backward a page,
+keeping a couple of lines of continuity between screens
+so that it is possible to read through a file using these rather than
+\fB^D\fR and \fB^U\fR if you wish.
+.PP
+Notice the difference between scrolling and paging.  If you are trying
+to read the text in a file, hitting \fB^F\fR to move forward a page
+will leave you only a little context to look back at.  Scrolling on the
+other hand leaves more context, and happens more smoothly.  You can continue
+to read the text as scrolling is taking place.
+.NH 2
+Searching, goto, and previous context
+.PP
+Another way to position yourself in the file is by giving the editor a string
+to search for.  Type the character \fB/\fR followed by a string of characters
+terminated by \s-2CR\s0.  The editor will position the cursor
+at the next occurrence of this string.
+Try hitting \fBn\fR to then go to the next occurrence of this string.
+The character \fB?\fR will search backwards from where you are, and is
+otherwise like \fB/\fR.\*(dg
+.FS
+\*(dg These searches will normally wrap around the end of the file, and thus
+find the string even if it is not on a line in the direction you search
+provided it is anywhere else in the file.  You can disable this wraparound
+in scans by giving the command \fB:se nowrapscan\fR\s-2CR\s0,
+or more briefly \fB:se nows\fR\s-2CR\s0.
+.FE
+.PP
+If the search string you give the editor is not present in the
+file the editor will print
+a diagnostic on the last line of the screen, and the cursor will be returned
+to its initial position.
+.PP
+If you wish the search to match only at the beginning of a line, begin
+the search string with an \fB\(ua\fR.  To match only at the end of
+a line, end the search string with a \fB$\fR.
+Thus \fB/\(uasearch\fR\s-2CR\s0 will search for the word `search' at
+the beginning of a line, and \fB/last$\fR\s-2CR\s0 searches for the
+word `last' at the end of a line.*
+.FS
+*Actually, the string you give to search for here can be a
+.I "regular expression"
+in the sense of the editors
+.I ex (1)
+and
+.I ed (1).
+If you don't wish to learn about this yet, you can disable this more
+general facility by doing
+\fB:se\ nomagic\fR\s-2CR\s0;
+by putting this command in
+EXINIT
+in your environment, you can have this always be in effect (more
+about
+.I EXINIT
+later.)
+.FE
+.PP
+The command \fBG\fR, when preceded by a number will position the cursor
+at that line in the file.
+Thus \fB1G\fR will move the cursor to
+the first line of the file.  If you give \fBG\fR no count, then it moves
+to the end of the file.
+.PP
+If you are near the end of the file, and the last line is not at the bottom
+of the screen, the editor will place only the character `~' on each remaining
+line.  This indicates that the last line in the file is on the screen;
+that is, the `~' lines are past the end of the file.
+.PP
+You can find out the state of the file you are editing by typing a \fB^G\fR.
+The editor will show you the name of the file you are editing, the number
+of the current line, the number of lines in the buffer, and the percentage
+of the way through the buffer which you are.
+Try doing this now, and remember the number of the line you are on.
+Give a \fBG\fR command to get to the end and then another \fBG\fR command
+to get back where you were.
+.PP
+You can also get back to a previous position by using the command
+\fB\(ga\(ga\fR (two back quotes).
+This is often more convenient than \fBG\fR because it requires no advance
+preparation.
+Try giving a \fBG\fR or a search with \fB/\fR or \fB?\fR and then a
+\fB\(ga\(ga\fR to get back to where you were.  If you accidentally hit
+\fBn\fR or any command which moves you far away from a context of interest, you
+can quickly get back by hitting \fB\(ga\(ga\fR.
+.NH 2
+Moving around on the screen
+.PP
+Now try just moving the cursor around on the screen.
+If your terminal has arrow keys (4 or 5 keys with arrows
+going in each direction) try them and convince yourself
+that they work.
+If you don't have working arrow keys, you can always use
+.B h ,
+.B j ,
+.B k ,
+and
+.B l .
+Experienced users of
+.I vi
+prefer these keys to arrow keys,
+because they are usually right underneath their fingers.
+.PP
+Hit the \fB+\fR key.  Each time you do, notice that the cursor
+advances to the next line in the file, at the first non-white position
+on the line.  The \fB\-\fR key is like \fB+\fR but goes the other way.
+.PP
+These are very common keys for moving up and down lines in the file.
+Notice that if you go off the bottom or top with these keys then the
+screen will scroll down (and up if possible) to bring a line at a time
+into view.  The \s-2RETURN\s0 key has the same effect as the \fB+\fR
+key.
+.PP
+.I Vi
+also has commands to take you to the top, middle and bottom of the screen.
+\fBH\fR will take you to the top (home) line on the screen.
+Try preceding it with a
+number as in \fB3H\fR.
+This will take you to the third line on the screen.
+Many
+.I vi
+commands take preceding numbers and do interesting things with them.
+Try \fBM\fR,
+which takes you to the middle line on the screen,
+and \fBL\fR,
+which takes you to the last line on the screen.
+\fBL\fR also takes counts, thus
+\fB5L\fR will take you to the fifth line from the bottom.
+.NH 2
+Moving within a line
+.PP
+Now try picking a word on some line on the screen, not the
+first word on the line.
+move the cursor using \s-2RETURN\s0 and \fB\-\fR to be on the line where
+the word is.
+Try hitting the \fBw\fR key.  This will advance the cursor to the
+next word on the line.
+Try hitting the \fBb\fR key to back up words
+in the line.
+Also try the \fBe\fR key which advances you to the end of the current
+word rather than to the beginning of the next word.
+Also try \s-2SPACE\s0 (the space bar) which moves right one character
+and the \s-2BS\s0 (backspace or \fB^H\fR) key which moves left one character.
+The key \fBh\fR works as \fB^H\fR does and is useful if you don't have
+a \s-2BS\s0 key.
+(Also, as noted just above, \fBl\fR will move to the right.)
+.PP
+If the line had punctuation in it you may have noticed that
+that the \fBw\fR and \fBb\fR
+keys stopped at each group of punctuation.  You can also go back and
+forwards words without stopping at punctuation by using \fBW\fR and \fBB\fR
+rather than the lower case equivalents.  Think of these as bigger words.
+Try these on a few lines with punctuation to see how they differ from
+the lower case \fBw\fR and \fBb\fR.
+.PP
+The word keys wrap around the end of line,
+rather than stopping at the end.  Try moving to a word on a line below
+where you are by repeatedly hitting \fBw\fR.
+.NH 2
+Summary
+.IP
+.TS
+lw(.50i)b a.
+\fR\s-2SPACE\s0\fP     advance the cursor one position
+^B     backwards to previous page
+^D     scrolls down in the file
+^E     exposes another line at the bottom
+^F     forward to next page
+^G     tell what is going on
+^H     backspace the cursor
+^N     next line, same column
+^P     previous line, same column
+^U     scrolls up in the file
+^Y     exposes another line at the top
++      next line, at the beginning
+\-     previous line, at the beginning
+/      scan for a following string forwards
+?      scan backwards
+B      back a word, ignoring punctuation
+G      go to specified line, last default
+H      home screen line
+M      middle screen line
+L      last screen line
+W      forward a word, ignoring punctuation
+b      back a word
+e      end of current word
+n      scan for next instance of \fB/\fR or \fB?\fR pattern
+w      word after this word
+.TE
+.NH 2
+View
+.PP
+If you want to use the editor to look at a file,
+rather than to make changes,
+invoke it as
+.I view
+instead of
+.I vi .
+This will set the
+.I readonly
+option which will prevent you from
+accidently overwriting the file.
+.sp
+.NH 1
+Making simple changes
+.NH 2
+Inserting
+.PP
+One of the most useful commands is the
+\fBi\fR (insert) command.
+After you type \fBi\fR, everything you type until you hit \s-2ESC\s0
+is inserted into the file.
+Try this now; position yourself to some word in the file and try inserting
+text before this word.
+If you are on an dumb terminal it will seem, for a minute,
+that some of the characters in your line have been overwritten, but they will
+reappear when you hit \s-2ESC\s0.
+.PP
+Now try finding a word which can, but does not, end in an `s'.
+Position yourself at this word and type \fBe\fR (move to end of word), then
+\fBa\fR for append and then `s\s-2ESC\s0' to terminate the textual insert.
+This sequence of commands can be used to easily pluralize a word.
+.PP
+Try inserting and appending a few times to make sure you understand how
+this works; \fBi\fR placing text to the left of the cursor, \fBa\fR to
+the right.
+.PP
+It is often the case that you want to add new lines to the file you are
+editing, before or after some specific line in the file.  Find a line
+where this makes sense and then give the command \fBo\fR to create a
+new line after the line you are on, or the command \fBO\fR to create
+a new line before the line you are on.  After you create a new line in
+this way, text you type up to an \s-2ESC\s0 is inserted on the new line.
+.PP
+Many related editor commands
+are invoked by the same letter key and differ only in that one is given
+by a lower
+case key and the other is given by
+an upper case key.  In these cases, the
+upper case key often differs from the lower case key in its sense of
+direction, with
+the upper case key working backward and/or up, while the lower case
+key moves forward and/or down.
+.PP
+Whenever you are typing in text, you can give many lines of input or
+just a few characters.
+To type in more than one line of text,
+hit a \s-2RETURN\s0 at the middle of your input.  A new line will be created
+for text, and you can continue to type.  If you are on a slow
+and dumb terminal the editor may choose to wait to redraw the
+tail of the screen, and will let you type over the existing screen lines.
+This avoids the lengthy delay which would occur if the editor attempted
+to keep the tail of the screen always up to date.  The tail of the screen will
+be fixed up, and the missing lines will reappear, when you hit \s-2ESC\s0.
+.PP
+While you are inserting new text, you can use the characters you normally use
+at the system command level (usually \fB^H\fR or \fB#\fR) to backspace
+over the last
+character which you typed, and the character which you use to kill input lines
+(usually \fB@\fR, \fB^X\fR, or \fB^U\fR)
+to erase the input you have typed on the current line.\*(dg
+.FS
+\*(dg In fact, the character \fB^H\fR (backspace) always works to erase the
+last input character here, regardless of what your erase character is.
+.FE
+The character \fB^W\fR
+will erase a whole word and leave you after the space after the previous
+word; it is useful for quickly backing up in an insert.
+.PP
+Notice that when you backspace during an insertion the characters you
+backspace over are not erased; the cursor moves backwards, and the characters
+remain on the display.  This is often useful if you are planning to type
+in something similar.  In any case the characters disappear when when
+you hit \s-2ESC\s0; if you want to get rid of them immediately, hit an
+\s-2ESC\s0 and then \fBa\fR again.
+.PP
+Notice also that you can't erase characters which you didn't insert, and that
+you can't backspace around the end of a line.  If you need to back up
+to the previous line to make a correction, just hit \s-2ESC\s0 and move
+the cursor back to the previous line.  After making the correction you
+can return to where you were and use the insert or append command again.
+.sp .5
+.NH 2
+Making small corrections
+.PP
+You can make small corrections in existing text quite easily.
+Find a single character which is wrong or just pick any character.
+Use the arrow keys to find the character, or
+get near the character with the word motion keys and then either
+backspace (hit the \s-2BS\s0 key or \fB^H\fR or even just \fBh\fR) or 
+\s-2SPACE\s0 (using the space bar)
+until the cursor is on the character which is wrong.
+If the character is not needed then hit the \fBx\fP key; this deletes
+the character from the file.  It is analogous to the way you \fBx\fP
+out characters when you make mistakes on a typewriter (except it's not
+as messy).
+.PP
+If the character
+is incorrect, you can replace it with the correct character by giving
+the command \fBr\fR\fIc\fR,
+where \fIc\fR is replaced by the correct character.
+Finally if the character which is incorrect should be replaced
+by more than one character, give the command \fBs\fR which substitutes
+a string of characters, ending with \s-2ESC\s0, for it.
+If there are a small number of characters
+which are wrong you can precede \fBs\fR with a count of the number of
+characters to be replaced.  Counts are also useful with \fBx\fR to specify
+the number of characters to be deleted.
+.NH 2
+More corrections: operators
+.PP
+You already know almost enough to make changes at a higher level.
+All you need to know now is that the 
+.B d
+key acts as a delete operator.  Try the command
+.B dw
+to delete a word.
+Try hitting \fB.\fR a few times.  Notice that this repeats the effect
+of the \fBdw\fR.  The command \fB.\fR repeats the last command which
+made a change.  You can remember it by analogy with an ellipsis `\fB...\fR'.
+.PP
+Now try
+\fBdb\fR.
+This deletes a word backwards, namely the preceding word.
+Try 
+\fBd\fR\s-2SPACE\s0.  This deletes a single character, and is equivalent
+to the \fBx\fR command.
+.PP
+Another very useful operator is
+.B c
+or change.  The command 
+.B cw
+thus changes the text of a single word.
+You follow it by the replacement text ending with an \s-2ESC\s0.
+Find a word which you can change to another, and try this
+now.
+Notice that the end of the text to be changed was marked with the character
+`$' so that you can see this as you are typing in the new material.
+.sp .5
+.NH 2
+Operating on lines
+.PP
+It is often the case that you want to operate on lines.
+Find a line which you want to delete, and type 
+\fBdd\fR,
+the
+.B d
+operator twice.  This will delete the line.
+If you are on a dumb terminal, the editor may just erase the line on
+the screen, replacing it with a line with only an @ on it.  This line
+does not correspond to any line in your file, but only acts as a place
+holder.  It helps to avoid a lengthy redraw of the rest of the screen
+which would be necessary to close up the hole created by the deletion
+on a terminal without a delete line capability.
+.PP
+Try repeating the
+.B c
+operator twice; this will change a whole line, erasing its previous contents and
+replacing them with text you type up to an \s-2ESC\s0.\*(dg
+.FS
+\*(dg The command \fBS\fR is a convenient synonym for for \fBcc\fR, by
+analogy with \fBs\fR.  Think of \fBS\fR as a substitute on lines, while
+\fBs\fR is a substitute on characters.
+.FE
+.PP
+You can delete or change more than one line by preceding the
+.B dd
+or
+.B cc
+with a count, i.e. \fB5dd\fR deletes 5 lines.
+You can also give a command like \fBdL\fR to delete all the lines up to
+and including
+the last line on the screen, or \fBd3L\fR to delete through the third from
+the bottom line.  Try some commands like this now.*
+.FS
+* One subtle point here involves using the \fB/\fR search after a \fBd\fR.
+This will normally delete characters from the current position to the
+point of the match.  If what is desired is to delete whole lines
+including the two points, give the pattern as \fB/pat/+0\fR, a line address.
+.FE
+Notice that the editor lets you know when you change a large number of
+lines so that you can see the extent of the change.
+The editor will also always tell you when a change you make affects text which
+you cannot see.
+.NH 2
+Undoing
+.PP
+Now suppose that the last change which you made was incorrect;
+you could use the insert, delete and append commands to put the correct
+material back.  However, since it is often the case that we regret a
+change or make a change incorrectly, the editor provides a
+.B u
+(undo) command to reverse the last change which you made.
+Try this a few times, and give it twice in a row to notice that an
+.B u
+also undoes a
+.B u.
+.PP
+The undo command lets you reverse only a single change.  After you make
+a number of changes to a line, you may decide that you would rather have
+the original state of the line back.  The
+.B U
+command restores the current line to the state before you started changing
+it.
+.PP
+You can recover text which you delete, even if
+undo will not bring it back; see the section on recovering lost text
+below.
+.NH 2
+Summary
+.IP
+.TS
+lw(.50i)b a.
+\fR\s-2SPACE\s0\fP     advance the cursor one position
+^H     backspace the cursor
+^W     erase a word during an insert
+\fRerase\fP    your erase (usually ^H or #), erases a character during an insert
+\fRkill\fP     your kill (usually @, ^X, or ^U), kills the insert on this line
+\&\fB.\fP      repeats the changing command
+O      opens and inputs new lines, above the current
+U      undoes the changes you made to the current line
+a      appends text after the cursor
+c      changes the object you specify to the following text
+d      deletes the object you specify
+i      inserts text before the cursor
+o      opens and inputs new lines, below the current
+u      undoes the last change
+.TE
+.NH 1
+Moving about; rearranging and duplicating text
+.NH 2
+Low level character motions
+.PP
+Now move the cursor to a line where there is a punctuation or a bracketing
+character such as a parenthesis or a comma or period.  Try the command
+\fBf\fR\fIx\fR where \fIx\fR is this character.  This command finds
+the next \fIx\fR character to the right of the cursor in the current
+line.  Try then hitting a \fB;\fR, which finds the next instance of the
+same character.  By using the \fBf\fR command and then a sequence of
+\fB;\fR's you can often
+get to a particular place in a line much faster than with a sequence
+of word motions or \s-2SPACE\s0s.
+There is also a \fBF\fR command, which is like \fBf\fR, but searches 
+backward.  The \fB;\fR command repeats \fBF\fR also.
+.PP
+When you are operating on the text in a line it is often desirable to
+deal with the characters up to, but not including, the first instance of
+a character.  Try \fBdf\fR\fIx\fR for some \fIx\fR now and
+notice that the \fIx\fR character is deleted.  Undo this with \fBu\fR
+and then try \fBdt\fR\fIx\fR;  the \fBt\fR here stands for to, i.e.
+delete up to the next \fIx\fR, but not the \fIx\fR.  The command \fBT\fR
+is the reverse of \fBt\fR.
+.PP
+When working with the text of a single line, an \fB\(ua\fR moves the
+cursor to the first non-white position on the line, and a
+\fB$\fR moves it to the end of the line.  Thus \fB$a\fR will append new
+text at the end of the current line.
+.PP
+Your file may have tab (\fB^I\fR) characters in it.  These
+characters are represented as a number of spaces expanding to a tab stop,
+where tab stops are every 8 positions.*
+.FS
+* This is settable by a command of the form \fB:se ts=\fR\fIx\fR\s-2CR\s0,
+where \fIx\fR is 4 to set tabstops every four columns.  This has
+effect on the screen representation within the editor.
+.FE
+When the cursor is at a tab, it sits on the last of the several spaces
+which represent that tab.  Try moving the cursor back and forth over
+tabs so you understand how this works.
+.PP
+On rare occasions, your file may have nonprinting characters in it. 
+These characters are displayed in the same way they are represented in
+this document, that is with a two character code, the first character
+of which is `^'.  On the screen non-printing characters resemble a `^'
+character adjacent to another, but spacing or backspacing over the character
+will reveal that the two characters are, like the spaces representing
+a tab character, a single character.
+.PP
+The editor sometimes discards control characters,
+depending on the character and the setting of the
+.I beautify
+option,
+if you attempt to insert them in your file.
+You can get a control character in the file by beginning
+an insert and then typing a \fB^V\fR before the control
+character.  The
+\fB^V\fR quotes the following character, causing it to be
+inserted directly into the file.
+.PP
+.NH 2
+Higher level text objects
+.PP
+In working with a document it is often advantageous to work in terms
+of sentences, paragraphs, and sections.  The operations \fB(\fR and \fB)\fR
+move to the beginning of the previous and next sentences respectively.
+Thus the command \fBd)\fR will delete the rest of the current sentence;
+likewise \fBd(\fR will delete the previous sentence if you are at the
+beginning of the current sentence, or the current sentence up to where
+you are if you are not at the beginning of the current sentence.
+.PP
+A sentence is defined to end at a `.', `!' or `?' which is followed by
+either the end of a line, or by two spaces.  Any number of closing `)',
+`]', `"' and `\(aa' characters may appear after the `.', `!' or `?' before
+the spaces or end of line.
+.PP
+The operations \fB{\fR and \fB}\fR move over paragraphs and the operations
+\fB[[\fR and \fB]]\fR move over sections.\*(dg
+.FS
+\*(dg The \fB[[\fR and \fB]]\fR operations
+require the operation character to be doubled because they can move the
+cursor far from where it currently is.  While it is easy to get back
+with the command \fB\(ga\(ga\fP,
+these commands would still be frustrating
+if they were easy to hit accidentally.
+.FE
+.PP
+A paragraph begins after each empty line, and also
+at each of a set of paragraph macros, specified by the pairs of characters
+in the definition of the string valued option \fIparagraphs\fR.
+The default setting for this option defines the paragraph macros of the
+\fI\-ms\fR and \fI\-mm\fR macro packages, i.e. the `.IP', `.LP', `.PP'
+and `.QP', `.P' and `.LI' macros.\*(dd
+.FS
+\*(dd You can easily change or extend this set of macros by assigning a
+different string to the \fIparagraphs\fR option in your EXINIT.
+See section 6.2 for details.
+The `.bp' directive is also considered to start a paragraph.
+.FE
+Each paragraph boundary is also a sentence boundary.  The sentence
+and paragraph commands can
+be given counts to operate over groups of sentences and paragraphs.
+.PP
+Sections in the editor begin after each macro in the \fIsections\fR option,
+normally `.NH', `.SH', `.H' and `.HU', and each line with a formfeed \fB^L\fR
+in the first column.
+Section boundaries are always line and paragraph boundaries also.
+.PP
+Try experimenting with the sentence and paragraph commands until you are
+sure how they work.  If you have a large document, try looking through
+it using the section commands.
+The section commands interpret a preceding count as a different window size in
+which to redraw the screen at the new location, and this window size
+is the base size for newly drawn windows until another size is specified.
+This is very useful
+if you are on a slow terminal and are looking for a particular section. 
+You can give the first section command a small count to then see each successive
+section heading in a small window.
+.NH 2
+Rearranging and duplicating text
+.PP
+The editor has a single unnamed buffer where the last deleted or
+changed away text is saved, and a set of named buffers \fBa\fR\-\fBz\fR
+which you can use to save copies of text and to move text around in
+your file and between files.
+.PP
+The operator
+.B y
+yanks a copy of the object which follows into the unnamed buffer.
+If preceded by a buffer name, \fB"\fR\fIx\fR\|\fBy\fR, where
+\fIx\fR here is replaced by a letter \fBa\-z\fR, it places the text in the named
+buffer.  The text can then be put back in the file with the commands
+.B p
+and
+.B P;
+\fBp\fR puts the text after or below the cursor, while \fBP\fR puts the text
+before or above the cursor.
+.PP
+If the text which you
+yank forms a part of a line, or is an object such as a sentence which
+partially spans more than one line, then when you put the text back,
+it will be placed after the cursor (or before if you
+use \fBP\fR).  If the yanked text forms whole lines, they will be put
+back as whole lines, without changing the current line.  In this case,
+the put acts much like a \fBo\fR or \fBO\fR command.
+.PP
+Try the command \fBYP\fR.  This makes a copy of the current line and
+leaves you on this copy, which is placed before the current line.
+The command \fBY\fR is a convenient abbreviation for \fByy\fR.
+The command \fBYp\fR will also make a copy of the current line, and place
+it after the current line.  You can give \fBY\fR a count of lines to
+yank, and thus duplicate several lines; try \fB3YP\fR.
+.PP
+To move text within the buffer, you need to delete it in one place, and
+put it back in another.  You can precede a delete operation by the
+name of a buffer in which the text is to be stored as in \fB"a5dd\fR
+deleting 5 lines into the named buffer \fIa\fR.  You can then move the
+cursor to the eventual resting place of the these lines and do a \fB"ap\fR
+or \fB"aP\fR to put them back.
+In fact, you can switch and edit another file before you put the lines
+back, by giving a command of the form \fB:e \fR\fIname\fR\s-2CR\s0 where
+\fIname\fR is the name of the other file you want to edit.  You will
+have to write back the contents of the current editor buffer (or discard
+them) if you have made changes before the editor will let you switch
+to the other file.
+An ordinary delete command saves the text in the unnamed buffer,
+so that an ordinary put can move it elsewhere.
+However, the unnamed buffer is lost when you change files,
+so to move text from one file to another you should use an unnamed buffer.
+.NH 2
+Summary.
+.IP
+.TS
+lw(.50i)b a.
+\(ua   first non-white on line
+$      end of line
+)      forward sentence
+}      forward paragraph
+]]     forward section
+(      backward sentence
+{      backward paragraph
+[[     backward section
+f\fIx\fR       find \fIx\fR forward in line
+p      put text back, after cursor or below current line
+y      yank operator, for copies and moves
+t\fIx\fR       up to \fIx\fR forward, for operators
+F\fIx\fR       f backward in line
+P      put text back, before cursor or above current line
+T\fIx\fR       t backward in line
+.TE
+.ne 1i
+.NH 1
+High level commands
+.NH 2
+Writing, quitting, editing new files
+.PP
+So far we have seen how to enter
+.I vi
+and to write out our file using either
+\fBZZ\fR or \fB:w\fR\s-2CR\s0. The first exits from
+the editor,
+(writing if changes were made),
+the second writes and stays in the editor.
+.PP
+If you have changed the editor's copy of the file but do not wish to
+save your changes, either because you messed up the file or decided that the
+changes are not an improvement to the file, then you can give the command
+\fB:q!\fR\s-2CR\s0 to quit from the editor without writing the changes.
+You can also reedit the same file (starting over) by giving the command
+\fB:e!\fR\s-2CR\s0.  These commands should be used only rarely, and with
+caution, as it is not possible to recover the changes you have made after
+you discard them in this manner.
+.PP
+You can edit a different file without leaving the editor by giving the
+command \fB:e\fR\ \fIname\fR\s-2CR\s0.  If you have not written out
+your file before you try to do this, then the editor will tell you this,
+and delay editing the other file.  You can then give the command
+\fB:w\fR\s-2CR\s0 to save your work and then the \fB:e\fR\ \fIname\fR\s-2CR\s0
+command again, or carefully give the command \fB:e!\fR\ \fIname\fR\s-2CR\s0,
+which edits the other file discarding the changes you have made to the
+current file.
+To have the editor automatically save changes,
+include
+.I "set autowrite"
+in your EXINIT,
+and use \fB:n\fP instead of \fB:e\fP.
+.NH 2
+Escaping to a shell
+.PP
+You can get to a shell to execute a single command by giving a
+.I vi
+command of the form \fB:!\fIcmd\fR\s-2CR\s0.
+The system will run the single command
+.I cmd
+and when the command finishes, the editor will ask you to hit a \s-2RETURN\s0
+to continue.  When you have finished looking at the output on the screen,
+you should hit \s-2RETURN\s0 and the editor will clear the screen and
+redraw it.  You can then continue editing.
+You can also give another \fB:\fR command when it asks you for a \s-2RETURN\s0;
+in this case the screen will not be redrawn.
+.PP
+If you wish to execute more than one command in the shell, then you can
+give the command \fB:sh\fR\s-2CR\s0.
+This will give you a new shell, and when you finish with the shell, ending
+it by typing a \fB^D\fR, the editor will clear the screen and continue.
+.PP
+On systems which support it, \fB^Z\fP will suspend the editor
+and return to the (top level) shell.
+When the editor is resumed, the screen will be redrawn.
+.NH 2
+Marking and returning
+.PP
+The command \fB\(ga\(ga\fR returned to the previous place
+after a motion of the cursor by a command such as \fB/\fR, \fB?\fR or
+\fBG\fR.  You can also mark lines in the file with single letter tags
+and return to these marks later by naming the tags.  Try marking the
+current line with the command \fBm\fR\fIx\fR, where you should pick some
+letter for \fIx\fR, say `a'.  Then move the cursor to a different line
+(any way you like) and hit \fB\(gaa\fR.  The cursor will return to the
+place which you marked.
+Marks last only until you edit another file.
+.PP
+When using operators such as
+.B d
+and referring to marked lines, it is often desirable to delete whole lines
+rather than deleting to the exact position in the line marked by \fBm\fR.
+In this case you can use the form \fB\(aa\fR\fIx\fR rather than
+\fB\(ga\fR\fIx\fR.  Used without an operator, \fB\(aa\fR\fIx\fR will move to
+the first non-white character of the marked line; similarly \fB\(aa\(aa\fR
+moves to the first non-white character of the line containing the previous
+context mark \fB\(ga\(ga\fR.
+.NH 2
+Adjusting the screen
+.PP
+If the screen image is messed up because of a transmission error to your
+terminal, or because some program other than the editor wrote output
+to your terminal, you can hit a \fB^L\fR, the \s-2ASCII\s0 form-feed
+character, to cause the screen to be refreshed.
+.PP
+On a dumb terminal, if there are @ lines in the middle of the screen
+as a result of line deletion, you may get rid of these lines by typing
+\fB^R\fR to cause the editor to retype the screen, closing up these holes.
+.PP
+Finally, if you wish to place a certain line on the screen at the top
+middle or bottom of the screen, you can position the cursor to that line,
+and then give a \fBz\fR command.
+You should follow the \fBz\fR command with a \s-2RETURN\s0 if you want
+the line to appear at the top of the window, a \fB.\fR if you want it
+at the center, or a \fB\-\fR if you want it at the bottom.
+.NH 1
+Special topics
+.NH 2
+Editing on slow terminals
+.PP
+When you are on a slow terminal, it is important to limit the amount
+of output which is generated to your screen so that you will not suffer
+long delays, waiting for the screen to be refreshed.  We have already
+pointed out how the editor optimizes the updating of the screen during
+insertions on dumb terminals to limit the delays, and how the editor erases
+lines to @ when they are deleted on dumb terminals.
+.PP
+The use of the slow terminal insertion mode is controlled by the
+.I slowopen
+option.  You can force the editor to use this mode even on faster terminals
+by giving the command \fB:se slow\fR\s-2CR\s0.  If your system is sluggish
+this helps lessen the amount of output coming to your terminal.
+You can disable this option by \fB:se noslow\fR\s-2CR\s0.
+.PP
+The editor can simulate an intelligent terminal on a dumb one.  Try
+giving the command \fB:se redraw\fR\s-2CR\s0.  This simulation generates
+a great deal of output and is generally tolerable only on lightly loaded
+systems and fast terminals.  You can disable this by giving the command
+ \fB:se noredraw\fR\s-2CR\s0.
+.PP
+The editor also makes editing more pleasant at low speed by starting
+editing in a small window, and letting the window expand as you edit.
+This works particularly well on intelligent terminals.  The editor can
+expand the window easily when you insert in the middle of the screen
+on these terminals.  If possible, try the editor on an intelligent terminal
+to see how this works.
+.PP
+You can control the size of the window which is redrawn each time the
+screen is cleared by giving window sizes as argument to the commands
+which cause large screen motions:
+.DS
+.B ":  /  ?  [[  ]]  \(ga  \(aa"
+.DE
+Thus if you are searching for a particular instance of a common string
+in a file you can precede the first search command by a small number,
+say 3, and the editor will draw three line windows around each instance
+of the string which it locates.
+.PP
+You can easily expand or contract the window, placing the current line
+as you choose, by giving a number on a \fBz\fR command, after the \fBz\fR
+and before the following \s-2RETURN\s0, \fB.\fR or \fB\-\fR.  Thus the
+command \fBz5.\fR redraws the screen with the current line in the center
+of a five line window.\*(dg
+.FS
+\*(dg Note that the command \fB5z.\fR has an entirely different effect,
+placing line 5 in the center of a new window.
+.FE
+.PP
+If the editor is redrawing or otherwise updating large portions of the
+display, you can interrupt this updating by hitting a \s-2DEL\s0 or \s-2RUB\s0
+as usual.  If you do this you may partially confuse the editor about
+what is displayed on the screen.  You can still edit the text on
+the screen if you wish; clear up the confusion
+by hitting a \fB^L\fR; or move or search again, ignoring the
+current state of the display.
+.PP
+See section 7.8 on \fIopen\fR mode for another way to use the
+.I vi
+command set on slow terminals.
+.NH 2
+Options, set, and editor startup files
+.PP
+The editor has a set of options, some of which have been mentioned above.
+The most useful options are given in the following table.
+.PP
+The options are of three kinds:  numeric options, string options, and
+toggle options.  You can set numeric and string options by a statement
+of the form
+.DS
+\fBset\fR \fIopt\fR\fB=\fR\fIval\fR
+.DE
+and toggle options can be set or unset by statements of one of the forms
+.DS
+\fBset\fR \fIopt\fR
+\fBset\fR \fBno\fR\fIopt\fR
+.DE
+.KF
+.TS
+lb lb lb lb
+l l l a.
+Name   Default Description
+_
+autoindent     noai    Supply indentation automatically
+autowrite      noaw    Automatic write before \fB:n\fR, \fB:ta\fR, \fB^\(ua\fR, \fB!\fR
+ignorecase     noic    Ignore case in searching
+lisp   nolisp  \fB( { ) }\fR commands deal with S-expressions
+list   nolist  Tabs print as ^I; end of lines marked with $
+magic  nomagic The characters . [ and * are special in scans
+number nonu    Lines are displayed prefixed with line numbers
+paragraphs     para=IPLPPPQPbpP LI     Macro names which start paragraphs
+redraw nore    Simulate a smart terminal on a dumb one
+sections       sect=NHSHH HU   Macro names which start new sections
+shiftwidth     sw=8    Shift distance for <, > and input \fB^D\fP and \fB^T\fR
+showmatch      nosm    Show matching \fB(\fP or \fB{\fP as \fB)\fP or \fB}\fR is typed
+slowopen       slow    Postpone display updates during inserts
+term   dumb    The kind of terminal you are using.
+.TE
+.KE
+These statements can be placed in your EXINIT in your environment,
+or given while you are running
+.I vi
+by preceding them with a \fB:\fR and following them with a \s-2CR\s0.
+.PP
+You can get a list of all options which you have changed by the
+command \fB:set\fR\s-2CR\s0, or the value of a single option by the
+command \fB:set\fR \fIopt\fR\fB?\fR\s-2CR\s0.
+A list of all possible options and their values is generated by
+\fB:set all\fP\s-2CR\s0.
+Set can be abbreviated \fBse\fP.
+Multiple options can be placed on one line, e.g.
+\fB:se ai aw nu\fP\s-2CR\s0.
+.PP
+Options set by the \fBset\fP command only last
+while you stay in the editor.
+It is common to want to have certain options set whenever you
+use the editor.
+This can be accomplished by creating a list of \fIex\fP commands\*(dg
+.FS
+\*(dg
+All commands which start with
+.B :
+are \fIex\fP commands.
+.FE
+which are to be run every time you start up \fIex\fP, \fIedit\fP,
+or \fIvi\fP.
+A typical list includes a \fBset\fP command, and possibly a few
+\fBmap\fP commands.
+Since it is advisable to get these commands on one line, they can
+be separated with the | character, for example:
+.DS
+\fBset\fP ai aw terse|\fBmap\fP @ dd|\fBmap\fP # x
+.DE
+which sets the options \fIautoindent\fP, \fIautowrite\fP, \fIterse\fP,
+(the
+.B set
+command),
+makes @ delete a line,
+(the first
+.B map ),
+and makes # delete a character,
+(the second
+.B map ).
+(See section 6.9 for a description of the \fBmap\fP command)
+This string should be placed in the variable EXINIT in your environment.
+If you use the shell \fIcsh\fP,
+put this line in the file
+.I .login
+in your home directory:
+.DS
+setenv EXINIT \(aa\fBset\fP ai aw terse|\fBmap\fP @ dd|\fBmap\fP # x\(aa
+.DE
+If you use the standard shell \fIsh\fP,
+put these lines in the file
+.I .profile
+in your home directory:
+.DS
+EXINIT=\(aa\fBset\fP ai aw terse|\fBmap\fP @ dd|\fBmap\fP # x\(aa
+export EXINIT
+.DE
+Of course, the particulars of the line would depend on which options
+you wanted to set.
+.NH 2
+Recovering lost lines
+.PP
+You might have a serious problem if you delete a number of lines and then
+regret that they were deleted.  Despair not, the editor saves the last
+9 deleted blocks of text in a set of numbered registers 1\-9.
+You can get the \fIn\fR'th previous deleted text back in your file by
+the command
+"\fR\fIn\fR\|\fBp\fR.
+The "\fR here says that a buffer name is to follow,
+\fIn\fR is the number of the buffer you wish to try
+(use the number 1 for now),
+and
+.B p
+is the put command, which puts text in the buffer after the cursor.
+If this doesn't bring back the text you wanted, hit
+.B u
+to undo this and then
+\fB\&.\fR
+(period)
+to repeat the put command.
+In general the
+\fB\&.\fR
+command will repeat the last change you made.
+As a special case, when the last command refers to a numbered text buffer,
+the \fB.\fR command increments the number of the buffer before repeating
+the command.  Thus a sequence of the form
+.DS
+\fB"1pu.u.u.\fR
+.DE
+will, if repeated long enough, show you all the deleted text which has
+been saved for you.
+You can omit the
+.B u
+commands here to gather up all this text in the buffer, or stop after any
+\fB\&.\fR command to keep just the then recovered text.
+The command
+.B P
+can also be used rather than
+.B p
+to put the recovered text before rather than after the cursor.
+.NH 2
+Recovering lost files
+.PP
+If the system crashes, you can recover the work you were doing
+to within a few changes.  You will normally receive mail when you next
+login giving you the name of the file which has been saved for you. 
+You should then change to the directory where you were when the system
+crashed and give a command of the form:
+.DS
+% \fBvi \-r\fR \fIname\fR
+.DE
+replacing \fIname\fR with the name of the file which you were editing.
+This will recover your work to a point near where you left off.\*(dg
+.FS
+\*(dg In rare cases, some of the lines of the file may be lost.  The
+editor will give you the numbers of these lines and the text of the lines
+will be replaced by the string `LOST'.  These lines will almost always
+be among the last few which you changed.  You can either choose to discard
+the changes which you made (if they are easy to remake) or to replace
+the few lost lines by hand.
+.FE
+.PP
+You can get a listing of the files which are saved for you by giving
+the command:
+.DS
+% \fBvi \-r\fR
+.DE
+If there is more than one instance of a particular file saved, the editor
+gives you the newest instance each time you recover it.  You can thus
+get an older saved copy back by first recovering the newer copies.
+.PP
+For this feature to work,
+.I vi
+must be correctly installed by a super user on your system,
+and the
+.I mail
+program must exist to receive mail.
+The invocation ``\fIvi -r\fP'' will not always list all saved files,
+but they can be recovered even if they are not listed.
+.NH 2
+Continuous text input
+.PP
+When you are typing in large amounts of text it is convenient to have
+lines broken near the right margin automatically.  You can cause this
+to happen by giving the command
+\fB:se wm=10\fR\s-2CR\s0.
+This causes all lines to be broken at a space at least 10 columns
+from the right hand edge of the screen.
+.PP
+If the editor breaks an input line and you wish to put it back together
+you can tell it to join the lines with \fBJ\fR.  You can give \fBJ\fR
+a count of the number of lines to be joined as in \fB3J\fR to join 3
+lines.  The editor supplies white space, if appropriate,
+at the juncture of the joined
+lines, and leaves the cursor at this white space.
+You can kill the white space with \fBx\fR if you don't want it.
+.NH 2
+Features for editing programs
+.PP
+The editor has a number of commands for editing programs.
+The thing that most distinguishes editing of programs from editing of text
+is the desirability of maintaining an indented structure to the body of
+the program.  The editor has a
+.I autoindent
+facility for helping you generate correctly indented programs.
+.PP
+To enable this facility you can give the command \fB:se ai\fR\s-2CR\s0.
+Now try opening a new line with \fBo\fR and type some characters on the
+line after a few tabs.  If you now start another line, notice that the
+editor supplies white space at the beginning of the line to line it up
+with the previous line.  You cannot backspace over this indentation,
+but you can use \fB^D\fR key to backtab over the supplied indentation.
+.PP
+Each time you type \fB^D\fR you back up one position, normally to an
+8 column boundary.  This amount is settable; the editor has an option
+called
+.I shiftwidth
+which you can set to change this value.
+Try giving the command \fB:se sw=4\fR\s-2CR\s0
+and then experimenting with autoindent again.
+.PP
+For shifting lines in the program left and right, there are operators
+.B <
+and
+.B >.
+These shift the lines you specify right or left by one
+.I shiftwidth.
+Try
+.B <<
+and
+.B >>
+which shift one line left or right, and
+.B <L
+and
+.B >L
+shifting the rest of the display left and right.
+.PP
+If you have a complicated expression and wish to see how the parentheses
+match, put the cursor at a left or right parenthesis and hit \fB%\fR.
+This will show you the matching parenthesis.
+This works also for braces { and }, and brackets [ and ].
+.PP
+If you are editing C programs, you can use the \fB[[\fR and \fB]]\fR keys
+to advance or retreat to a line starting with a \fB{\fR, i.e. a function
+declaration at a time.  When \fB]]\fR is used with an operator it stops
+after a line which starts with \fB}\fR; this is sometimes useful with
+\fBy]]\fR.
+.NH 2
+Filtering portions of the buffer
+.PP
+You can run system commands over portions of the buffer using the operator
+\fB!\fR.
+You can use this to sort lines in the buffer, or to reformat portions
+of the buffer with a pretty-printer.
+Try typing in a list of random words, one per line and ending them
+with a blank line.  Back up to the beginning of the list, and then give
+the command \fB!}sort\fR\s-2CR\s0.  This says to sort the next paragraph
+of material, and the blank line ends a paragraph.
+.NH 2
+Commands for editing \s-2LISP\s0
+.PP
+If you are editing a \s-2LISP\s0 program you should set the option
+.I lisp
+by doing
+\fB:se\ lisp\fR\s-2CR\s0.
+This changes the \fB(\fR and \fB)\fR commands to move backward and forward
+over s-expressions.
+The \fB{\fR and \fB}\fR commands are like \fB(\fR and \fB)\fR but don't
+stop at atoms.  These can be used to skip to the next list, or through
+a comment quickly.
+.PP
+The
+.I autoindent
+option works differently for \s-2LISP\s0, supplying indent to align at
+the first argument to the last open list.  If there is no such argument
+then the indent is two spaces more than the last level.
+.PP
+There is another option which is useful for typing in \s-2LISP\s0, the
+.I showmatch
+option.
+Try setting it with
+\fB:se sm\fR\s-2CR\s0
+and then try typing a `(' some words and then a `)'.  Notice that the
+cursor shows the position of the `(' which matches the `)' briefly. 
+This happens only if the matching `(' is on the screen, and the cursor
+stays there for at most one second.
+.PP
+The editor also has an operator to realign existing lines as though they
+had been typed in with
+.I lisp
+and
+.I autoindent
+set.  This is the \fB=\fR operator.
+Try the command \fB=%\fR at the beginning of a function.  This will realign
+all the lines of the function declaration.
+.PP
+When you are editing \s-2LISP\s0,, the \fB[[\fR and \fR]]\fR advance
+and retreat to lines beginning with a \fB(\fR, and are useful for dealing
+with entire function definitions.
+.NH 2
+Macros
+.PP
+.I Vi
+has a parameterless macro facility, which lets you set it up so that
+when you hit a single keystroke, the editor will act as though
+you had hit some longer sequence of keys.  You can set this up if
+you find yourself typing the same sequence of commands repeatedly.
+.PP
+Briefly, there are two flavors of macros:
+.IP a)
+Ones where you put the macro body in a buffer register, say \fIx\fR.
+You can then type \fB@x\fR to invoke the macro.  The \fB@\fR may be followed
+by another \fB@\fR to repeat the last macro.
+.IP b)
+You can use the
+.I map
+command from
+.I vi
+(typically in your
+.I EXINIT )
+with a command of the form:
+.DS
+:map \fIlhs\fR \fIrhs\fR\s-2CR
+.DE
+mapping
+.I lhs
+into
+.I rhs.
+There are restrictions:
+.I lhs
+should be one keystroke (either 1 character or one function key)
+since it must be entered within one second
+(unless
+.I notimeout
+is set, in which case you can type it as slowly as you wish,
+and
+.I vi
+will wait for you to finish it before it echoes anything).
+The
+.I lhs
+can be no longer than 10 characters, the
+.I rhs
+no longer than 100.
+To get a space, tab or newline into
+.I lhs
+or
+.I rhs
+you should escape them with a \fB^V\fR.
+(It may be necessary to double the \fB^V\fR if the map
+command is given inside
+.I vi,
+rather than in
+.I ex.)
+Spaces and tabs inside the
+.I rhs
+need not be escaped.
+.PP
+Thus to make the \fBq\fR key write and exit the editor, you can give
+the command
+.DS
+:map q :wq\fB^V^V\fP\s-2CR CR\s0
+.DE
+which means that whenever you type \fBq\fR, it will be as though you
+had typed the four characters \fB:wq\fR\s-2CR\s0.
+A \fB^V\fR's is needed because without it the \s-2CR\s0 would end the
+\fB:\fR command, rather than becoming part of the
+.I map
+definition.
+There are two
+.B ^V 's
+because from within
+.I vi ,
+two
+.B ^V 's
+must be typed to get one.
+The first \s-2CR\s0 is part of the
+.I rhs ,
+the second terminates the : command.
+.PP
+Macros can be deleted with
+.DS
+unmap lhs
+.DE
+.PP
+If the
+.I lhs
+of a macro is ``#0'' through ``#9'', this maps the particular function key
+instead of the 2 character ``#'' sequence.  So that terminals without
+function keys can access such definitions, the form ``#x'' will mean function
+key
+.I x
+on all terminals (and need not be typed within one second.)
+The character ``#'' can be changed by using a macro in the usual way:
+.DS
+:map \fB^V^V^I\fP #
+.DE
+to use tab, for example.  (This won't affect the
+.I map
+command, which still uses
+.B #,
+but just the invocation from visual mode.
+.PP
+The undo command reverses an entire macro call as a unit,
+if it made any changes.
+.PP
+Placing a `!' after the word
+.B map
+causes the mapping to apply
+to input mode, rather than command mode.
+Thus, to arrange for \fB^T\fP to be the same as 4 spaces in input mode,
+you can type:
+.DS
+:map \fB^T\fP \fB^V\fP\o'b/'\o'b/'\o'b/'\o'b/'
+.DE
+where
+.B \o'b/'
+is a blank.
+The \fB^V\fP is necessary to prevent the blanks from being taken as
+white space between the
+.I lhs
+and
+.I rhs .
+.NH
+Word Abbreviations
+.PP
+A feature similar to macros in input mode is word abbreviation.
+This allows you to type a short word and have it expanded into
+a longer word or words.
+The commands are
+.B :abbreviate
+and
+.B :unabbreviate
+(\fB:ab\fP
+and
+.B :una )
+and have the same syntax as
+.B :map .
+For example:
+.DS
+:ab eecs Electrical Engineering and Computer Sciences
+.DE
+causes the word `eecs' to always be changed into the
+phrase `Electrical Engineering and Computer Sciences'.
+Word abbreviation is different from macros in that
+only whole words are affected.
+If `eecs' were typed as part of a larger word, it would
+be left alone.
+Also, the partial word is echoed as it is typed.
+There is no need for an abbreviation to be a single keystroke,
+as it should be with a macro.
+.NH 2
+Abbreviations
+.PP
+The editor has a number of short
+commands which abbreviate longer commands which we
+have introduced here.  You can find these commands easily
+on the quick reference card.
+They often save a bit of typing and you can learn them as convenient.
+.NH 1
+Nitty-gritty details
+.NH 2
+Line representation in the display
+.PP
+The editor folds long logical lines onto many physical lines in the display.
+Commands which advance lines advance logical lines and will skip
+over all the segments of a line in one motion.  The command \fB|\fR moves
+the cursor to a specific column, and may be useful for getting near the
+middle of a long line to split it in half.  Try \fB80|\fR on a line which
+is more than 80 columns long.\*(dg
+.FS
+\*(dg You can make long lines very easily by using \fBJ\fR to join together
+short lines.
+.FE
+.PP
+The editor only puts full lines on the display; if there is not enough
+room on the display to fit a logical line, the editor leaves the physical
+line empty, placing only an @ on the line as a place holder.  When you
+delete lines on a dumb terminal, the editor will often just clear the
+lines to @ to save time (rather than rewriting the rest of the screen.)
+You can always maximize the information on the screen by giving the \fB^R\fR
+command.
+.PP
+If you wish, you can have the editor place line numbers before each line
+on the display.  Give the command \fB:se nu\fR\s-2CR\s0 to enable
+this, and the command \fB:se nonu\fR\s-2CR\s0 to turn it off.
+You can have tabs represented as \fB^I\fR and the ends of lines indicated
+with `$' by giving the command \fB:se list\fR\s-2CR\s0;
+\fB:se nolist\fR\s-2CR\s0 turns this off.
+.PP
+Finally, lines consisting of only the character `~' are displayed when
+the last line in the file is in the middle of the screen.  These represent
+physical lines which are past the logical end of file.
+.NH 2
+Counts
+.PP
+Most
+.I vi
+commands will use a preceding count to affect their behavior in some way.
+The following table gives the common ways in which the counts are used:
+.DS
+.TS
+l lb.
+new window size        :  /  ?  [[  ]]  \`  \'
+scroll amount  ^D  ^U
+line/column number     z  G  |
+repeat effect  \fRmost of the rest\fP
+.TE
+.DE
+.PP
+The editor maintains a notion of the current default window size.
+On terminals which run at speeds greater than 1200 baud
+the editor uses the full terminal screen.
+On terminals which are slower than 1200 baud
+(most dialup lines are in this group)
+the editor uses 8 lines as the default window size.
+At 1200 baud the default is 16 lines.
+.PP
+This size is the size used when the editor clears and refills the screen
+after a search or other motion moves far from the edge of the current window.
+The commands which take a new window size as count all often cause the
+screen to be redrawn.  If you anticipate this, but do not need as large
+a window as you are currently using, you may wish to change the screen
+size by specifying the new size before these commands.
+In any case, the number of lines used on the screen will expand if you
+move off the top with a \fB\-\fR or similar command or off the bottom
+with a command such as \s-2RETURN\s0 or \fB^D\fR.
+The window will revert to the last specified size the next time it is
+cleared and refilled.\*(dg
+.FS
+\*(dg But not by a \fB^L\fR which just redraws the screen as it is.
+.FE
+.PP
+The scroll commands \fB^D\fR and \fB^U\fR likewise remember the amount
+of scroll last specified, using half the basic window size initially.
+The simple insert commands use a count to specify a repetition of the
+inserted text.  Thus \fB10a+\-\-\-\-\fR\s-2ESC\s0 will insert a grid-like
+string of text.
+A few commands also use a preceding count as a line or column number.
+.PP
+Except for a few commands which ignore any counts (such as \fB^R\fR),
+the rest of the editor commands use a count to indicate a simple repetition
+of their effect.  Thus \fB5w\fR advances five words on the current line,
+while \fB5\fR\s-2RETURN\s0 advances five lines.  A very useful instance
+of a count as a repetition is a count given to the \fB.\fR command, which
+repeats the last changing command.  If you do \fBdw\fR and then \fB3.\fR,
+you will delete first one and then three words.  You can then delete
+two more words with \fB2.\fR.
+.NH 2
+More file manipulation commands
+.PP
+The following table lists the file manipulation commands which you can
+use when you are in
+.I vi.
+.KF
+.DS
+.TS
+lb l.
+:w     write back changes
+:wq    write and quit
+:x     write (if necessary) and quit (same as ZZ).
+:e \fIname\fP  edit file \fIname\fR
+:e!    reedit, discarding changes
+:e + \fIname\fP        edit, starting at end
+:e +\fIn\fP    edit, starting at line \fIn\fP
+:e #   edit alternate file
+:w \fIname\fP  write file \fIname\fP
+:w! \fIname\fP overwrite file \fIname\fP
+:\fIx,y\fPw \fIname\fP write lines \fIx\fP through \fIy\fP to \fIname\fP
+:r \fIname\fP  read file \fIname\fP into buffer
+:r !\fIcmd\fP  read output of \fIcmd\fP into buffer
+:n     edit next file in argument list
+:n!    edit next file, discarding changes to current
+:n \fIargs\fP  specify new argument list
+:ta \fItag\fP  edit file containing tag \fItag\fP, at \fItag\fP
+.TE
+.DE
+.KE
+All of these commands are followed by a \s-2CR\s0 or \s-2ESC\s0.
+The most basic commands are \fB:w\fR and \fB:e\fR.
+A normal editing session on a single file will end with a \fBZZ\fR command.
+If you are editing for a long period of time you can give \fB:w\fR commands
+occasionally after major amounts of editing, and then finish
+with a \fBZZ\fR.   When you edit more than one file, you can finish
+with one with a \fB:w\fR and start editing a new file by giving a \fB:e\fR
+command,
+or set
+.I autowrite
+and use \fB:n\fP <file>.
+.PP
+If you make changes to the editor's copy of a file, but do not wish to
+write them back, then you must give an \fB!\fR after the command you
+would otherwise use; this forces the editor to discard any changes
+you have made.  Use this carefully.
+.ne 1i
+.PP
+The \fB:e\fR command can be given a \fB+\fR argument to start at the
+end of the file, or a \fB+\fR\fIn\fR argument to start at line \fIn\fR\^.
+In actuality, \fIn\fR may be any editor command not containing a space,
+usefully a scan like \fB+/\fIpat\fR or \fB+?\fIpat\fR.
+In forming new names to the \fBe\fR command, you can use the character
+\fB%\fR which is replaced by the current file name, or the character
+\fB#\fR which is replaced by the alternate file name.
+The alternate file name is generally the last name you typed other than
+the current file.  Thus if you try to do a \fB:e\fR and get a diagnostic
+that you haven't written the file, you can give a \fB:w\fR command and
+then a \fB:e #\fR command to redo the previous \fB:e\fR.
+.PP
+You can write part of the buffer to a file by finding out the lines
+that bound the range to be written using \fB^G\fR, and giving these
+numbers after the \fB:\fR
+and before the \fBw\fP, separated by \fB,\fR's.
+You can also mark these lines with \fBm\fR and
+then use an address of the form \fB\(aa\fR\fIx\fR\fB,\fB\(aa\fR\fIy\fR
+on the \fBw\fR command here.
+.PP
+You can read another file into the buffer after the current line by using
+the \fB:r\fR command.
+You can similarly read in the output from a command, just use \fB!\fR\fIcmd\fR
+instead of a file name.
+.PP
+If you wish to edit a set of files in succession, you can give all the
+names on the command line, and then edit each one in turn using the command
+\fB:n\fR.  It is also possible to respecify the list of files to be edited
+by giving the \fB:n\fR command a list of file names, or a pattern to
+be expanded as you would have given it on the initial
+.I vi
+command.
+.PP
+If you are editing large programs, you will find the \fB:ta\fR command
+very useful.  It utilizes a data base of function names and their locations,
+which can be created by programs such as
+.I ctags,
+to quickly find a function whose name you give.
+If the \fB:ta\fR command will require the editor to switch files, then
+you must \fB:w\fR or abandon any changes before switching.  You can repeat
+the \fB:ta\fR command without any arguments to look for the same tag
+again.
+.NH 2
+More about searching for strings
+.PP
+When you are searching for strings in the file with \fB/\fR and \fB?\fR,
+the editor normally places you at the next or previous occurrence
+of the string.  If you are using an operator such as \fBd\fR,
+\fBc\fR or \fBy\fR, then you may well wish to affect lines up to the
+line before the line containing the pattern.  You can give a search of
+the form \fB/\fR\fIpat\fR\fB/\-\fR\fIn\fR to refer to the \fIn\fR'th line
+before the next line containing \fIpat\fR, or you can use \fB+\fR instead
+of \fB\-\fR to refer to the lines after the one containing \fIpat\fR.
+If you don't give a line offset, then the editor will affect characters
+up to the match place, rather than whole lines; thus use ``+0'' to affect
+to the line which matches.
+.PP
+You can have the editor ignore the case of words in the searches it does
+by giving the command \fB:se ic\fR\s-2CR\s0.
+The command \fB:se noic\fR\s-2CR\s0 turns this off.
+.ne 1i
+.PP
+Strings given to searches may actually be regular expressions.
+If you do not want or need this facility, you should
+.DS
+set nomagic
+.DE
+in your EXINIT.
+In this case, 
+only the characters \fB\(ua\fR and \fB$\fR are special in patterns.
+The character \fB\e\fR is also then special (as it is most everywhere in
+the system), and may be used to get at the
+an extended pattern matching facility.
+It is also necessary to use a \e before a
+\fB/\fR in a forward scan or a \fB?\fR in a backward scan, in any case.
+The following table gives the extended forms when \fBmagic\fR is set.
+.DS
+.TS
+lb l.
+\(ua   at beginning of pattern, matches beginning of line
+$      at end of pattern, matches end of line
+\fB\&.\fR      matches any character
+\e<    matches the beginning of a word
+\e>    matches the end of a word
+[\fIstr\fP]    matches any single character in \fIstr\fP
+[\(ua\fIstr\fP]        matches any single character not in \fIstr\fP
+[\fIx\fP\-\fIy\fP]     matches any character between \fIx\fP and \fIy\fP
+*      matches any number of the preceding pattern
+.TE
+.DE
+If you use \fBnomagic\fR mode, then
+the \fB. [\fR and \fB*\fR primitives are given with a preceding
+\e.
+.NH 2
+More about input mode
+.PP
+There are a number of characters which you can use to make corrections
+during input mode.  These are summarized in the following table.
+.sp .5
+.DS
+.TS
+lb l.
+^H     deletes the last input character
+^W     deletes the last input word, defined as by \fBb\fR
+erase  your erase character, same as \fB^H\fP
+kill   your kill character, deletes the input on this line
+\e     escapes a following \fB^H\fP and your erase and kill
+\s-2ESC\s0     ends an insertion
+\s-2DEL\s0     interrupts an insertion, terminating it abnormally
+\s-2CR\s0      starts a new line
+^D     backtabs over \fIautoindent\fP
+0^D    kills all the \fIautoindent\fP
+\(ua^D same as \fB0^D\fP, but restores indent next line
+^V     quotes the next non-printing character into the file
+.TE
+.DE
+.sp .5
+.PP
+The most usual way of making corrections to input is by typing \fB^H\fR
+to correct a single character, or by typing one or more \fB^W\fR's to
+back over incorrect words.  If you use \fB#\fR as your erase character
+in the normal system, it will work like \fB^H\fR.
+.PP
+Your system kill character, normally \fB@\fR, \fB^X\fP or \fB^U\fR,
+will erase all
+the input you have given on the current line.
+In general, you can neither
+erase input back around a line boundary nor can you erase characters
+which you did not insert with this insertion command.  To make corrections
+on the previous line after a new line has been started you can hit \s-2ESC\s0
+to end the insertion, move over and make the correction, and then return
+to where you were to continue.  The command \fBA\fR which appends at the
+end of the current line is often useful for continuing.
+.PP
+If you wish to type in your erase or kill character (say # or @) then
+you must precede it with a \fB\e\fR, just as you would do at the normal
+system command level.  A more general way of typing non-printing characters
+into the file is to precede them with a \fB^V\fR.  The \fB^V\fR echoes
+as a \fB\(ua\fR character on which the cursor rests.  This indicates that
+the editor expects you to type a control character.  In fact you may
+type any character and it will be inserted into the file at that point.*
+.FS
+* This is not quite true.  The implementation of the editor does
+not allow the \s-2NULL\s0 (\fB^@\fR) character to appear in files.  Also
+the \s-2LF\s0 (linefeed or \fB^J\fR) character is used by the editor
+to separate lines in the file, so it cannot appear in the middle of a
+line.  You can insert any other character, however, if you wait for the
+editor to echo the \fB\(ua\fR before you type the character.  In fact,
+the editor will treat a following letter as a request for the corresponding
+control character.  This is the only way to type \fB^S\fR or \fB^Q\fP,
+since the system normally uses them to suspend and resume output
+and never gives them to the editor to process.
+.FE
+.PP
+If you are using \fIautoindent\fR you can backtab over the indent which
+it supplies by typing a \fB^D\fR.  This backs up to a \fIshiftwidth\fR
+boundary.
+This only works immediately after the supplied \fIautoindent\fR.
+.PP
+When you are using \fIautoindent\fR you may wish to place a label at
+the left margin of a line.  The way to do this easily is to type \fB\(ua\fR
+and then \fB^D\fR.  The editor will move the cursor to the left margin
+for one line, and restore the previous indent on the next.  You can also
+type a \fB0\fR followed immediately by a \fB^D\fR if you wish to kill
+all the indent and not have it come back on the next line.
+.NH 2
+Upper case only terminals
+.PP
+If your terminal has only upper case, you can still use
+.I vi
+by using the normal
+system convention for typing on such a terminal.
+Characters which you normally type are converted to lower case, and you
+can type upper case letters by preceding them with a \e.
+The characters { ~ } | \(ga are not available on such terminals, but you
+can escape them as \e( \e\(ua \e) \e! \e\(aa.
+These characters are represented on the display in the same way they
+are typed.\*(dd
+.FS
+\*(dd The \e character you give will not echo until you type another
+key.
+.FE
+.NH 2
+Vi and ex
+.PP
+.I Vi
+is actually one mode of editing within the editor
+.I ex.
+When you are running
+.I vi
+you can escape to the line oriented editor of
+.I ex
+by giving the command
+\fBQ\fR.
+All of the
+.B :
+commands which were introduced above are available in
+.I ex.
+Likewise, most
+.I ex
+commands can be invoked from
+.I vi
+using :.
+Just give them without the \fB:\fR and follow them with a \s-2CR\s0.
+.PP
+In rare instances, an internal error may occur in
+.I vi.
+In this case you will get a diagnostic and be left in the command mode of
+.I ex.
+You can then save your work and quit if you wish by giving a command
+\fBx\fR after the \fB:\fR which \fIex\fR prompts you with, or you can
+reenter \fIvi\fR by giving
+.I ex
+a
+.I vi
+command.
+.PP
+There are a number of things which you can do more easily in
+.I ex
+than in
+.I vi.
+Systematic changes in line oriented material are particularly easy.
+You can read the advanced editing documents for the editor
+.I ed
+to find out a lot more about this style of editing.
+Experienced
+users often mix their use of
+.I ex
+command mode and
+.I vi
+command mode to speed the work they are doing.
+.NH 2
+Open mode: vi on hardcopy terminals and ``glass tty's''
+\(dd
+.PP
+If you are on a hardcopy terminal or a terminal which does not have a cursor
+which can move off the bottom line, you can still use the command set of
+.I vi,
+but in a different mode.
+When you give a
+.I vi
+command, the editor will tell you that it is using
+.I open
+mode.
+This name comes from the
+.I open
+command in
+.I ex,
+which is used to get into the same mode.
+.PP
+The only difference between
+.I visual
+mode
+and
+.I open
+mode is the way in which the text is displayed.
+.PP
+In
+.I open
+mode the editor uses a single line window into the file, and moving backward
+and forward in the file causes new lines to be displayed, always below the
+current line.
+Two commands of
+.I vi
+work differently in
+.I open:
+.B z
+and
+\fB^R\fR.
+The
+.B z
+command does not take parameters, but rather draws a window of context around
+the current line and then returns you to the current line.
+.PP
+If you are on a hardcopy terminal,
+the
+.B ^R
+command will retype the current line.
+On such terminals, the editor normally uses two lines to represent the
+current line.
+The first line is a copy of the line as you started to edit it, and you work
+on the line below this line.
+When you delete characters, the editor types a number of \e's to show
+you the characters which are deleted.  The editor also reprints the current
+line soon after such changes so that you can see what the line looks
+like again.
+.PP
+It is sometimes useful to use this mode on very slow terminals which
+can support
+.I vi
+in the full screen mode.
+You can do this by entering
+.I ex
+and using an
+.I open
+command.
+.LP
+.SH
+Acknowledgements
+.PP
+Bruce Englar encouraged the early development of this display editor.
+Peter Kessler helped bring sanity to version 2's command layout.
+Bill Joy wrote versions 1 and 2.0 through 2.7,
+and created the framework that users see in the present editor.
+Mark Horton added macros and other features and made the
+editor work on a large number of terminals and Unix systems.
diff --git a/dist/nvi/docs/vitut/vi.summary b/dist/nvi/docs/vitut/vi.summary
new file mode 100644 (file)
index 0000000..a7af400
--- /dev/null
@@ -0,0 +1,442 @@
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" %sccs.include.redist.roff%
+.\"
+.\"    Id: vi.summary,v 8.3 1996/08/18 11:35:55 bostic Exp (Berkeley) Date: 1996/08/18 11:35:55
+.\"
+.ds CH
+.ds CF
+.de TS
+.br
+.if !\\n(1T .RT
+.ul 0
+.ti \\n(.iu
+.if t .sp 0.25
+.if n .sp
+.if \a\\$1\aH\a .TQ
+.nr IX 1
+..
+.nr PS 9
+.ps 9
+.nr VS 11
+.vs 11
+.nr HM .50i
+.nr FM .25i
+.nr PO 1.0i
+.po 1.0i
+.nr LL 4.5i
+.ll 4.5i
+.de nc
+.bp
+..
+.de h
+.LG
+.B
+\\$1
+.R
+.NL
+..
+.LG
+.LG
+.B
+.ce
+Ex Quick Reference
+.R
+.NL
+.LP
+.LP
+.h "Entering/leaving ex"
+.TS
+aw(1.4i)b aw(1.8i).
+% ex \fIname\fP        edit \fIname\fP, start at end
+% ex +\fIn\fP \fIname\fP       ... at line \fIn\fP
+% ex \-t \fItag\fP     start at \fItag\fP
+% ex \-r       list saved files
+% ex \-r \fIname\fP    recover file \fIname\fP
+% ex \fIname\fP ...    edit first; rest via \fB:n\fP
+% ex \-R \fIname\fP    read only mode
+: x    exit, saving changes
+: q!   exit, discarding changes
+.TE
+.h "Ex states"
+.TS
+lw(1i) lw(2.0i).
+Command        T{
+Normal and initial state.  Input prompted for by \fB:\fP.
+Your kill character cancels partial command.
+T}
+Insert T{
+Entered by \fBa\fP \fBi\fP and \fBc\fP.
+Arbitrary text then terminates with line having only \fB.\fP
+character on it or abnormally with interrupt.
+T}
+Open/visual    T{
+Entered by \fBopen\fP or \fBvi\fP, terminates with \fBQ\fP
+or ^\e.
+T}
+.TE
+.h "Ex commands"
+.TS
+lw(.45i) lw(.08i)b lw(.45i) lw(.08i)b lw(.45i) lw(.08i)b.
+abbrev ab      next    n       unabbrev        una
+append a       number  nu      undo    u
+args   ar      open    o       unmap   unm
+change c       preserve        pre     version ve
+copy   co      print   p       visual  vi
+delete d       put     pu      write   w
+edit   e       quit    q       xit     x
+file   f       read    re      yank    ya
+global g       recover rec     \fIwindow\fP    z
+insert i       rewind  rew     \fIescape\fP    !
+join   j       set     se      \fIlshift\fP    <
+list   l       shell   sh      \fIprint next\fP        \fRCR\fP
+map            source  so      \fIresubst\fP   &
+mark   ma      stop    st      \fIrshift\fP    >
+move   m       substitute      s       \fIscroll\fP    ^D
+.TE
+.h "Ex command addresses"
+.TS
+lw(.3i)b lw(0.8i) lw(.3i)b lw(0.8i).
+\fIn\fP        line \fIn\fP    /\fIpat\fP      next with \fIpat\fP
+\&.    current ?\fIpat\fP      previous with \fIpat\fP
+$      last    \fIx\fP-\fIn\fP \fIn\fP before \fIx\fP
++      next    \fIx\fP,\fIy\fP \fIx\fP through \fIy\fP
+\-     previous        \(aa\fIx\fP     marked with \fIx\fP
++\fIn\fP       \fIn\fP forward \(aa\(aa        previous context
+%      1,$
+.TE
+.nc
+.h "Specifying terminal type"
+.TS
+aw(1.7i)b aw(1.5i).
+% setenv TERM \fItype\fP       \fIcsh\fP and all version 6
+$ TERM=\fItype\fP; export TERM \fIsh\fP in Version 7
+See also \fItset\fR(1)
+.TE
+.h "Some terminal types"
+.TS
+lw(.4i) lw(.4i) lw(.4i) lw(.4i) lw(.4i).
+2621   43      adm31   dw1     h19
+2645   733     adm3a   dw2     i100
+300s   745     c100    gt40    mime
+33     act4    dm1520  gt42    owl
+37     act5    dm2500  h1500   t1061
+4014   adm3    dm3025  h1510   vt52
+.TE
+.h "Initializing options"
+.TS
+lw(.9i)b aw(1.5i).
+EXINIT place \fBset\fP's here in environment var.
+set \fIx\fP    enable option
+set no\fIx\fP  disable option
+set \fIx\fP=\fIval\fP  give value \fIval\fP
+set    show changed options
+set all        show all options
+set \fIx\fP?   show value of option \fIx\fP
+.TE
+.h "Useful options"
+.TS
+lw(.9i)b lw(.3i) lw(1.0i).
+autoindent     ai      supply indent
+autowrite      aw      write before changing files
+ignorecase     ic      in scanning
+lisp           \fB( ) { }\fP are s-exp's
+list           print ^I for tab, $ at end
+magic          \fB. [ *\fP special in patterns
+number nu      number lines
+paragraphs     para    macro names which start ...
+redraw         simulate smart terminal
+scroll         command mode lines
+sections       sect    macro names ...
+shiftwidth     sw      for \fB< >\fP, and input \fB^D\fP
+showmatch      sm      to \fB)\fP and \fB}\fP as typed
+slowopen       slow    choke updates during insert
+window         visual mode lines
+wrapscan       ws      around end of buffer?
+wrapmargin     wm      automatic line splitting
+.TE
+.LP
+.h "Scanning pattern formation"
+.TS
+aw(.9i)b aw(1.0i).
+\(ua   beginning of line
+$      end of line
+\fB.\fR        any character
+\e<    beginning of word
+\e>    end of word
+[\fIstr\fP]    any char in \fIstr\fP
+[\(ua\fIstr\fP]        ... not in \fIstr\fP
+[\fIx\-y\fP]   ... between \fIx\fP and \fIy\fP
+*      any number of preceding
+.TE
+.nc
+.LP
+.LG
+.LG
+.B
+.ce
+Vi Quick Reference
+.NL
+.R
+.LP
+.LP
+.h "Entering/leaving vi"
+.TS
+aw(1.4i)b aw(1.8i).
+% vi \fIname\fP        edit \fIname\fP at top
+% vi +\fIn\fP \fIname\fP       ... at line \fIn\fP
+% vi + \fIname\fP      ... at end
+% vi \-r       list saved files
+% vi \-r \fIname\fP    recover file \fIname\fP
+% vi \fIname\fP ...    edit first; rest via \fB:n\fP
+% vi \-t \fItag\fP     start at \fItag\fP
+% vi +/\fIpat\fP \fIname\fP    search for \fIpat\fP
+% view \fIname\fP      read only mode
+ZZ     exit from vi, saving changes
+^Z     stop vi for later resumption
+.TE
+.h "The display"
+.TS
+lw(.75i) lw(2.2i).
+Last line      T{
+Error messages, echoing input to \fB: / ?\fP and \fB!\fR,
+feedback about i/o and large changes.
+T}
+@ lines        On screen only, not in file.
+~ lines        Lines past end of file.
+^\fIx\fP       Control characters, ^? is delete.
+tabs   Expand to spaces, cursor at last.
+.TE
+.LP
+.h "Vi states"
+.TS
+lw(.75i) lw(2.2i).
+Command        T{
+Normal and initial state.  Others return here.
+ESC (escape) cancels partial command.
+T}
+Insert T{
+Entered by \fBa i A I o O c C s S\fP \fBR\fP.
+Arbitrary text then terminates with ESC character,
+or abnormally with interrupt.
+T}
+Last line      T{
+Reading input for \fB: / ?\fP or \fB!\fP; terminate
+with ESC or CR to execute, interrupt to cancel.
+T}
+.TE
+.h "Counts before vi commands"
+.TS
+lw(1.5i) lw(1.7i)b.
+line/column number     z  G  | 
+scroll amount  ^D  ^U
+replicate insert       a  i  A  I
+repeat effect  \fRmost rest\fP
+.TE
+.h "Simple commands"
+.TS
+lw(1.5i)b lw(1.7i).
+dw     delete a word
+de     ... leaving punctuation
+dd     delete a line
+3dd    ... 3 lines
+i\fItext\fP\fRESC\fP   insert text \fIabc\fP
+cw\fInew\fP\fRESC\fP   change word to \fInew\fP
+ea\fIs\fP\fRESC\fP     pluralize word
+xp     transpose characters
+.TE
+.nc
+.h "Interrupting, cancelling"
+.TS
+aw(0.75i)b aw(1.6i).
+ESC    end insert or incomplete cmd
+^?     (delete or rubout) interrupts
+^L     reprint screen if \fB^?\fR scrambles it
+.TE
+.h "File manipulation"
+.TS
+aw(0.75i)b aw(1.6i).
+:w     write back changes
+:wq    write and quit
+:q     quit
+:q!    quit, discard changes
+:e \fIname\fP  edit file \fIname\fP
+:e!    reedit, discard changes
+:e + \fIname\fP        edit, starting at end
+:e +\fIn\fR    edit starting at line \fIn\fR
+:e #   edit alternate file
+^\(ua  synonym for \fB:e #\fP
+:w \fIname\fP  write file \fIname\fP
+:w! \fIname\fP overwrite file \fIname\fP
+:sh    run shell, then return
+:!\fIcmd\fP    run \fIcmd\fR, then return
+:n     edit next file in arglist
+:n \fIargs\fP  specify new arglist
+:f     show current file and line
+^G     synonym for \fB:f\fP
+:ta \fItag\fP  to tag file entry \fItag\fP
+^]     \fB:ta\fP, following word is \fItag\fP
+.TE
+.h "Positioning within file"
+.TS
+aw(0.75i)b aw(1.6i).
+^F     forward screenfull
+^B     backward screenfull
+^D     scroll down half screen
+^U     scroll up half screen
+G      goto line (end default)
+/\fIpat\fR     next line matching \fIpat\fR
+?\fIpat\fR     prev line matching \fIpat\fR
+n      repeat last \fB/\fR or \fB?\fR
+N      reverse last \fB/\fR or \fB?\fR
+/\fIpat\fP/+\fIn\fP    n'th line after \fIpat\fR
+?\fIpat\fP?\-\fIn\fP   n'th line before \fIpat\fR
+]]     next section/function
+[[     previous section/function
+%      find matching \fB( ) {\fP or \fB}\fP
+.TE
+.h "Adjusting the screen"
+.TS
+aw(0.75i)b aw(1.6i).
+^L     clear and redraw
+^R     retype, eliminate @ lines
+z\fRCR\fP      redraw, current at window top
+z\-    ... at bottom
+z\|.   ... at center
+/\fIpat\fP/z\- \fIpat\fP line at bottom
+z\fIn\fP\|.    use \fIn\fP line window
+^E     scroll window down 1 line
+^Y     scroll window up 1 line
+.TE
+.nc
+.h "Marking and returning
+.TS
+aw(0.5i)b aw(2.0i).
+\(ga\(ga       previous context
+\(aa\(aa       ... at first non-white in line
+m\fIx\fP       mark position with letter \fIx\fP
+\(ga\fIx\fP    to mark \fIx\fP
+\(aa\fIx\fP    ... at first non-white in line
+.TE
+.h "Line positioning"
+.TS
+aw(0.5i)b aw(2.0i).
+H      home window line
+L      last window line
+M      middle window line
++      next line, at first non-white
+\-     previous line, at first non-white
+\fRCR\fP       return, same as +
+\(da \fRor\fP j        next line, same column
+\(ua \fRor\fP k        previous line, same column
+.TE
+.h "Character positioning"
+.TS
+aw(0.5i)b aw(2.0i).
+\(ua   first non white
+0      beginning of line
+$      end of line
+h \fRor\fP \(->        forward
+l \fRor\fP \(<-        backwards
+^H     same as \fB\(<-\fP
+\fRspace\fP    same as \fB\(->\fP
+f\fIx\fP       find \fIx\fP forward
+F\fIx\fP       \fBf\fR backward
+t\fIx\fP       upto \fIx\fP forward
+T\fIx\fP       back upto \fIx\fP
+;      repeat last \fBf F t\fP or \fBT\fP
+,      inverse of \fB;\fP
+|      to specified column
+%      find matching \fB( { )\fP or \fB}\fR
+.TE
+.h "Words, sentences, paragraphs"
+.TS
+aw(0.5i)b aw(2.0i).
+w      word forward
+b      back word
+e      end of word
+)      to next sentence
+}      to next paragraph
+(      back sentence
+{      back paragraph
+W      blank delimited word
+B      back \fBW\fP
+E      to end of \fBW\fP
+.TE
+.h "Commands for \s-2LISP\s0"
+.TS
+aw(0.5i)b aw(2.0i).
+)      Forward s-expression
+}      ... but don't stop at atoms
+(      Back s-expression
+{      ... but don't stop at atoms
+.TE
+.nc
+.h "Corrections during insert"
+.TS
+aw(.5i)b aw(2.0i).
+^H     erase last character
+^W     erases last word
+\fRerase\fP    your erase, same as \fB^H\fP
+\fRkill\fP     your kill, erase input this line
+\e     escapes \fB^H\fR, your erase and kill
+\fRESC\fP      ends insertion, back to command
+^?     interrupt, terminates insert
+^D     backtab over \fIautoindent\fP
+\(ua^D kill \fIautoindent\fP, save for next
+0^D    ... but at margin next also
+^V     quote non-printing character
+.TE
+.h "Insert and replace"
+.TS
+aw(.5i)b aw(2.0i).
+a      append after cursor
+i      insert before
+A      append at end of line
+I      insert before first non-blank
+o      open line below
+O      open above
+r\fIx\fP       replace single char with \fIx\fP
+R      replace characters
+.TE
+.h "Operators (double to affect lines)"
+.TS
+aw(0.5i)b aw(2.0i).
+d      delete
+c      change
+<      left shift
+>      right shift
+!      filter through command
+\&=    indent for \s-2LISP\s0
+y      yank lines to buffer
+.TE
+.h "Miscellaneous operations"
+.TS
+aw(0.5i)b aw(2.0i).
+C      change rest of line
+D      delete rest of line
+s      substitute chars
+S      substitute lines
+J      join lines
+x      delete characters
+X      ... before cursor
+Y      yank lines
+.TE
+.h "Yank and put"
+.TS
+aw(0.5i)b aw(2.0i).
+p      put back lines
+P      put before
+"\fIx\fPp      put from buffer \fIx\fP
+"\fIx\fPy      yank to buffer \fIx\fP
+"\fIx\fPd      delete into buffer \fIx\fP
+.TE
+.h "Undo, redo, retrieve"
+.TS
+aw(0.5i)b aw(2.0i).
+u      undo last change
+U      restore current line
+\fB.\fP        repeat last change
+"\fId\fP\|p    retrieve \fId\fP'th last delete
+.TE
diff --git a/dist/nvi/ex/ex.awk b/dist/nvi/ex/ex.awk
new file mode 100644 (file)
index 0000000..9cbb53f
--- /dev/null
@@ -0,0 +1,6 @@
+#      Id: ex.awk,v 10.1 1995/06/08 18:55:37 bostic Exp (Berkeley) Date: 1995/06/08 18:55:37
+/^\/\* C_[0-9A-Z_]* \*\/$/ {
+       printf("#define %s %d\n", $2, cnt++);
+       next;
+}
diff --git a/dist/nvi/ex/ex.c b/dist/nvi/ex/ex.c
new file mode 100644 (file)
index 0000000..d26bede
--- /dev/null
@@ -0,0 +1,2365 @@
+/*     $NetBSD: ex.c,v 1.9 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex.c,v 10.75 2004/03/16 14:13:35 skimo Exp (Berkeley) Date: 2004/03/16 14:13:35";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+#if defined(DEBUG) && defined(COMLOG)
+static void    ex_comlog __P((SCR *, EXCMD *));
+#endif
+static EXCMDLIST const *
+               ex_comm_search __P((SCR *, CHAR_T *, size_t));
+static int     ex_discard __P((SCR *));
+static int     ex_line __P((SCR *, EXCMD *, MARK *, int *, int *));
+static int     ex_load __P((SCR *));
+static void    ex_unknown __P((SCR *, CHAR_T *, size_t));
+
+/*
+ * ex --
+ *     Main ex loop.
+ *
+ * PUBLIC: int ex __P((SCR **));
+ */
+int
+ex(SCR **spp)
+{
+       EX_PRIVATE *exp;
+       GS *gp;
+       WIN *wp;
+       MSGS *mp;
+       SCR *sp;
+       TEXT *tp;
+       u_int32_t flags;
+
+       sp = *spp;
+       wp = sp->wp;
+       gp = sp->gp;
+       exp = EXP(sp);
+
+       /* Start the ex screen. */
+       if (ex_init(sp))
+               return (1);
+
+       /* Flush any saved messages. */
+       while ((mp = gp->msgq.lh_first) != NULL) {
+               wp->scr_msg(sp, mp->mtype, mp->buf, mp->len);
+               LIST_REMOVE(mp, q);
+               free(mp->buf);
+               free(mp);
+       }
+
+       /* If reading from a file, errors should have name and line info. */
+       if (F_ISSET(gp, G_SCRIPTED)) {
+               wp->excmd.if_lno = 1;
+               wp->excmd.if_name = strdup("script");
+       }
+
+       /*
+        * !!!
+        * Initialize the text flags.  The beautify edit option historically
+        * applied to ex command input read from a file.  In addition, the
+        * first time a ^H was discarded from the input, there was a message,
+        * "^H discarded", that was displayed.  We don't bother.
+        */
+       LF_INIT(TXT_BACKSLASH | TXT_CNTRLD | TXT_CR);
+       for (;; ++wp->excmd.if_lno) {
+               /* Display status line and flush. */
+               if (F_ISSET(sp, SC_STATUS)) {
+                       if (!F_ISSET(sp, SC_EX_SILENT))
+                               msgq_status(sp, sp->lno, 0);
+                       F_CLR(sp, SC_STATUS);
+               }
+               (void)ex_fflush(sp);
+
+               /* Set the flags the user can reset. */
+               if (O_ISSET(sp, O_BEAUTIFY))
+                       LF_SET(TXT_BEAUTIFY);
+               if (O_ISSET(sp, O_PROMPT))
+                       LF_SET(TXT_PROMPT);
+
+               /* Clear any current interrupts, and get a command. */
+               CLR_INTERRUPT(sp);
+               if (ex_txt(sp, &sp->tiq, ':', flags))
+                       return (1);
+               if (INTERRUPTED(sp)) {
+                       (void)ex_puts(sp, "\n");
+                       (void)ex_fflush(sp);
+                       continue;
+               }
+
+               /* Initialize the command structure. */
+               CLEAR_EX_PARSER(&wp->excmd);
+
+               /*
+                * If the user entered a single carriage return, send
+                * ex_cmd() a separator -- it discards single newlines.
+                */
+               tp = sp->tiq.cqh_first;
+               if (tp->len == 0) {
+                       static CHAR_T space = ' ';
+                       wp->excmd.cp = &space;  /* __TK__ why not |? */
+                       wp->excmd.clen = 1;
+               } else {
+                       wp->excmd.cp = tp->lb;
+                       wp->excmd.clen = tp->len;
+               }
+               F_INIT(&wp->excmd, E_NRSEP);
+
+               if (ex_cmd(sp) && F_ISSET(gp, G_SCRIPTED))
+                       return (1);
+
+               if (INTERRUPTED(sp)) {
+                       CLR_INTERRUPT(sp);
+                       msgq(sp, M_ERR, "170|Interrupted");
+               }
+
+               /*
+                * If the last command caused a restart, or switched screens
+                * or into vi, return.
+                */
+               if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_SSWITCH | SC_VI)) {
+                       *spp = sp;
+                       break;
+               }
+
+               /* If the last command switched files, we don't care. */
+               F_CLR(sp, SC_FSWITCH);
+
+               /*
+                * If we're exiting this screen, move to the next one.  By
+                * definition, this means returning into vi, so return to the
+                * main editor loop.  The ordering is careful, don't discard
+                * the contents of sp until the end.
+                */
+               if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+                       if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
+                               return (1);
+                       *spp = screen_next(sp);
+                       return (screen_end(sp));
+               }
+       }
+       return (0);
+}
+
+/*
+ * ex_cmd --
+ *     The guts of the ex parser: parse and execute a string containing
+ *     ex commands.
+ *
+ * !!!
+ * This code MODIFIES the string that gets passed in, to delete quoting
+ * characters, etc.  The string cannot be readonly/text space, nor should
+ * you expect to use it again after ex_cmd() returns.
+ *
+ * !!!
+ * For the fun of it, if you want to see if a vi clone got the ex argument
+ * parsing right, try:
+ *
+ *     echo 'foo|bar' > file1; echo 'foo/bar' > file2;
+ *     vi
+ *     :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
+ *
+ * or: vi
+ *     :set|file|append|set|file
+ *
+ * For extra credit, try them in a startup .exrc file.
+ *
+ * PUBLIC: int ex_cmd __P((SCR *));
+ */
+int
+ex_cmd(SCR *sp)
+{
+       enum nresult nret;
+       EX_PRIVATE *exp;
+       EXCMD *ecp;
+       GS *gp;
+       WIN *wp;
+       MARK cur;
+       db_recno_t lno;
+       size_t arg1_len, discard, len;
+       u_int32_t flags;
+       long ltmp;
+       int at_found, gv_found;
+       int cnt, delim, isaddr, namelen;
+       int newscreen, notempty, tmp, vi_address;
+       CHAR_T *arg1, *s, *p, *t;
+       ARG_CHAR_T ch;
+       const CHAR_T *n;
+       const char *np;
+
+       gp = sp->gp;
+       wp = sp->wp;
+       exp = EXP(sp);
+       ch = '\0';      /* XXX: gcc -O1 -Wuninitialized */
+
+       /*
+        * We always start running the command on the top of the stack.
+        * This means that *everything* must be resolved when we leave
+        * this function for any reason.
+        */
+loop:  ecp = wp->ecq.lh_first;
+
+       /* If we're reading a command from a file, set up error information. */
+       if (ecp->if_name != NULL) {
+               wp->if_lno = ecp->if_lno;
+               wp->if_name = ecp->if_name;
+       }
+
+       /*
+        * If a move to the end of the file is scheduled for this command,
+        * do it now.
+        */
+       if (F_ISSET(ecp, E_MOVETOEND)) {
+               if (db_last(sp, &sp->lno))
+                       goto rfail;
+               sp->cno = 0;
+               F_CLR(ecp, E_MOVETOEND);
+       }
+
+       /* If we found a newline, increment the count now. */
+       if (F_ISSET(ecp, E_NEWLINE)) {
+               ++wp->if_lno;
+               ++ecp->if_lno;
+               F_CLR(ecp, E_NEWLINE);
+       }
+
+       /* (Re)initialize the EXCMD structure, preserving some flags. */
+       CLEAR_EX_CMD(ecp);
+
+       /* Initialize the argument structures. */
+       if (argv_init(sp, ecp))
+               goto err;
+
+       /* Initialize +cmd, saved command information. */
+       arg1 = NULL;
+       ecp->save_cmdlen = 0;
+
+       /* Skip <blank>s, empty lines.  */
+       for (notempty = 0; ecp->clen > 0; ++ecp->cp, --ecp->clen)
+               if ((ch = (UCHAR_T)*ecp->cp) == '\n') {
+                       ++wp->if_lno;
+                       ++ecp->if_lno;
+               } else if (ISBLANK(ch))
+                       notempty = 1;
+               else
+                       break;
+
+       /*
+        * !!!
+        * Permit extra colons at the start of the line.  Historically,
+        * ex/vi allowed a single extra one.  It's simpler not to count.
+        * The stripping is done here because, historically, any command
+        * could have preceding colons, e.g. ":g/pattern/:p" worked.
+        */
+       if (ecp->clen != 0 && ch == ':') {
+               notempty = 1;
+               while (--ecp->clen > 0 && (ch = (UCHAR_T)*++ecp->cp) == ':');
+       }
+
+       /*
+        * Command lines that start with a double-quote are comments.
+        *
+        * !!!
+        * Historically, there was no escape or delimiter for a comment, e.g.
+        * :"foo|set was a single comment and nothing was output.  Since nvi
+        * permits users to escape <newline> characters into command lines, we
+        * have to check for that case.
+        */
+       if (ecp->clen != 0 && ch == '"') {
+               while (--ecp->clen > 0 && *++ecp->cp != '\n');
+               if (*ecp->cp == '\n') {
+                       F_SET(ecp, E_NEWLINE);
+                       ++ecp->cp;
+                       --ecp->clen;
+               }
+               goto loop;
+       }
+
+       /* Skip whitespace. */
+       for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
+               ch = (UCHAR_T)*ecp->cp;
+               if (!ISBLANK(ch))
+                       break;
+       }
+
+       /*
+        * The last point at which an empty line can mean do nothing.
+        *
+        * !!!
+        * Historically, in ex mode, lines containing only <blank> characters
+        * were the same as a single <carriage-return>, i.e. a default command.
+        * In vi mode, they were ignored.  In .exrc files this was a serious
+        * annoyance, as vi kept trying to treat them as print commands.  We
+        * ignore backward compatibility in this case, discarding lines that
+        * contain only <blank> characters from .exrc files.
+        *
+        * !!!
+        * This is where you end up when you're done a command, i.e. clen has
+        * gone to zero.  Continue if there are more commands to run.
+        */
+       if (ecp->clen == 0 &&
+           (!notempty || F_ISSET(sp, SC_VI) || F_ISSET(ecp, E_BLIGNORE))) {
+               if (ex_load(sp))
+                       goto rfail;
+               ecp = wp->ecq.lh_first;
+               if (ecp->clen == 0)
+                       goto rsuccess;
+               goto loop;
+       }
+
+       /*
+        * Check to see if this is a command for which we may want to move
+        * the cursor back up to the previous line.  (The command :1<CR>
+        * wants a <newline> separator, but the command :<CR> wants to erase
+        * the command line.)  If the line is empty except for <blank>s,
+        * <carriage-return> or <eof>, we'll probably want to move up.  I
+        * don't think there's any way to get <blank> characters *after* the
+        * command character, but this is the ex parser, and I've been wrong
+        * before.
+        */
+       if (F_ISSET(ecp, E_NRSEP) &&
+           ecp->clen != 0 && (ecp->clen != 1 || ecp->cp[0] != '\004'))
+               F_CLR(ecp, E_NRSEP);
+
+       /* Parse command addresses. */
+       if (ex_range(sp, ecp, &tmp))
+               goto rfail;
+       if (tmp)
+               goto err;
+
+       /*
+        * Skip <blank>s and any more colons (the command :3,5:print
+        * worked, historically).
+        */
+       for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
+               ch = (UCHAR_T)*ecp->cp;
+               if (!ISBLANK(ch) && ch != ':')
+                       break;
+       }
+
+       /*
+        * If no command, ex does the last specified of p, l, or #, and vi
+        * moves to the line.  Otherwise, determine the length of the command
+        * name by looking for the first non-alphabetic character.  (There
+        * are a few non-alphabetic characters in command names, but they're
+        * all single character commands.)  This isn't a great test, because
+        * it means that, for the command ":e +cut.c file", we'll report that
+        * the command "cut" wasn't known.  However, it makes ":e+35 file" work
+        * correctly.
+        *
+        * !!!
+        * Historically, lines with multiple adjacent (or <blank> separated)
+        * command separators were very strange.  For example, the command
+        * |||<carriage-return>, when the cursor was on line 1, displayed
+        * lines 2, 3 and 5 of the file.  In addition, the command "   |  "
+        * would only display the line after the next line, instead of the
+        * next two lines.  No ideas why.  It worked reasonably when executed
+        * from vi mode, and displayed lines 2, 3, and 4, so we do a default
+        * command for each separator.
+        */
+#define        SINGLE_CHAR_COMMANDS    "\004!#&*<=>@~"
+       newscreen = 0;
+       if (ecp->clen != 0 && ecp->cp[0] != '|' && ecp->cp[0] != '\n') {
+               if (strchr(SINGLE_CHAR_COMMANDS, *ecp->cp)) {
+                       p = ecp->cp;
+                       ++ecp->cp;
+                       --ecp->clen;
+                       namelen = 1;
+               } else {
+                       for (p = ecp->cp;
+                           ecp->clen > 0; --ecp->clen, ++ecp->cp)
+                               if (!ISALPHA((UCHAR_T)*ecp->cp))
+                                       break;
+                       if ((namelen = ecp->cp - p) == 0) {
+                               msgq(sp, M_ERR, "080|Unknown command name");
+                               goto err;
+                       }
+               }
+
+               /*
+                * !!!
+                * Historic vi permitted flags to immediately follow any
+                * subset of the 'delete' command, but then did not permit
+                * further arguments (flag, buffer, count).  Make it work.
+                * Permit further arguments for the few shreds of dignity
+                * it offers.
+                *
+                * Adding commands that start with 'd', and match "delete"
+                * up to a l, p, +, - or # character can break this code.
+                *
+                * !!!
+                * Capital letters beginning the command names ex, edit,
+                * next, previous, tag and visual (in vi mode) indicate the
+                * command should happen in a new screen.
+                */
+               switch (p[0]) {
+               case 'd':
+                       for (s = p,
+                           n = cmds[C_DELETE].name; *s == *n; ++s, ++n);
+                       if (s[0] == 'l' || s[0] == 'p' || s[0] == '+' ||
+                           s[0] == '-' || s[0] == '^' || s[0] == '#') {
+                               len = (ecp->cp - p) - (s - p);
+                               ecp->cp -= len;
+                               ecp->clen += len;
+                               ecp->rcmd = cmds[C_DELETE];
+                               ecp->rcmd.syntax = "1bca1";
+                               ecp->cmd = &ecp->rcmd;
+                               goto skip_srch;
+                       }
+                       break;
+               case 'E': case 'F': case 'N': case 'P': case 'T': case 'V':
+                       newscreen = 1;
+                       p[0] = TOLOWER(p[0]);
+                       break;
+               }
+
+               /*
+                * Search the table for the command.
+                *
+                * !!!
+                * Historic vi permitted the mark to immediately follow the
+                * 'k' in the 'k' command.  Make it work.
+                *
+                * !!!
+                * Historic vi permitted any flag to follow the s command, e.g.
+                * "s/e/E/|s|sgc3p" was legal.  Make the command "sgc" work.
+                * Since the following characters all have to be flags, i.e.
+                * alphabetics, we can let the s command routine return errors
+                * if it was some illegal command string.  This code will break
+                * if an "sg" or similar command is ever added.  The substitute
+                * code doesn't care if it's a "cgr" flag or a "#lp" flag that
+                * follows the 's', but we limit the choices here to "cgr" so
+                * that we get unknown command messages for wrong combinations.
+                */
+               if ((ecp->cmd = ex_comm_search(sp, p, namelen)) == NULL)
+                       switch (p[0]) {
+                       case 'k':
+                               if (namelen == 2) {
+                                       ecp->cp -= namelen - 1;
+                                       ecp->clen += namelen - 1;
+                                       ecp->cmd = &cmds[C_K];
+                                       break;
+                               }
+                               goto unknown;
+                       case 's':
+                               for (s = p + 1, cnt = namelen; --cnt; ++s)
+                                       if (s[0] != 'c' &&
+                                           s[0] != 'g' && s[0] != 'r')
+                                               break;
+                               if (cnt == 0) {
+                                       ecp->cp -= namelen - 1;
+                                       ecp->clen += namelen - 1;
+                                       ecp->rcmd = cmds[C_SUBSTITUTE];
+                                       ecp->rcmd.fn = ex_subagain;
+                                       ecp->cmd = &ecp->rcmd;
+                                       break;
+                               }
+                               /* FALLTHROUGH */
+                       default:
+unknown:                       if (newscreen)
+                                       p[0] = TOUPPER((UCHAR_T)p[0]);
+                               ex_unknown(sp, p, namelen);
+                               goto err;
+                       }
+
+               /*
+                * The visual command has a different syntax when called
+                * from ex than when called from a vi colon command.  FMH.
+                * Make the change now, before we test for the newscreen
+                * semantic, so that we're testing the right one.
+                */
+skip_srch:     if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
+                       ecp->cmd = &cmds[C_VISUAL_VI];
+
+               /*
+                * !!!
+                * Historic vi permitted a capital 'P' at the beginning of
+                * any command that started with 'p'.  Probably wanted the
+                * P[rint] command for backward compatibility, and the code
+                * just made Preserve and Put work by accident.  Nvi uses
+                * Previous to mean previous-in-a-new-screen, so be careful.
+                */
+               if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN) &&
+                   (ecp->cmd == &cmds[C_PRINT] ||
+                   ecp->cmd == &cmds[C_PRESERVE]))
+                       newscreen = 0;
+
+               /* Test for a newscreen associated with this command. */
+               if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN))
+                       goto unknown;
+
+               /* Secure means no shell access. */
+               if (F_ISSET(ecp->cmd, E_SECURE) && O_ISSET(sp, O_SECURE)) {
+                       ex_wemsg(sp, ecp->cmd->name, EXM_SECURE);
+                       goto err;
+               }
+
+               /*
+                * Multiple < and > characters; another "feature".  Note,
+                * The string passed to the underlying function may not be
+                * nul terminated in this case.
+                */
+               if ((ecp->cmd == &cmds[C_SHIFTL] && *p == '<') ||
+                   (ecp->cmd == &cmds[C_SHIFTR] && *p == '>')) {
+                       for (ch = (UCHAR_T)*p;
+                           ecp->clen > 0; --ecp->clen, ++ecp->cp)
+                               if (*ecp->cp != ch)
+                                       break;
+                       if (argv_exp0(sp, ecp, p, ecp->cp - p))
+                               goto err;
+               }
+
+               /* Set the format style flags for the next command. */
+               if (ecp->cmd == &cmds[C_HASH])
+                       exp->fdef = E_C_HASH;
+               else if (ecp->cmd == &cmds[C_LIST])
+                       exp->fdef = E_C_LIST;
+               else if (ecp->cmd == &cmds[C_PRINT])
+                       exp->fdef = E_C_PRINT;
+               F_CLR(ecp, E_USELASTCMD);
+       } else {
+               /* Print is the default command. */
+               ecp->cmd = &cmds[C_PRINT];
+
+               /* Set the saved format flags. */
+               F_SET(ecp, exp->fdef);
+
+               /*
+                * !!!
+                * If no address was specified, and it's not a global command,
+                * we up the address by one.  (I have no idea why globals are
+                * exempted, but it's (ahem) historic practice.)
+                */
+               if (ecp->addrcnt == 0 && !F_ISSET(sp, SC_EX_GLOBAL)) {
+                       ecp->addrcnt = 1;
+                       ecp->addr1.lno = sp->lno + 1;
+                       ecp->addr1.cno = sp->cno;
+               }
+
+               F_SET(ecp, E_USELASTCMD);
+       }
+
+       /*
+        * !!!
+        * Historically, the number option applied to both ex and vi.  One
+        * strangeness was that ex didn't switch display formats until a
+        * command was entered, e.g. <CR>'s after the set didn't change to
+        * the new format, but :1p would.
+        */
+       if (O_ISSET(sp, O_NUMBER)) {
+               F_SET(ecp, E_OPTNUM);
+               FL_SET(ecp->iflags, E_C_HASH);
+       } else
+               F_CLR(ecp, E_OPTNUM);
+
+       /* Check for ex mode legality. */
+       if (F_ISSET(sp, SC_EX) && (F_ISSET(ecp->cmd, E_VIONLY) || newscreen)) {
+               msgq_wstr(sp, M_ERR, ecp->cmd->name,
+                   "082|%s: command not available in ex mode");
+               goto err;
+       }
+
+       /* Add standard command flags. */
+       F_SET(ecp, ecp->cmd->flags);
+       if (!newscreen)
+               F_CLR(ecp, E_NEWSCREEN);
+
+       /*
+        * There are three normal termination cases for an ex command.  They
+        * are the end of the string (ecp->clen), or unescaped (by <literal
+        * next> characters) <newline> or '|' characters.  As we're now past
+        * possible addresses, we can determine how long the command is, so we
+        * don't have to look for all the possible terminations.  Naturally,
+        * there are some exciting special cases:
+        *
+        * 1: The bang, global, v and the filter versions of the read and
+        *    write commands are delimited by <newline>s (they can contain
+        *    shell pipes).
+        * 2: The ex, edit, next and visual in vi mode commands all take ex
+        *    commands as their first arguments.
+        * 3: The s command takes an RE as its first argument, and wants it
+        *    to be specially delimited.
+        *
+        * Historically, '|' characters in the first argument of the ex, edit,
+        * next, vi visual, and s commands didn't delimit the command.  And,
+        * in the filter cases for read and write, and the bang, global and v
+        * commands, they did not delimit the command at all.
+        *
+        * For example, the following commands were legal:
+        *
+        *      :edit +25|s/abc/ABC/ file.c
+        *      :s/|/PIPE/
+        *      :read !spell % | columnate
+        *      :global/pattern/p|l
+        *
+        * It's not quite as simple as it sounds, however.  The command:
+        *
+        *      :s/a/b/|s/c/d|set
+        *
+        * was also legal, i.e. the historic ex parser (using the word loosely,
+        * since "parser" implies some regularity of syntax) delimited the RE's
+        * based on its delimiter and not anything so irretrievably vulgar as a
+        * command syntax.
+        *
+        * Anyhow, the following code makes this all work.  First, for the
+        * special cases we move past their special argument(s).  Then, we
+        * do normal command processing on whatever is left.  Barf-O-Rama.
+        */
+       discard = 0;            /* Characters discarded from the command. */
+       arg1_len = 0;
+       ecp->save_cmd = ecp->cp;
+       if (ecp->cmd == &cmds[C_EDIT] || ecp->cmd == &cmds[C_EX] ||
+           ecp->cmd == &cmds[C_NEXT] || ecp->cmd == &cmds[C_VISUAL_VI] ||
+           ecp->cmd == &cmds[C_VSPLIT]) {
+               /*
+                * Move to the next non-whitespace character.  A '!'
+                * immediately following the command is eaten as a
+                * force flag.
+                */
+               if (ecp->clen > 0 && *ecp->cp == '!') {
+                       ++ecp->cp;
+                       --ecp->clen;
+                       FL_SET(ecp->iflags, E_C_FORCE);
+
+                       /* Reset, don't reparse. */
+                       ecp->save_cmd = ecp->cp;
+               }
+               for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+                       if (!ISBLANK(*ecp->cp))
+                               break;
+               /*
+                * QUOTING NOTE:
+                *
+                * The historic implementation ignored all escape characters
+                * so there was no way to put a space or newline into the +cmd
+                * field.  We do a simplistic job of fixing it by moving to the
+                * first whitespace character that isn't escaped.  The escaping
+                * characters are stripped as no longer useful.
+                */
+               if (ecp->clen > 0 && *ecp->cp == '+') {
+                       ++ecp->cp;
+                       --ecp->clen;
+                       for (arg1 = p = ecp->cp;
+                           ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+                               ch = (UCHAR_T)*ecp->cp;
+                               if (IS_ESCAPE(sp, ecp, ch) &&
+                                   ecp->clen > 1) {
+                                       ++discard;
+                                       --ecp->clen;
+                                       ch = (UCHAR_T)*++ecp->cp;
+                               } else if (ISBLANK(ch))
+                                       break;
+                               *p++ = ch;
+                       }
+                       arg1_len = ecp->cp - arg1;
+
+                       /* Reset, so the first argument isn't reparsed. */
+                       ecp->save_cmd = ecp->cp;
+               }
+       } else if (ecp->cmd == &cmds[C_BANG] ||
+           ecp->cmd == &cmds[C_GLOBAL] || ecp->cmd == &cmds[C_V]) {
+               /*
+                * QUOTING NOTE:
+                *
+                * We use backslashes to escape <newline> characters, although
+                * this wasn't historic practice for the bang command.  It was
+                * for the global and v commands, and it's common usage when
+                * doing text insert during the command.  Escaping characters
+                * are stripped as no longer useful.
+                */
+               for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+                       ch = (UCHAR_T)*ecp->cp;
+                       if (ch == '\\' && ecp->clen > 1 && ecp->cp[1] == '\n') {
+                               ++discard;
+                               --ecp->clen;
+                               ch = (UCHAR_T)*++ecp->cp;
+
+                               ++wp->if_lno;
+                               ++ecp->if_lno;
+                       } else if (ch == '\n')
+                               break;
+                       *p++ = ch;
+               }
+       } else if (ecp->cmd == &cmds[C_READ] || ecp->cmd == &cmds[C_WRITE]) {
+               /*
+                * For write commands, if the next character is a <blank>, and
+                * the next non-blank character is a '!', it's a filter command
+                * and we want to eat everything up to the <newline>.  For read
+                * commands, if the next non-blank character is a '!', it's a
+                * filter command and we want to eat everything up to the next
+                * <newline>.  Otherwise, we're done.
+                */
+               for (tmp = 0; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+                       ch = (UCHAR_T)*ecp->cp;
+                       if (ISBLANK(ch))
+                               tmp = 1;
+                       else
+                               break;
+               }
+               if (ecp->clen > 0 && ch == '!' &&
+                   (ecp->cmd == &cmds[C_READ] || tmp))
+                       for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+                               if (ecp->cp[0] == '\n')
+                                       break;
+       } else if (ecp->cmd == &cmds[C_SUBSTITUTE]) {
+               /*
+                * Move to the next non-whitespace character, we'll use it as
+                * the delimiter.  If the character isn't an alphanumeric or
+                * a '|', it's the delimiter, so parse it.  Otherwise, we're
+                * into something like ":s g", so use the special s command.
+                */
+               for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+                       if (!ISBLANK(ecp->cp[0]))
+                               break;
+
+               if (ISALNUM((UCHAR_T)ecp->cp[0]) || ecp->cp[0] == '|') {
+                       ecp->rcmd = cmds[C_SUBSTITUTE];
+                       ecp->rcmd.fn = ex_subagain;
+                       ecp->cmd = &ecp->rcmd;
+               } else if (ecp->clen > 0) {
+                       /*
+                        * QUOTING NOTE:
+                        *
+                        * Backslashes quote delimiter characters for RE's.
+                        * The backslashes are NOT removed since they'll be
+                        * used by the RE code.  Move to the third delimiter
+                        * that's not escaped (or the end of the command).
+                        */
+                       delim = *ecp->cp;
+                       ++ecp->cp;
+                       --ecp->clen;
+                       for (cnt = 2; ecp->clen > 0 &&
+                           cnt != 0; --ecp->clen, ++ecp->cp)
+                               if (ecp->cp[0] == '\\' &&
+                                   ecp->clen > 1) {
+                                       ++ecp->cp;
+                                       --ecp->clen;
+                               } else if (ecp->cp[0] == delim)
+                                       --cnt;
+               }
+       }
+
+       /*
+        * Use normal quoting and termination rules to find the end of this
+        * command.
+        *
+        * QUOTING NOTE:
+        *
+        * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
+        * file.  It was almost certainly a bug, but that's what bug-for-bug
+        * compatibility means, Grasshopper.  Also, ^V's escape the command
+        * delimiters.  Literal next quote characters in front of the newlines,
+        * '|' characters or literal next characters are stripped as they're
+        * no longer useful.
+        */
+       vi_address = ecp->clen != 0 && ecp->cp[0] != '\n';
+       for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+               ch = (UCHAR_T)ecp->cp[0];
+               if (IS_ESCAPE(sp, ecp, ch) && ecp->clen > 1) {
+                       ARG_CHAR_T tmp1 = (UCHAR_T)ecp->cp[1];
+                       if (tmp1 == '\n' || tmp1 == '|') {
+                               if (tmp1 == '\n') {
+                                       ++wp->if_lno;
+                                       ++ecp->if_lno;
+                               }
+                               ++discard;
+                               --ecp->clen;
+                               ++ecp->cp;
+                               ch = tmp1;
+                       }
+               } else if (ch == '\n' || ch == '|') {
+                       if (ch == '\n')
+                               F_SET(ecp, E_NEWLINE);
+                       --ecp->clen;
+                       break;
+               }
+               *p++ = ch;
+       }
+
+       /*
+        * Save off the next command information, go back to the
+        * original start of the command.
+        */
+       p = ecp->cp + 1;
+       ecp->cp = ecp->save_cmd;
+       ecp->save_cmd = p;
+       ecp->save_cmdlen = ecp->clen;
+       ecp->clen = ((ecp->save_cmd - ecp->cp) - 1) - discard;
+
+       /*
+        * QUOTING NOTE:
+        *
+        * The "set tags" command historically used a backslash, not the
+        * user's literal next character, to escape whitespace.  Handle
+        * it here instead of complicating the argv_exp3() code.  Note,
+        * this isn't a particularly complex trap, and if backslashes were
+        * legal in set commands, this would have to be much more complicated.
+        */
+       if (ecp->cmd == &cmds[C_SET])
+               for (p = ecp->cp, len = ecp->clen; len > 0; --len, ++p)
+                       if (*p == '\\')
+                               *p = CH_LITERAL;
+
+       /*
+        * Set the default addresses.  It's an error to specify an address for
+        * a command that doesn't take them.  If two addresses are specified
+        * for a command that only takes one, lose the first one.  Two special
+        * cases here, some commands take 0 or 2 addresses.  For most of them
+        * (the E_ADDR2_ALL flag), 0 defaults to the entire file.  For one
+        * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
+        *
+        * Also, if the file is empty, some commands want to use an address of
+        * 0, i.e. the entire file is 0 to 0, and the default first address is
+        * 0.  Otherwise, an entire file is 1 to N and the default line is 1.
+        * Note, we also add the E_ADDR_ZERO flag to the command flags, for the
+        * case where the 0 address is only valid if it's a default address.
+        *
+        * Also, set a flag if we set the default addresses.  Some commands
+        * (ex: z) care if the user specified an address or if we just used
+        * the current cursor.
+        */
+       switch (F_ISSET(ecp, E_ADDR1 | E_ADDR2 | E_ADDR2_ALL | E_ADDR2_NONE)) {
+       case E_ADDR1:                           /* One address: */
+               switch (ecp->addrcnt) {
+               case 0:                         /* Default cursor/empty file. */
+                       ecp->addrcnt = 1;
+                       F_SET(ecp, E_ADDR_DEF);
+                       if (F_ISSET(ecp, E_ADDR_ZERODEF)) {
+                               if (db_last(sp, &lno))
+                                       goto err;
+                               if (lno == 0) {
+                                       ecp->addr1.lno = 0;
+                                       F_SET(ecp, E_ADDR_ZERO);
+                               } else
+                                       ecp->addr1.lno = sp->lno;
+                       } else
+                               ecp->addr1.lno = sp->lno;
+                       ecp->addr1.cno = sp->cno;
+                       break;
+               case 1:
+                       break;
+               case 2:                         /* Lose the first address. */
+                       ecp->addrcnt = 1;
+                       ecp->addr1 = ecp->addr2;
+               }
+               break;
+       case E_ADDR2_NONE:                      /* Zero/two addresses: */
+               if (ecp->addrcnt == 0)          /* Default to nothing. */
+                       break;
+               goto two_addr;
+       case E_ADDR2_ALL:                       /* Zero/two addresses: */
+               if (ecp->addrcnt == 0) {        /* Default entire/empty file. */
+                       F_SET(ecp, E_ADDR_DEF);
+                       ecp->addrcnt = 2;
+                       if (sp->ep == NULL)
+                               ecp->addr2.lno = 0;
+                       else if (db_last(sp, &ecp->addr2.lno))
+                               goto err;
+                       if (F_ISSET(ecp, E_ADDR_ZERODEF) &&
+                           ecp->addr2.lno == 0) {
+                               ecp->addr1.lno = 0;
+                               F_SET(ecp, E_ADDR_ZERO);
+                       } else
+                               ecp->addr1.lno = 1;
+                       ecp->addr1.cno = ecp->addr2.cno = 0;
+                       F_SET(ecp, E_ADDR2_ALL);
+                       break;
+               }
+               /* FALLTHROUGH */
+       case E_ADDR2:                           /* Two addresses: */
+two_addr:      switch (ecp->addrcnt) {
+               case 0:                         /* Default cursor/empty file. */
+                       ecp->addrcnt = 2;
+                       F_SET(ecp, E_ADDR_DEF);
+                       if (sp->lno == 1 &&
+                           F_ISSET(ecp, E_ADDR_ZERODEF)) {
+                               if (db_last(sp, &lno))
+                                       goto err;
+                               if (lno == 0) {
+                                       ecp->addr1.lno = ecp->addr2.lno = 0;
+                                       F_SET(ecp, E_ADDR_ZERO);
+                               } else
+                                       ecp->addr1.lno =
+                                           ecp->addr2.lno = sp->lno;
+                       } else
+                               ecp->addr1.lno = ecp->addr2.lno = sp->lno;
+                       ecp->addr1.cno = ecp->addr2.cno = sp->cno;
+                       break;
+               case 1:                         /* Default to first address. */
+                       //ecp->addrcnt = 2;     /* XXX Was this needed ??? */
+                       ecp->addr2 = ecp->addr1;
+                       break;
+               case 2:
+                       break;
+               }
+               break;
+       default:
+               if (ecp->addrcnt)               /* Error. */
+                       goto usage;
+       }
+
+       /*
+        * !!!
+        * The ^D scroll command historically scrolled the value of the scroll
+        * option or to EOF.  It was an error if the cursor was already at EOF.
+        * (Leading addresses were permitted, but were then ignored.)
+        */
+       if (ecp->cmd == &cmds[C_SCROLL]) {
+               ecp->addrcnt = 2;
+               ecp->addr1.lno = sp->lno + 1;
+               ecp->addr2.lno = sp->lno + O_VAL(sp, O_SCROLL);
+               ecp->addr1.cno = ecp->addr2.cno = sp->cno;
+               if (db_last(sp, &lno))
+                       goto err;
+               if (lno != 0 && lno > sp->lno && ecp->addr2.lno > lno)
+                       ecp->addr2.lno = lno;
+       }
+
+       ecp->flagoff = 0;
+       for (np = ecp->cmd->syntax; *np != '\0'; ++np) {
+               /*
+                * The force flag is sensitive to leading whitespace, i.e.
+                * "next !" is different from "next!".  Handle it before
+                * skipping leading <blank>s.
+                */
+               if (*np == '!') {
+                       if (ecp->clen > 0 && *ecp->cp == '!') {
+                               ++ecp->cp;
+                               --ecp->clen;
+                               FL_SET(ecp->iflags, E_C_FORCE);
+                       }
+                       continue;
+               }
+
+               /* Skip leading <blank>s. */
+               for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+                       if (!ISBLANK(*ecp->cp))
+                               break;
+               if (ecp->clen == 0)
+                       break;
+
+               switch (*np) {
+               case '1':                               /* +, -, #, l, p */
+                       /*
+                        * !!!
+                        * Historically, some flags were ignored depending
+                        * on where they occurred in the command line.  For
+                        * example, in the command, ":3+++p--#", historic vi
+                        * acted on the '#' flag, but ignored the '-' flags.
+                        * It's unambiguous what the flags mean, so we just
+                        * handle them regardless of the stupidity of their
+                        * location.
+                        */
+                       for (; ecp->clen; --ecp->clen, ++ecp->cp)
+                               switch (*ecp->cp) {
+                               case '+':
+                                       ++ecp->flagoff;
+                                       break;
+                               case '-':
+                               case '^':
+                                       --ecp->flagoff;
+                                       break;
+                               case '#':
+                                       F_CLR(ecp, E_OPTNUM);
+                                       FL_SET(ecp->iflags, E_C_HASH);
+                                       exp->fdef |= E_C_HASH;
+                                       break;
+                               case 'l':
+                                       FL_SET(ecp->iflags, E_C_LIST);
+                                       exp->fdef |= E_C_LIST;
+                                       break;
+                               case 'p':
+                                       FL_SET(ecp->iflags, E_C_PRINT);
+                                       exp->fdef |= E_C_PRINT;
+                                       break;
+                               default:
+                                       goto end_case1;
+                               }
+end_case1:             break;
+               case '2':                               /* -, ., +, ^ */
+               case '3':                               /* -, ., +, ^, = */
+                       for (; ecp->clen; --ecp->clen, ++ecp->cp)
+                               switch (*ecp->cp) {
+                               case '-':
+                                       FL_SET(ecp->iflags, E_C_DASH);
+                                       break;
+                               case '.':
+                                       FL_SET(ecp->iflags, E_C_DOT);
+                                       break;
+                               case '+':
+                                       FL_SET(ecp->iflags, E_C_PLUS);
+                                       break;
+                               case '^':
+                                       FL_SET(ecp->iflags, E_C_CARAT);
+                                       break;
+                               case '=':
+                                       if (*np == '3') {
+                                               FL_SET(ecp->iflags, E_C_EQUAL);
+                                               break;
+                                       }
+                                       /* FALLTHROUGH */
+                               default:
+                                       goto end_case23;
+                               }
+end_case23:            break;
+               case 'b':                               /* buffer */
+                       /*
+                        * !!!
+                        * Historically, "d #" was a delete with a flag, not a
+                        * delete into the '#' buffer.  If the current command
+                        * permits a flag, don't use one as a buffer.  However,
+                        * the 'l' and 'p' flags were legal buffer names in the
+                        * historic ex, and were used as buffers, not flags.
+                        */
+                       if ((ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
+                           ecp->cp[0] == '^' || ecp->cp[0] == '#') &&
+                           strchr(np, '1') != NULL)
+                               break;
+                       /*
+                        * !!!
+                        * Digits can't be buffer names in ex commands, or the
+                        * command "d2" would be a delete into buffer '2', and
+                        * not a two-line deletion.
+                        */
+                       if (!ISDIGIT((UCHAR_T)ecp->cp[0])) {
+                               ecp->buffer = (UCHAR_T)*ecp->cp;
+                               ++ecp->cp;
+                               --ecp->clen;
+                               FL_SET(ecp->iflags, E_C_BUFFER);
+                       }
+                       break;
+               case 'c':                               /* count [01+a] */
+                       ++np;
+                       /* Validate any signed value. */
+                       if (!ISDIGIT((UCHAR_T)*ecp->cp) && (*np != '+' ||
+                           (*ecp->cp != '+' && *ecp->cp != '-')))
+                               break;
+                       /* If a signed value, set appropriate flags. */
+                       if (*ecp->cp == '-')
+                               FL_SET(ecp->iflags, E_C_COUNT_NEG);
+                       else if (*ecp->cp == '+')
+                               FL_SET(ecp->iflags, E_C_COUNT_POS);
+                       if ((nret =
+                           nget_slong(sp, &ltmp, ecp->cp, &t, 10)) != NUM_OK) {
+                               ex_badaddr(sp, NULL, A_NOTSET, nret);
+                               goto err;
+                       }
+                       if (ltmp == 0 && *np != '0') {
+                               msgq(sp, M_ERR, "083|Count may not be zero");
+                               goto err;
+                       }
+                       ecp->clen -= (t - ecp->cp);
+                       ecp->cp = t;
+
+                       /*
+                        * Counts as address offsets occur in commands taking
+                        * two addresses.  Historic vi practice was to use
+                        * the count as an offset from the *second* address.
+                        *
+                        * Set a count flag; some underlying commands (see
+                        * join) do different things with counts than with
+                        * line addresses.
+                        */
+                       if (*np == 'a') {
+                               ecp->addr1 = ecp->addr2;
+                               ecp->addr2.lno = ecp->addr1.lno + ltmp - 1;
+                       } else
+                               ecp->count = ltmp;
+                       FL_SET(ecp->iflags, E_C_COUNT);
+                       break;
+               case 'f':                               /* file */
+                       if (argv_exp2(sp, ecp, ecp->cp, ecp->clen))
+                               goto err;
+                       goto arg_cnt_chk;
+               case 'l':                               /* line */
+                       /*
+                        * Get a line specification.
+                        *
+                        * If the line was a search expression, we may have
+                        * changed state during the call, and we're now
+                        * searching the file.  Push ourselves onto the state
+                        * stack.
+                        */
+                       if (ex_line(sp, ecp, &cur, &isaddr, &tmp))
+                               goto rfail;
+                       if (tmp)
+                               goto err;
+
+                       /* Line specifications are always required. */
+                       if (!isaddr) {
+                               msgq_wstr(sp, M_ERR, ecp->cp,
+                                    "084|%s: bad line specification");
+                               goto err;
+                       }
+                       /*
+                        * The target line should exist for these commands,
+                        * but 0 is legal for them as well.
+                        */
+                       if (cur.lno != 0 && !db_exist(sp, cur.lno)) {
+                               ex_badaddr(sp, NULL, A_EOF, NUM_OK);
+                               goto err;
+                       }
+                       ecp->lineno = cur.lno;
+                       break;
+               case 'S':                               /* string, file exp. */
+                       if (ecp->clen != 0) {
+                               if (argv_exp1(sp, ecp, ecp->cp,
+                                   ecp->clen, ecp->cmd == &cmds[C_BANG]))
+                                       goto err;
+                               goto addr_verify;
+                       }
+                       /* FALLTHROUGH */
+               case 's':                               /* string */
+                       if (argv_exp0(sp, ecp, ecp->cp, ecp->clen))
+                               goto err;
+                       goto addr_verify;
+               case 'W':                               /* word string */
+                       /*
+                        * QUOTING NOTE:
+                        *
+                        * Literal next characters escape the following
+                        * character.  Quoting characters are stripped here
+                        * since they are no longer useful.
+                        *
+                        * First there was the word.
+                        */
+                       for (p = t = ecp->cp;
+                           ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+                               ch = (UCHAR_T)*ecp->cp;
+                               if (IS_ESCAPE(sp,
+                                   ecp, ch) && ecp->clen > 1) {
+                                       --ecp->clen;
+                                       *p++ = *++ecp->cp;
+                               } else if (ISBLANK(ch)) {
+                                       ++ecp->cp;
+                                       --ecp->clen;
+                                       break;
+                               } else
+                                       *p++ = ch;
+                       }
+                       if (argv_exp0(sp, ecp, t, p - t))
+                               goto err;
+
+                       /* Delete intervening whitespace. */
+                       for (; ecp->clen > 0;
+                           --ecp->clen, ++ecp->cp) {
+                               ch = (UCHAR_T)*ecp->cp;
+                               if (!ISBLANK(ch))
+                                       break;
+                       }
+                       if (ecp->clen == 0)
+                               goto usage;
+
+                       /* Followed by the string. */
+                       for (p = t = ecp->cp; ecp->clen > 0;
+                           --ecp->clen, ++ecp->cp, ++p) {
+                               ch = (UCHAR_T)*ecp->cp;
+                               if (IS_ESCAPE(sp,
+                                   ecp, ch) && ecp->clen > 1) {
+                                       --ecp->clen;
+                                       *p = *++ecp->cp;
+                               } else
+                                       *p = ch;
+                       }
+                       if (argv_exp0(sp, ecp, t, p - t))
+                               goto err;
+                       goto addr_verify;
+               case 'w':                               /* word */
+                       if (argv_exp3(sp, ecp, ecp->cp, ecp->clen))
+                               goto err;
+arg_cnt_chk:           if (*++np != 'N') {             /* N */
+                               /*
+                                * If a number is specified, must either be
+                                * 0 or that number, if optional, and that
+                                * number, if required.
+                                */
+                               tmp = *np - '0';
+                               if ((*++np != 'o' || exp->argsoff != 0) &&
+                                   exp->argsoff != tmp)
+                                       goto usage;
+                       }
+                       goto addr_verify;
+               default: {
+                       const char *nstr;
+                       size_t nlen;
+                       INT2CHAR(sp, ecp->cmd->name, STRLEN(ecp->cmd->name) + 1,
+                           nstr, nlen);
+                       msgq(sp, M_ERR,
+                           "085|Internal syntax table error (%s: %s)",
+                           nstr, KEY_NAME(sp, *np));
+               }
+               }
+       }
+
+       /* Skip trailing whitespace. */
+       for (; ecp->clen > 0; --ecp->clen) {
+               ch = (UCHAR_T)*ecp->cp++;
+               if (!ISBLANK(ch))
+                       break;
+       }
+
+       /*
+        * There shouldn't be anything left, and no more required fields,
+        * i.e neither 'l' or 'r' in the syntax string.
+        */
+       if (ecp->clen != 0 || strpbrk(np, "lr")) {
+usage:         msgq(sp, M_ERR, "086|Usage: %s", ecp->cmd->usage);
+               goto err;
+       }
+
+       /*
+        * Verify that the addresses are legal.  Check the addresses here,
+        * because this is a place where all ex addresses pass through.
+        * (They don't all pass through ex_line(), for instance.)  We're
+        * assuming that any non-existent line doesn't exist because it's
+        * past the end-of-file.  That's a pretty good guess.
+        *
+        * If it's a "default vi command", an address of zero is okay.
+        */
+addr_verify:
+       switch (ecp->addrcnt) {
+       case 2:
+               /*
+                * Historic ex/vi permitted commands with counts to go past
+                * EOF.  So, for example, if the file only had 5 lines, the
+                * ex command "1,6>" would fail, but the command ">300"
+                * would succeed.  Since we don't want to have to make all
+                * of the underlying commands handle random line numbers,
+                * fix it here.
+                */
+               if (ecp->addr2.lno == 0) {
+                       if (!F_ISSET(ecp, E_ADDR_ZERO) &&
+                           (F_ISSET(sp, SC_EX) ||
+                           !F_ISSET(ecp, E_USELASTCMD))) {
+                               ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
+                               goto err;
+                       }
+               } else if (!db_exist(sp, ecp->addr2.lno)) {
+                       if (FL_ISSET(ecp->iflags, E_C_COUNT)) {
+                               if (db_last(sp, &lno))
+                                       goto err;
+                               ecp->addr2.lno = lno;
+                       } else {
+                               ex_badaddr(sp, NULL, A_EOF, NUM_OK);
+                               goto err;
+                       }
+               }
+               /* FALLTHROUGH */
+       case 1:
+               if (ecp->addr1.lno == 0) {
+                       if (!F_ISSET(ecp, E_ADDR_ZERO) &&
+                           (F_ISSET(sp, SC_EX) ||
+                           !F_ISSET(ecp, E_USELASTCMD))) {
+                               ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
+                               goto err;
+                       }
+               } else if (!db_exist(sp, ecp->addr1.lno)) {
+                       ex_badaddr(sp, NULL, A_EOF, NUM_OK);
+                       goto err;
+               }
+               break;
+       }
+
+       /*
+        * If doing a default command and there's nothing left on the line,
+        * vi just moves to the line.  For example, ":3" and ":'a,'b" just
+        * move to line 3 and line 'b, respectively, but ":3|" prints line 3.
+        *
+        * !!!
+        * In addition, IF THE LINE CHANGES, move to the first nonblank of
+        * the line.
+        *
+        * !!!
+        * This is done before the absolute mark gets set; historically,
+        * "/a/,/b/" did NOT set vi's absolute mark, but "/a/,/b/d" did.
+        */
+       if ((F_ISSET(sp, SC_VI) || F_ISSET(ecp, E_NOPRDEF)) &&
+           F_ISSET(ecp, E_USELASTCMD) && vi_address == 0) {
+               switch (ecp->addrcnt) {
+               case 2:
+                       if (sp->lno !=
+                           (ecp->addr2.lno ? ecp->addr2.lno : 1)) {
+                               sp->lno =
+                                   ecp->addr2.lno ? ecp->addr2.lno : 1;
+                               sp->cno = 0;
+                               (void)nonblank(sp, sp->lno, &sp->cno);
+                       }
+                       break;
+               case 1:
+                       if (sp->lno !=
+                           (ecp->addr1.lno ? ecp->addr1.lno : 1)) {
+                               sp->lno =
+                                   ecp->addr1.lno ? ecp->addr1.lno : 1;
+                               sp->cno = 0;
+                               (void)nonblank(sp, sp->lno, &sp->cno);
+                       }
+                       break;
+               }
+               ecp->cp = ecp->save_cmd;
+               ecp->clen = ecp->save_cmdlen;
+               goto loop;
+       }
+
+       /*
+        * Set the absolute mark -- we have to set it for vi here, in case
+        * it's a compound command, e.g. ":5p|6" should set the absolute
+        * mark for vi.
+        */
+       if (F_ISSET(ecp, E_ABSMARK)) {
+               cur.lno = sp->lno;
+               cur.cno = sp->cno;
+               F_CLR(ecp, E_ABSMARK);
+               if (mark_set(sp, ABSMARK1, &cur, 1))
+                       goto err;
+       }
+
+#if defined(DEBUG) && defined(COMLOG)
+       ex_comlog(sp, ecp);
+#endif
+       /* Increment the command count if not called from vi. */
+       if (F_ISSET(sp, SC_EX))
+               ++sp->ccnt;
+
+       /*
+        * If file state available, and not doing a global command,
+        * log the start of an action.
+        */
+       if (sp->ep != NULL && !F_ISSET(sp, SC_EX_GLOBAL))
+               (void)log_cursor(sp);
+
+       /*
+        * !!!
+        * There are two special commands for the purposes of this code: the
+        * default command (<carriage-return>) or the scrolling commands (^D
+        * and <EOF>) as the first non-<blank> characters  in the line.
+        *
+        * If this is the first command in the command line, we received the
+        * command from the ex command loop and we're talking to a tty, and
+        * and there's nothing else on the command line, and it's one of the
+        * special commands, we move back up to the previous line, and erase
+        * the prompt character with the output.  Since ex runs in canonical
+        * mode, we don't have to do anything else, a <newline> has already
+        * been echoed by the tty driver.  It's OK if vi calls us -- we won't
+        * be in ex mode so we'll do nothing.
+        */
+       if (F_ISSET(ecp, E_NRSEP)) {
+               if (sp->ep != NULL &&
+                   F_ISSET(sp, SC_EX) && !F_ISSET(gp, G_SCRIPTED) &&
+                   (F_ISSET(ecp, E_USELASTCMD) || ecp->cmd == &cmds[C_SCROLL]))
+                       gp->scr_ex_adjust(sp, EX_TERM_SCROLL);
+               F_CLR(ecp, E_NRSEP);
+       }
+
+       /*
+        * Call the underlying function for the ex command.
+        *
+        * XXX
+        * Interrupts behave like errors, for now.
+        */
+       if (ecp->cmd->fn(sp, ecp) || INTERRUPTED(sp)) {
+               if (F_ISSET(gp, G_SCRIPTED))
+                       F_SET(sp, SC_EXIT_FORCE);
+               goto err;
+       }
+
+#ifdef DEBUG
+       /* Make sure no function left global temporary space locked. */
+       if (F_ISSET(wp, W_TMP_INUSE)) {
+               F_CLR(wp, W_TMP_INUSE);
+               msgq(sp, M_ERR, "087|%s: temporary buffer not released",
+                   ecp->cmd->name);
+       }
+#endif
+       /*
+        * Ex displayed the number of lines modified immediately after each
+        * command, so the command "1,10d|1,10d" would display:
+        *
+        *      10 lines deleted
+        *      10 lines deleted
+        *      <autoprint line>
+        *
+        * Executing ex commands from vi only reported the final modified
+        * lines message -- that's wrong enough that we don't match it.
+        */
+       if (F_ISSET(sp, SC_EX))
+               mod_rpt(sp);
+
+       /*
+        * Integrate any offset parsed by the underlying command, and make
+        * sure the referenced line exists.
+        *
+        * XXX
+        * May not match historic practice (which I've never been able to
+        * completely figure out.)  For example, the '=' command from vi
+        * mode often got the offset wrong, and complained it was too large,
+        * but didn't seem to have a problem with the cursor.  If anyone
+        * complains, ask them how it's supposed to work, they might know.
+        */
+       if (sp->ep != NULL && ecp->flagoff) {
+               if (ecp->flagoff < 0) {
+                       if (sp->lno <= (db_recno_t)(-ecp->flagoff)) {
+                               msgq(sp, M_ERR,
+                                   "088|Flag offset to before line 1");
+                               goto err;
+                       }
+               } else {
+                       if (!NPFITS(DB_MAX_RECORDS, sp->lno, (db_recno_t)ecp->flagoff)) {
+                               ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
+                               goto err;
+                       }
+                       if (!db_exist(sp, sp->lno + ecp->flagoff)) {
+                               msgq(sp, M_ERR,
+                                   "089|Flag offset past end-of-file");
+                               goto err;
+                       }
+               }
+               sp->lno += ecp->flagoff;
+       }
+
+       /*
+        * If the command executed successfully, we may want to display a line
+        * based on the autoprint option or an explicit print flag.  (Make sure
+        * that there's a line to display.)  Also, the autoprint edit option is
+        * turned off for the duration of global commands.
+        */
+       if (F_ISSET(sp, SC_EX) && sp->ep != NULL && sp->lno != 0) {
+               /*
+                * The print commands have already handled the `print' flags.
+                * If so, clear them.
+                */
+               if (FL_ISSET(ecp->iflags, E_CLRFLAG))
+                       FL_CLR(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT);
+
+               /* If hash set only because of the number option, discard it. */
+               if (F_ISSET(ecp, E_OPTNUM))
+                       FL_CLR(ecp->iflags, E_C_HASH);
+
+               /*
+                * If there was an explicit flag to display the new cursor line,
+                * or autoprint is set and a change was made, display the line.
+                * If any print flags were set use them, else default to print.
+                */
+               LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT));
+               if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO) &&
+                   !F_ISSET(sp, SC_EX_GLOBAL) &&
+                   O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT))
+                       LF_INIT(E_C_PRINT);
+
+               if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)) {
+                       cur.lno = sp->lno;
+                       cur.cno = 0;
+                       (void)ex_print(sp, ecp, &cur, &cur, flags);
+               }
+       }
+
+       /*
+        * If the command had an associated "+cmd", it has to be executed
+        * before we finish executing any more of this ex command.  For
+        * example, consider a .exrc file that contains the following lines:
+        *
+        *      :set all
+        *      :edit +25 file.c|s/abc/ABC/|1
+        *      :3,5 print
+        *
+        * This can happen more than once -- the historic vi simply hung or
+        * dropped core, of course.  Prepend the + command back into the
+        * current command and continue.  We may have to add an additional
+        * <literal next> character.  We know that it will fit because we
+        * discarded at least one space and the + character.
+        */
+       if (arg1_len != 0) {
+               /*
+                * If the last character of the + command was a <literal next>
+                * character, it would be treated differently because of the
+                * append.  Quote it, if necessary.
+                */
+               if (IS_ESCAPE(sp, ecp, arg1[arg1_len - 1])) {
+                       *--ecp->save_cmd = CH_LITERAL;
+                       ++ecp->save_cmdlen;
+               }
+
+               ecp->save_cmd -= arg1_len;
+               ecp->save_cmdlen += arg1_len;
+               MEMCPYW(ecp->save_cmd, arg1, arg1_len);
+
+               /*
+                * Any commands executed from a +cmd are executed starting at
+                * the first column of the last line of the file -- NOT the
+                * first nonblank.)  The main file startup code doesn't know
+                * that a +cmd was set, however, so it may have put us at the
+                * top of the file.  (Note, this is safe because we must have
+                * switched files to get here.)
+                */
+               F_SET(ecp, E_MOVETOEND);
+       }
+
+       /* Update the current command. */
+       ecp->cp = ecp->save_cmd;
+       ecp->clen = ecp->save_cmdlen;
+
+       /*
+        * !!!
+        * If we've changed screens or underlying files, any pending global or
+        * v command, or @ buffer that has associated addresses, has to be
+        * discarded.  This is historic practice for globals, and necessary for
+        * @ buffers that had associated addresses.
+        *
+        * Otherwise, if we've changed underlying files, it's not a problem,
+        * we continue with the rest of the ex command(s), operating on the
+        * new file.  However, if we switch screens (either by exiting or by
+        * an explicit command), we have no way of knowing where to put output
+        * messages, and, since we don't control screens here, we could screw
+        * up the upper layers, (e.g. we could exit/reenter a screen multiple
+        * times).  So, return and continue after we've got a new screen.
+        */
+       if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_FSWITCH | SC_SSWITCH)) {
+               at_found = gv_found = 0;
+               for (ecp = wp->ecq.lh_first;
+                   ecp != NULL; ecp = ecp->q.le_next)
+                       switch (ecp->agv_flags) {
+                       case 0:
+                       case AGV_AT_NORANGE:
+                               break;
+                       case AGV_AT:
+                               if (!at_found) {
+                                       at_found = 1;
+                                       msgq(sp, M_ERR,
+               "090|@ with range running when the file/screen changed");
+                               }
+                               break;
+                       case AGV_GLOBAL:
+                       case AGV_V:
+                               if (!gv_found) {
+                                       gv_found = 1;
+                                       msgq(sp, M_ERR,
+               "091|Global/v command running when the file/screen changed");
+                               }
+                               break;
+                       default:
+                               abort();
+                       }
+               if (at_found || gv_found)
+                       goto discard;
+               if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_SSWITCH))
+                       goto rsuccess;
+       }
+
+       goto loop;
+       /* NOTREACHED */
+
+err:   /*
+        * On command failure, we discard keys and pending commands remaining,
+        * as well as any keys that were mapped and waiting.  The save_cmdlen
+        * test is not necessarily correct.  If we fail early enough we don't
+        * know if the entire string was a single command or not.  Guess, as
+        * it's useful to know if commands other than the current one are being
+        * discarded.
+        */
+       if (ecp->save_cmdlen == 0)
+               for (; ecp->clen; --ecp->clen) {
+                       ch = (UCHAR_T)*ecp->cp++;
+                       if (IS_ESCAPE(sp, ecp, ch) && ecp->clen > 1) {
+                               --ecp->clen;
+                               ++ecp->cp;
+                       } else if (ch == '\n' || ch == '|') {
+                               if (ecp->clen > 1)
+                                       ecp->save_cmdlen = 1;
+                               break;
+                       }
+               }
+       if (ecp->save_cmdlen != 0 || wp->ecq.lh_first != &wp->excmd) {
+discard:       msgq(sp, M_BERR,
+                   "092|Ex command failed: pending commands discarded");
+               ex_discard(sp);
+       }
+       if (v_event_flush(sp, CH_MAPPED))
+               msgq(sp, M_BERR,
+                   "093|Ex command failed: mapped keys discarded");
+
+rfail: tmp = 1;
+       if (0)
+rsuccess:      tmp = 0;
+
+       /* Turn off any file name error information. */
+       wp->if_name = NULL;
+
+       /* Turn off the global bit. */
+       F_CLR(sp, SC_EX_GLOBAL);
+
+       return (tmp);
+}
+
+/*
+ * ex_range --
+ *     Get a line range for ex commands, or perform a vi ex address search.
+ *
+ * PUBLIC: int ex_range __P((SCR *, EXCMD *, int *));
+ */
+int
+ex_range(SCR *sp, EXCMD *ecp, int *errp)
+{
+       enum { ADDR_FOUND, ADDR_NEED, ADDR_NONE } addr;
+       GS *gp;
+       EX_PRIVATE *exp;
+       MARK m;
+       int isaddr;
+
+       *errp = 0;
+
+       /*
+        * Parse comma or semi-colon delimited line specs.
+        *
+        * Semi-colon delimiters update the current address to be the last
+        * address.  For example, the command
+        *
+        *      :3;/pattern/ecp->cp
+        *
+        * will search for pattern from line 3.  In addition, if ecp->cp
+        * is not a valid command, the current line will be left at 3, not
+        * at the original address.
+        *
+        * Extra addresses are discarded, starting with the first.
+        *
+        * !!!
+        * If any addresses are missing, they default to the current line.
+        * This was historically true for both leading and trailing comma
+        * delimited addresses as well as for trailing semicolon delimited
+        * addresses.  For consistency, we make it true for leading semicolon
+        * addresses as well.
+        */
+       gp = sp->gp;
+       exp = EXP(sp);
+       for (addr = ADDR_NONE, ecp->addrcnt = 0; ecp->clen > 0;)
+               switch (*ecp->cp) {
+               case '%':               /* Entire file. */
+                       /* Vi ex address searches didn't permit % signs. */
+                       if (F_ISSET(ecp, E_VISEARCH))
+                               goto ret;
+
+                       /* It's an error if the file is empty. */
+                       if (sp->ep == NULL) {
+                               ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
+                               *errp = 1;
+                               return (0);
+                       }
+                       /*
+                        * !!!
+                        * A percent character addresses all of the lines in
+                        * the file.  Historically, it couldn't be followed by
+                        * any other address.  We do it as a text substitution
+                        * for simplicity.  POSIX 1003.2 is expected to follow
+                        * this practice.
+                        *
+                        * If it's an empty file, the first line is 0, not 1.
+                        */
+                       if (addr == ADDR_FOUND) {
+                               ex_badaddr(sp, NULL, A_COMBO, NUM_OK);
+                               *errp = 1;
+                               return (0);
+                       }
+                       if (db_last(sp, &ecp->addr2.lno))
+                               return (1);
+                       ecp->addr1.lno = ecp->addr2.lno == 0 ? 0 : 1;
+                       ecp->addr1.cno = ecp->addr2.cno = 0;
+                       ecp->addrcnt = 2;
+                       addr = ADDR_FOUND;
+                       ++ecp->cp;
+                       --ecp->clen;
+                       break;
+               case ',':               /* Comma delimiter. */
+                       /* Vi ex address searches didn't permit commas. */
+                       if (F_ISSET(ecp, E_VISEARCH))
+                               goto ret;
+                       /* FALLTHROUGH */
+               case ';':               /* Semi-colon delimiter. */
+                       if (sp->ep == NULL) {
+                               ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
+                               *errp = 1;
+                               return (0);
+                       }
+                       if (addr != ADDR_FOUND)
+                               switch (ecp->addrcnt) {
+                               case 0:
+                                       ecp->addr1.lno = sp->lno;
+                                       ecp->addr1.cno = sp->cno;
+                                       ecp->addrcnt = 1;
+                                       break;
+                               case 2:
+                                       ecp->addr1 = ecp->addr2;
+                                       /* FALLTHROUGH */
+                               case 1:
+                                       ecp->addr2.lno = sp->lno;
+                                       ecp->addr2.cno = sp->cno;
+                                       ecp->addrcnt = 2;
+                                       break;
+                               }
+                       if (*ecp->cp == ';')
+                               switch (ecp->addrcnt) {
+                               case 0:
+                                       abort();
+                                       /* NOTREACHED */
+                               case 1:
+                                       sp->lno = ecp->addr1.lno;
+                                       sp->cno = ecp->addr1.cno;
+                                       break;
+                               case 2:
+                                       sp->lno = ecp->addr2.lno;
+                                       sp->cno = ecp->addr2.cno;
+                                       break;
+                               }
+                       addr = ADDR_NEED;
+                       /* FALLTHROUGH */
+               case ' ':               /* Whitespace. */
+               case '\t':              /* Whitespace. */
+                       ++ecp->cp;
+                       --ecp->clen;
+                       break;
+               default:
+                       /* Get a line specification. */
+                       if (ex_line(sp, ecp, &m, &isaddr, errp))
+                               return (1);
+                       if (*errp)
+                               return (0);
+                       if (!isaddr)
+                               goto ret;
+                       if (addr == ADDR_FOUND) {
+                               ex_badaddr(sp, NULL, A_COMBO, NUM_OK);
+                               *errp = 1;
+                               return (0);
+                       }
+                       switch (ecp->addrcnt) {
+                       case 0:
+                               ecp->addr1 = m;
+                               ecp->addrcnt = 1;
+                               break;
+                       case 1:
+                               ecp->addr2 = m;
+                               ecp->addrcnt = 2;
+                               break;
+                       case 2:
+                               ecp->addr1 = ecp->addr2;
+                               ecp->addr2 = m;
+                               break;
+                       }
+                       addr = ADDR_FOUND;
+                       break;
+               }
+
+       /*
+        * !!!
+        * Vi ex address searches are indifferent to order or trailing
+        * semi-colons.
+        */
+ret:   if (F_ISSET(ecp, E_VISEARCH))
+               return (0);
+
+       if (addr == ADDR_NEED)
+               switch (ecp->addrcnt) {
+               case 0:
+                       ecp->addr1.lno = sp->lno;
+                       ecp->addr1.cno = sp->cno;
+                       ecp->addrcnt = 1;
+                       break;
+               case 2:
+                       ecp->addr1 = ecp->addr2;
+                       /* FALLTHROUGH */
+               case 1:
+                       ecp->addr2.lno = sp->lno;
+                       ecp->addr2.cno = sp->cno;
+                       ecp->addrcnt = 2;
+                       break;
+               }
+
+       if (ecp->addrcnt == 2 && ecp->addr2.lno < ecp->addr1.lno) {
+               msgq(sp, M_ERR,
+                   "094|The second address is smaller than the first");
+               *errp = 1;
+       }
+       return (0);
+}
+
+/*
+ * ex_line --
+ *     Get a single line address specifier.
+ *
+ * The way the "previous context" mark worked was that any "non-relative"
+ * motion set it.  While ex/vi wasn't totally consistent about this, ANY
+ * numeric address, search pattern, '$', or mark reference in an address
+ * was considered non-relative, and set the value.  Which should explain
+ * why we're hacking marks down here.  The problem was that the mark was
+ * only set if the command was called, i.e. we have to set a flag and test
+ * it later.
+ *
+ * XXX
+ * This is probably still not exactly historic practice, although I think
+ * it's fairly close.
+ */
+static int
+ex_line(SCR *sp, EXCMD *ecp, MARK *mp, int *isaddrp, int *errp)
+{
+       enum nresult nret;
+       EX_PRIVATE *exp;
+       GS *gp;
+       long total, val;
+       unsigned long uval;
+       int isneg;
+       int (*sf) __P((SCR *, MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int));
+       CHAR_T *endp;
+
+       gp = sp->gp;
+       exp = EXP(sp);
+
+       *isaddrp = *errp = 0;
+       F_CLR(ecp, E_DELTA);
+
+       /* No addresses permitted until a file has been read in. */
+       if (sp->ep == NULL && STRCHR(L("$0123456789'\\/?.+-^"), *ecp->cp)) {
+               ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
+               *errp = 1;
+               return (0);
+       }
+
+       switch (*ecp->cp) {
+       case '$':                               /* Last line in the file. */
+               *isaddrp = 1;
+               F_SET(ecp, E_ABSMARK);
+
+               mp->cno = 0;
+               if (db_last(sp, &mp->lno))
+                       return (1);
+               ++ecp->cp;
+               --ecp->clen;
+               break;                          /* Absolute line number. */
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+               *isaddrp = 1;
+               F_SET(ecp, E_ABSMARK);
+
+               if ((nret = nget_uslong(sp, &uval, ecp->cp, &endp, 10)) != NUM_OK) {
+                       ex_badaddr(sp, NULL, A_NOTSET, nret);
+                       *errp = 1;
+                       return (0);
+               }
+               if (!NPFITS(DB_MAX_RECORDS, 0, uval)) {
+                       ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
+                       *errp = 1;
+                       return (0);
+               }
+               mp->lno = uval;
+               mp->cno = 0;
+               ecp->clen -= (endp - ecp->cp);
+               ecp->cp = endp;
+               break;
+       case '\'':                              /* Use a mark. */
+               *isaddrp = 1;
+               F_SET(ecp, E_ABSMARK);
+
+               if (ecp->clen == 1) {
+                       msgq(sp, M_ERR, "095|No mark name supplied");
+                       *errp = 1;
+                       return (0);
+               }
+               if (mark_get(sp, ecp->cp[1], mp, M_ERR)) {
+                       *errp = 1;
+                       return (0);
+               }
+               ecp->cp += 2;
+               ecp->clen -= 2;
+               break;
+       case '\\':                              /* Search: forward/backward. */
+               /*
+                * !!!
+                * I can't find any difference between // and \/ or between
+                * ?? and \?.  Mark Horton doesn't remember there being any
+                * difference.  C'est la vie.
+                */
+               if (ecp->clen < 2 ||
+                   (ecp->cp[1] != '/' && ecp->cp[1] != '?')) {
+                       msgq(sp, M_ERR, "096|\\ not followed by / or ?");
+                       *errp = 1;
+                       return (0);
+               }
+               ++ecp->cp;
+               --ecp->clen;
+               sf = ecp->cp[0] == '/' ? f_search : b_search;
+               goto search;
+       case '/':                               /* Search forward. */
+               sf = f_search;
+               goto search;
+       case '?':                               /* Search backward. */
+               sf = b_search;
+
+search:                mp->lno = sp->lno;
+               mp->cno = sp->cno;
+               if (sf(sp, mp, mp, ecp->cp, ecp->clen, &endp,
+                   SEARCH_MSG | SEARCH_PARSE | SEARCH_SET |
+                   (F_ISSET(ecp, E_SEARCH_WMSG) ? SEARCH_WMSG : 0))) {
+                       *errp = 1;
+                       return (0);
+               }
+
+               /* Fix up the command pointers. */
+               ecp->clen -= (endp - ecp->cp);
+               ecp->cp = endp;
+
+               *isaddrp = 1;
+               F_SET(ecp, E_ABSMARK);
+               break;
+       case '.':                               /* Current position. */
+               *isaddrp = 1;
+               mp->cno = sp->cno;
+
+               /* If an empty file, then '.' is 0, not 1. */
+               if (sp->lno == 1) {
+                       if (db_last(sp, &mp->lno))
+                               return (1);
+                       if (mp->lno != 0)
+                               mp->lno = 1;
+               } else
+                       mp->lno = sp->lno;
+
+               /*
+                * !!!
+                * Historically, .<number> was the same as .+<number>, i.e.
+                * the '+' could be omitted.  (This feature is found in ed
+                * as well.)
+                */
+               if (ecp->clen > 1 && ISDIGIT((UCHAR_T)ecp->cp[1]))
+                       *ecp->cp = '+';
+               else {
+                       ++ecp->cp;
+                       --ecp->clen;
+               }
+               break;
+       }
+
+       /* Skip trailing <blank>s. */
+       for (; ecp->clen > 0 &&
+           ISBLANK((UCHAR_T)ecp->cp[0]); ++ecp->cp, --ecp->clen);
+
+       /*
+        * Evaluate any offset.  If no address yet found, the offset
+        * is relative to ".".
+        */
+       total = 0;
+       if (ecp->clen != 0 && (ISDIGIT((UCHAR_T)ecp->cp[0]) ||
+           ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
+           ecp->cp[0] == '^')) {
+               if (!*isaddrp) {
+                       *isaddrp = 1;
+                       mp->lno = sp->lno;
+                       mp->cno = sp->cno;
+               }
+               /*
+                * Evaluate an offset, defined as:
+                *
+                *              [+-^<blank>]*[<blank>]*[0-9]*
+                *
+                * The rough translation is any number of signs, optionally
+                * followed by numbers, or a number by itself, all <blank>
+                * separated.
+                *
+                * !!!
+                * All address offsets were additive, e.g. "2 2 3p" was the
+                * same as "7p", or, "/ZZZ/ 2" was the same as "/ZZZ/+2".
+                * Note, however, "2 /ZZZ/" was an error.  It was also legal
+                * to insert signs without numbers, so "3 - 2" was legal, and
+                * equal to 4.
+                *
+                * !!!
+                * Offsets were historically permitted for any line address,
+                * e.g. the command "1,2 copy 2 2 2 2" copied lines 1,2 after
+                * line 8.
+                *
+                * !!!
+                * Offsets were historically permitted for search commands,
+                * and handled as addresses: "/pattern/2 2 2" was legal, and
+                * referenced the 6th line after pattern.
+                */
+               F_SET(ecp, E_DELTA);
+               for (;;) {
+                       for (; ecp->clen > 0 && ISBLANK((UCHAR_T)ecp->cp[0]);
+                           ++ecp->cp, --ecp->clen);
+                       if (ecp->clen == 0 || (!ISDIGIT((UCHAR_T)ecp->cp[0]) &&
+                           ecp->cp[0] != '+' && ecp->cp[0] != '-' &&
+                           ecp->cp[0] != '^'))
+                               break;
+                       if (!ISDIGIT((UCHAR_T)ecp->cp[0]) &&
+                           !ISDIGIT((UCHAR_T)ecp->cp[1])) {
+                               total += ecp->cp[0] == '+' ? 1 : -1;
+                               --ecp->clen;
+                               ++ecp->cp;
+                       } else {
+                               if (ecp->cp[0] == '-' ||
+                                   ecp->cp[0] == '^') {
+                                       ++ecp->cp;
+                                       --ecp->clen;
+                                       isneg = 1;
+                               } else
+                                       isneg = 0;
+
+                               /* Get a signed long, add it to the total. */
+                               if ((nret = nget_slong(sp, &val,
+                                   ecp->cp, &endp, 10)) != NUM_OK ||
+                                   (nret = NADD_SLONG(sp,
+                                   total, val)) != NUM_OK) {
+                                       ex_badaddr(sp, NULL, A_NOTSET, nret);
+                                       *errp = 1;
+                                       return (0);
+                               }
+                               total += isneg ? -val : val;
+                               ecp->clen -= (endp - ecp->cp);
+                               ecp->cp = endp;
+                       }
+               }
+       }
+
+       /*
+        * Any value less than 0 is an error.  Make sure that the new value
+        * will fit into a db_recno_t.
+        */
+       if (*isaddrp && total != 0) {
+               if (total < 0) {
+                       if ((db_recno_t)-total > mp->lno) {
+                               msgq(sp, M_ERR,
+                           "097|Reference to a line number less than 0");
+                               *errp = 1;
+                               return (0);
+                       }
+               } else
+                       if (!NPFITS(DB_MAX_RECORDS, mp->lno, (unsigned long)total)) {
+                               ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
+                               *errp = 1;
+                               return (0);
+                       }
+               mp->lno += total;
+       }
+       return (0);
+}
+
+
+/*
+ * ex_load --
+ *     Load up the next command, which may be an @ buffer or global command.
+ */
+static int
+ex_load(SCR *sp)
+{
+       WIN *wp;
+       EXCMD *ecp;
+       RANGE *rp;
+
+       F_CLR(sp, SC_EX_GLOBAL);
+
+       /*
+        * Lose any exhausted commands.  We know that the first command
+        * can't be an AGV command, which makes things a bit easier.
+        */
+       for (wp = sp->wp;;) {
+               /*
+                * If we're back to the original structure, leave it around,
+                * but discard any allocated source name, we've returned to
+                * the beginning of the command stack.
+                */
+               if ((ecp = wp->ecq.lh_first) == &wp->excmd) {
+                       if (F_ISSET(ecp, E_NAMEDISCARD)) {
+                               free(ecp->if_name);
+                               ecp->if_name = NULL;
+                       }
+                       return (0);
+               }
+
+               /*
+                * ecp->clen will be 0 for the first discarded command, but
+                * may not be 0 for subsequent ones, e.g. if the original
+                * command was ":g/xx/@a|s/b/c/", then when we discard the
+                * command pushed on the stack by the @a, we have to resume
+                * the global command which included the substitute command.
+                */
+               if (ecp->clen != 0)
+                       return (0);
+
+               /*
+                * If it's an @, global or v command, we may need to continue
+                * the command on a different line.
+                */
+               if (FL_ISSET(ecp->agv_flags, AGV_ALL)) {
+                       /* Discard any exhausted ranges. */
+                       while ((rp = ecp->rq.cqh_first) != (void *)&ecp->rq)
+                               if (rp->start > rp->stop) {
+                                       CIRCLEQ_REMOVE(&ecp->rq, rp, q);
+                                       free(rp);
+                               } else
+                                       break;
+
+                       /* If there's another range, continue with it. */
+                       if (rp != (void *)&ecp->rq)
+                               break;
+
+                       /* If it's a global/v command, fix up the last line. */
+                       if (FL_ISSET(ecp->agv_flags,
+                           AGV_GLOBAL | AGV_V) && ecp->range_lno != OOBLNO) {
+                               if (db_exist(sp, ecp->range_lno))
+                                       sp->lno = ecp->range_lno;
+                               else {
+                                       if (db_last(sp, &sp->lno))
+                                               return (1);
+                                       if (sp->lno == 0)
+                                               sp->lno = 1;
+                               }
+                       }
+                       free(ecp->o_cp);
+               }
+
+               /* Discard the EXCMD. */
+               LIST_REMOVE(ecp, q);
+               free(ecp);
+       }
+
+       /*
+        * We only get here if it's an active @, global or v command.  Set
+        * the current line number, and get a new copy of the command for
+        * the parser.  Note, the original pointer almost certainly moved,
+        * so we have play games.
+        */
+       ecp->cp = ecp->o_cp;
+       MEMCPYW(ecp->cp, ecp->cp + ecp->o_clen, ecp->o_clen);
+       ecp->clen = ecp->o_clen;
+       ecp->range_lno = sp->lno = rp->start++;
+
+       if (FL_ISSET(ecp->agv_flags, AGV_GLOBAL | AGV_V))
+               F_SET(sp, SC_EX_GLOBAL);
+       return (0);
+}
+
+/*
+ * ex_discard --
+ *     Discard any pending ex commands.
+ */
+static int
+ex_discard(SCR *sp)
+{
+       WIN *wp;
+       EXCMD *ecp;
+       RANGE *rp;
+
+       /*
+        * We know the first command can't be an AGV command, so we don't
+        * process it specially.  We do, however, nail the command itself.
+        */
+       for (wp = sp->wp; (ecp = wp->ecq.lh_first) != &wp->excmd;) {
+               if (FL_ISSET(ecp->agv_flags, AGV_ALL)) {
+                       while ((rp = ecp->rq.cqh_first) != (void *)&ecp->rq) {
+                               CIRCLEQ_REMOVE(&ecp->rq, rp, q);
+                               free(rp);
+                       }
+                       free(ecp->o_cp);
+               }
+               LIST_REMOVE(ecp, q);
+               free(ecp);
+       }
+       wp->ecq.lh_first->clen = 0;
+       return (0);
+}
+
+/*
+ * ex_unknown --
+ *     Display an unknown command name.
+ */
+static void
+ex_unknown(SCR *sp, CHAR_T *cmd, size_t len)
+{
+       size_t blen;
+       CHAR_T *bp;
+
+       GET_SPACE_GOTOW(sp, bp, blen, len + 1);
+       bp[len] = '\0';
+       MEMCPYW(bp, cmd, len);
+       msgq_wstr(sp, M_ERR, bp, "098|The %s command is unknown");
+       FREE_SPACEW(sp, bp, blen);
+
+alloc_err:
+       return;
+}
+
+/*
+ * ex_is_abbrev -
+ *     The vi text input routine needs to know if ex thinks this is an
+ *     [un]abbreviate command, so it can turn off abbreviations.  See
+ *     the usual ranting in the vi/v_txt_ev.c:txt_abbrev() routine.
+ *
+ * PUBLIC: int ex_is_abbrev __P((SCR *, CHAR_T *, size_t));
+ */
+int
+ex_is_abbrev(SCR *sp, CHAR_T *name, size_t len)
+{
+       EXCMDLIST const *cp;
+
+       return ((cp = ex_comm_search(sp, name, len)) != NULL &&
+           (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
+}
+
+/*
+ * ex_is_unmap -
+ *     The vi text input routine needs to know if ex thinks this is an
+ *     unmap command, so it can turn off input mapping.  See the usual
+ *     ranting in the vi/v_txt_ev.c:txt_unmap() routine.
+ *
+ * PUBLIC: int ex_is_unmap __P((SCR *, CHAR_T *, size_t));
+ */
+int
+ex_is_unmap(SCR *sp, CHAR_T *name, size_t len)
+{
+       EXCMDLIST const *cp;
+
+       /*
+        * The command the vi input routines are really interested in
+        * is "unmap!", not just unmap.
+        */
+       if (name[len - 1] != '!')
+               return (0);
+       --len;
+       return ((cp = ex_comm_search(sp, name, len)) != NULL &&
+           cp == &cmds[C_UNMAP]);
+}
+
+/*
+ * ex_comm_search --
+ *     Search for a command name.
+ */
+static EXCMDLIST const *
+ex_comm_search(SCR *sp, CHAR_T *name, size_t len)
+{
+       EXCMDLIST const *cp;
+
+       for (cp = cmds; cp->name != NULL; ++cp) {
+               if (cp->name[0] > name[0])
+                       return (NULL);
+               if (cp->name[0] != name[0])
+                       continue;
+               if (!MEMCMP(name, cp->name, len))
+                       return (cp);
+       }
+       return (NULL);
+}
+
+/*
+ * ex_badaddr --
+ *     Display a bad address message.
+ *
+ * PUBLIC: void ex_badaddr
+ * PUBLIC:    __P((SCR *, EXCMDLIST const *, enum badaddr, enum nresult));
+ */
+void
+ex_badaddr(SCR *sp, const EXCMDLIST *cp, enum badaddr ba, enum nresult nret)
+{
+       db_recno_t lno;
+
+       switch (nret) {
+       case NUM_OK:
+               break;
+       case NUM_ERR:
+               msgq(sp, M_SYSERR, NULL);
+               return;
+       case NUM_OVER:
+               msgq(sp, M_ERR, "099|Address value overflow");
+               return;
+       case NUM_UNDER:
+               msgq(sp, M_ERR, "100|Address value underflow");
+               return;
+       }
+
+       /*
+        * When encountering an address error, tell the user if there's no
+        * underlying file, that's the real problem.
+        */
+       if (sp->ep == NULL) {
+               ex_wemsg(sp, cp ? cp->name : NULL, EXM_NOFILEYET);
+               return;
+       }
+
+       switch (ba) {
+       case A_COMBO:
+               msgq(sp, M_ERR, "101|Illegal address combination");
+               break;
+       case A_EOF:
+               if (db_last(sp, &lno))
+                       return;
+               if (lno != 0) {
+                       msgq(sp, M_ERR,
+                           "102|Illegal address: only %lu lines in the file",
+                           (unsigned long)lno);
+                       break;
+               }
+               /* FALLTHROUGH */
+       case A_EMPTY:
+               msgq(sp, M_ERR, "103|Illegal address: the file is empty");
+               break;
+       case A_NOTSET:
+               abort();
+               /* NOTREACHED */
+       case A_ZERO:
+               msgq_wstr(sp, M_ERR, cp->name,
+                   "104|The %s command doesn't permit an address of 0");
+               break;
+       }
+       return;
+}
+
+#if defined(DEBUG) && defined(COMLOG)
+/*
+ * ex_comlog --
+ *     Log ex commands.
+ */
+static void
+ex_comlog(sp, ecp)
+       SCR *sp;
+       EXCMD *ecp;
+{
+       vtrace(sp, "ecmd: %s", ecp->cmd->name);
+       if (ecp->addrcnt > 0) {
+               vtrace(sp, " a1 %d", ecp->addr1.lno);
+               if (ecp->addrcnt > 1)
+                       vtrace(sp, " a2: %d", ecp->addr2.lno);
+       }
+       if (ecp->lineno)
+               vtrace(sp, " line %d", ecp->lineno);
+       if (ecp->flags)
+               vtrace(sp, " flags 0x%x", ecp->flags);
+       if (F_ISSET(&exc, E_BUFFER))
+               vtrace(sp, " buffer "WC, ecp->buffer);
+       if (ecp->argc)
+               for (cnt = 0; cnt < ecp->argc; ++cnt)
+                       vtrace(sp, " arg %d: {%s}", cnt, ecp->argv[cnt]->bp);
+       vtrace(sp, "\n");
+}
+#endif
diff --git a/dist/nvi/ex/ex.h b/dist/nvi/ex/ex.h
new file mode 100644 (file)
index 0000000..842c99b
--- /dev/null
@@ -0,0 +1,235 @@
+/*     $NetBSD: ex.h,v 1.4 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: ex.h,v 10.30 2004/03/16 14:11:33 skimo Exp (Berkeley) Date: 2004/03/16 14:11:33
+ */
+
+#define        PROMPTCHAR      ':'             /* Prompt using a colon. */
+
+typedef struct _excmdlist {            /* Ex command table structure. */
+       const CHAR_T *name;             /* Command name, underlying function. */
+       int (*fn) __P((SCR *, EXCMD *));
+
+#define        E_ADDR1         0x00000001      /* One address. */
+#define        E_ADDR2         0x00000002      /* Two addresses. */
+#define        E_ADDR2_ALL     0x00000004      /* Zero/two addresses; zero == all. */
+#define        E_ADDR2_NONE    0x00000008      /* Zero/two addresses; zero == none. */
+#define        E_ADDR_ZERO     0x00000010      /* 0 is a legal addr1. */
+#define        E_ADDR_ZERODEF  0x00000020      /* 0 is default addr1 of empty files. */
+#define        E_AUTOPRINT     0x00000040      /* Command always sets autoprint. */
+#define        E_CLRFLAG       0x00000080      /* Clear the print (#, l, p) flags. */
+#define        E_NEWSCREEN     0x00000100      /* Create a new screen. */
+#define        E_SECURE        0x00000200      /* Permission denied if O_SECURE set. */
+#define        E_VIONLY        0x00000400      /* Meaningful only in vi. */
+#define        __INUSE1        0xfffff800      /* Same name space as EX_PRIVATE. */
+       u_int16_t flags;
+
+       const char *syntax;             /* Syntax script. */
+       const char *usage;              /* Usage line. */
+       const char *help;               /* Help line. */
+} EXCMDLIST;
+
+#define        MAXCMDNAMELEN   12              /* Longest command name. */
+extern EXCMDLIST const cmds[];         /* Table of ex commands. */
+
+/*
+ * !!!
+ * QUOTING NOTE:
+ *
+ * Historically, .exrc files and EXINIT variables could only use ^V as an
+ * escape character, neither ^Q or a user specified character worked.  We
+ * enforce that here, just in case someone depends on it.
+ */
+#define        IS_ESCAPE(sp, cmdp, ch)                                         \
+       (F_ISSET(cmdp, E_VLITONLY) ?                                    \
+           (ch) == CH_LITERAL : KEY_VAL(sp, ch) == K_VLNEXT)
+
+/*
+ * File state must be checked for each command -- any ex command may be entered
+ * at any time, and most of them won't work well if a file hasn't yet been read
+ * in.  Historic vi generally took the easy way out and dropped core.
+ */
+#define        NEEDFILE(sp, cmdp) {                                            \
+       if ((sp)->ep == NULL) {                                         \
+               ex_wemsg(sp, (cmdp)->cmd->name, EXM_NOFILEYET);         \
+               return (1);                                             \
+       }                                                               \
+}
+
+/* Range structures for global and @ commands. */
+typedef struct _range RANGE;
+struct _range {                                /* Global command range. */
+       CIRCLEQ_ENTRY(_range) q;        /* Linked list of ranges. */
+       db_recno_t start, stop;         /* Start/stop of the range. */
+};
+
+/* Ex command structure. */
+struct _excmd {
+       LIST_ENTRY(_excmd) q;           /* Linked list of commands. */
+
+       char     *if_name;              /* Associated file. */
+       db_recno_t        if_lno;               /* Associated line number. */
+
+       /* Clear the structure for the ex parser. */
+#define        CLEAR_EX_PARSER(cmdp)                                           \
+       memset(&((cmdp)->cp), 0, ((char *)&(cmdp)->flags -              \
+           (char *)&((cmdp)->cp)) + sizeof((cmdp)->flags))
+
+       CHAR_T   *cp;                   /* Current command text. */
+       size_t    clen;                 /* Current command length. */
+
+       CHAR_T   *save_cmd;             /* Remaining command. */
+       size_t    save_cmdlen;          /* Remaining command length. */
+
+       EXCMDLIST const *cmd;           /* Command: entry in command table. */
+       EXCMDLIST rcmd;                 /* Command: table entry/replacement. */
+
+       CIRCLEQ_HEAD(_rh, _range) rq;   /* @/global range: linked list. */
+       db_recno_t   range_lno;         /* @/global range: set line number. */
+       CHAR_T   *o_cp;                 /* Original @/global command. */
+       size_t    o_clen;               /* Original @/global command length. */
+#define        AGV_AT          0x01            /* @ buffer execution. */
+#define        AGV_AT_NORANGE  0x02            /* @ buffer execution without range. */
+#define        AGV_GLOBAL      0x04            /* global command. */
+#define        AGV_V           0x08            /* v command. */
+#define        AGV_ALL         (AGV_AT | AGV_AT_NORANGE | AGV_GLOBAL | AGV_V)
+       u_int8_t  agv_flags;
+
+       /* Clear the structure before each ex command. */
+#define        CLEAR_EX_CMD(cmdp) {                                            \
+       u_int32_t L__f = F_ISSET(cmdp, E_PRESERVE);                     \
+       memset(&((cmdp)->buffer), 0, ((char *)&(cmdp)->flags -          \
+           (char *)&((cmdp)->buffer)) + sizeof((cmdp)->flags));        \
+       F_SET(cmdp, L__f);                                              \
+}
+
+       ARG_CHAR_T        buffer;               /* Command: named buffer. */
+       db_recno_t        lineno;               /* Command: line number. */
+       long      count;                /* Command: signed count. */
+       long      flagoff;              /* Command: signed flag offset. */
+       int       addrcnt;              /* Command: addresses (0, 1 or 2). */
+       MARK      addr1;                /* Command: 1st address. */
+       MARK      addr2;                /* Command: 2nd address. */
+       ARGS    **argv;                 /* Command: array of arguments. */
+       int       argc;                 /* Command: count of arguments. */
+
+#define        E_C_BUFFER      0x00001         /* Buffer name specified. */
+#define        E_C_CARAT       0x00002         /*  ^ flag. */
+#define        E_C_COUNT       0x00004         /* Count specified. */
+#define        E_C_COUNT_NEG   0x00008         /* Count was signed negative. */
+#define        E_C_COUNT_POS   0x00010         /* Count was signed positive. */
+#define        E_C_DASH        0x00020         /*  - flag. */
+#define        E_C_DOT         0x00040         /*  . flag. */
+#define        E_C_EQUAL       0x00080         /*  = flag. */
+#define        E_C_FORCE       0x00100         /*  ! flag. */
+#define        E_C_HASH        0x00200         /*  # flag. */
+#define        E_C_LIST        0x00400         /*  l flag. */
+#define        E_C_PLUS        0x00800         /*  + flag. */
+#define        E_C_PRINT       0x01000         /*  p flag. */
+       u_int16_t iflags;               /* User input information. */
+
+#define        __INUSE2        0x000007ff      /* Same name space as EXCMDLIST. */
+#define        E_BLIGNORE      0x00000800      /* Ignore blank lines. */
+#define        E_NAMEDISCARD   0x00001000      /* Free/discard the name. */
+#define        E_NOAUTO        0x00002000      /* Don't do autoprint output. */
+#define        E_NOPRDEF       0x00004000      /* Don't print as default. */
+#define        E_NRSEP         0x00008000      /* Need to line adjust ex output. */
+#define        E_OPTNUM        0x00010000      /* Number edit option affected. */
+#define        E_VLITONLY      0x00020000      /* Use ^V quoting only. */
+#define        E_PRESERVE      0x0003f800      /* Bits to preserve across commands. */
+
+#define        E_ABSMARK       0x00040000      /* Set the absolute mark. */
+#define        E_ADDR_DEF      0x00080000      /* Default addresses used. */
+#define        E_DELTA         0x00100000      /* Search address with delta. */
+#define        E_MODIFY        0x00200000      /* File name expansion modified arg. */
+#define        E_MOVETOEND     0x00400000      /* Move to the end of the file first. */
+#define        E_NEWLINE       0x00800000      /* Found ending <newline>. */
+#define        E_SEARCH_WMSG   0x01000000      /* Display search-wrapped message. */
+#define        E_USELASTCMD    0x02000000      /* Use the last command. */
+#define        E_VISEARCH      0x04000000      /* It's really a vi search command. */
+#ifdef GTAGS
+#define        E_REFERENCE     0x08000000      /* locate function references */
+#endif
+       u_int32_t flags;                /* Current flags. */
+};
+
+/* Ex private, per-screen memory. */
+typedef struct _ex_private {
+       CIRCLEQ_HEAD(_tqh, _tagq) tq;   /* Tag queue. */
+       TAILQ_HEAD(_tagfh, _tagf) tagfq;/* Tag file list. */
+       LIST_HEAD(_csch, _csc) cscq;    /* Cscope connection list. */
+       CHAR_T  *tag_last;              /* Saved last tag string. */
+
+       CHAR_T  *lastbcomm;             /* Last bang command. */
+
+       ARGS   **args;                  /* Command: argument list. */
+       int      argscnt;               /* Command: argument list count. */
+       int      argsoff;               /* Command: offset into arguments. */
+
+       u_int32_t fdef;                 /* Saved E_C_* default command flags. */
+
+       char    *ibp;                   /* File line input buffer. */
+       size_t   ibp_len;               /* File line input buffer length. */
+       CONVWIN  ibcw;                  /* File line input conversion buffer. */
+
+       /*
+        * Buffers for the ex output.  The screen/vi support doesn't do any
+        * character buffering of any kind.  We do it here so that we're not
+        * calling the screen output routines on every character.
+        *
+        * XXX
+        * Change to grow dynamically.
+        */
+       char     obp[1024];             /* Ex output buffer. */
+       size_t   obp_len;               /* Ex output buffer length. */
+
+#define        EXP_CSCINIT     0x01            /* Cscope initialized. */
+       u_int8_t flags;
+} EX_PRIVATE;
+#define        EXP(sp) ((EX_PRIVATE *)((sp)->ex_private))
+
+/*
+ * Filter actions:
+ *
+ *     FILTER_BANG     !:      filter text through the utility.
+ *     FILTER_RBANG    !:      read from the utility (without stdin).
+ *     FILTER_READ     read:   read from the utility (with stdin).
+ *     FILTER_WRITE    write:  write to the utility, display its output.
+ */
+enum filtertype { FILTER_BANG, FILTER_RBANG, FILTER_READ, FILTER_WRITE };
+
+/* Ex common error messages. */
+typedef enum {
+       EXM_EMPTYBUF,                   /* Empty buffer. */
+       EXM_FILECOUNT,                  /* Too many file names. */
+       EXM_LOCKED,                     /* Another thread is active. */
+       EXM_NOCANON,                    /* No terminal interface. */
+       EXM_NOCANON_F,                  /* EXM_NOCANO: filter version. */
+       EXM_NOFILEYET,                  /* Illegal until a file read in. */
+       EXM_NOPREVBUF,                  /* No previous buffer specified. */
+       EXM_NOPREVRE,                   /* No previous RE specified. */
+       EXM_NOSUSPEND,                  /* No suspension. */
+       EXM_SECURE,                     /* Illegal if secure edit option set. */
+       EXM_SECURE_F,                   /* EXM_SECURE: filter version */
+       EXM_USAGE                       /* Standard usage message. */
+} exm_t;
+
+/* Ex address error types. */
+enum badaddr { A_COMBO, A_EMPTY, A_EOF, A_NOTSET, A_ZERO };
+
+/* Ex common tag error messages. */                                         
+typedef enum {
+       TAG_BADLNO,             /* Tag line doesn't exist. */
+       TAG_EMPTY,              /* Tags stack is empty. */
+       TAG_SEARCH              /* Tags search pattern wasn't found. */
+} tagmsg_t;
+
+#include "ex_def.h"
+#include "extern.h"
diff --git a/dist/nvi/ex/ex_abbrev.c b/dist/nvi/ex/ex_abbrev.c
new file mode 100644 (file)
index 0000000..0fe90ef
--- /dev/null
@@ -0,0 +1,115 @@
+/*     $NetBSD: ex_abbrev.c,v 1.2 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_abbrev.c,v 10.10 2001/12/16 18:18:54 skimo Exp (Berkeley) Date: 2001/12/16 18:18:54";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_abbr -- :abbreviate [key replacement]
+ *     Create an abbreviation or display abbreviations.
+ *
+ * PUBLIC: int ex_abbr __P((SCR *, EXCMD *));
+ */
+int
+ex_abbr(SCR *sp, EXCMD *cmdp)
+{
+       CHAR_T *p;
+       size_t len;
+
+       switch (cmdp->argc) {
+       case 0:
+               if (seq_dump(sp, SEQ_ABBREV, 0) == 0)
+                       msgq(sp, M_INFO, "105|No abbreviations to display");
+               return (0);
+       case 2:
+               break;
+       default:
+               abort();
+       }
+
+       /*
+        * Check for illegal characters.
+        *
+        * !!!
+        * Another fun one, historically.  See vi/v_ntext.c:txt_abbrev() for
+        * details.  The bottom line is that all abbreviations have to end
+        * with a "word" character, because it's the transition from word to
+        * non-word characters that triggers the test for an abbreviation.  In
+        * addition, because of the way the test is done, there can't be any
+        * transitions from word to non-word character (or vice-versa) other
+        * than between the next-to-last and last characters of the string,
+        * and there can't be any <blank> characters.  Warn the user.
+        */
+       if (!inword(cmdp->argv[0]->bp[cmdp->argv[0]->len - 1])) {
+               msgq(sp, M_ERR,
+                   "106|Abbreviations must end with a \"word\" character");
+                       return (1);
+       }
+       for (p = cmdp->argv[0]->bp; *p != '\0'; ++p)
+               if (ISBLANK((UCHAR_T)p[0])) {
+                       msgq(sp, M_ERR,
+                           "107|Abbreviations may not contain tabs or spaces");
+                       return (1);
+               }
+       if (cmdp->argv[0]->len > 2)
+               for (p = cmdp->argv[0]->bp,
+                   len = cmdp->argv[0]->len - 2; len; --len, ++p)
+                       if (inword(p[0]) != inword(p[1])) {
+                               msgq(sp, M_ERR,
+"108|Abbreviations may not mix word/non-word characters, except at the end");
+                               return (1);
+                       }
+
+       if (seq_set(sp, NULL, 0, cmdp->argv[0]->bp, cmdp->argv[0]->len,
+           cmdp->argv[1]->bp, cmdp->argv[1]->len, SEQ_ABBREV, SEQ_USERDEF))
+               return (1);
+
+       F_SET(sp->gp, G_ABBREV);
+       return (0);
+}
+
+/*
+ * ex_unabbr -- :unabbreviate key
+ *      Delete an abbreviation.
+ *
+ * PUBLIC: int ex_unabbr __P((SCR *, EXCMD *));
+ */
+int
+ex_unabbr(SCR *sp, EXCMD *cmdp)
+{
+       ARGS *ap;
+
+       ap = cmdp->argv[0];
+       if (!F_ISSET(sp->gp, G_ABBREV) ||
+           seq_delete(sp, ap->bp, ap->len, SEQ_ABBREV)) {
+               msgq_wstr(sp, M_ERR, ap->bp,
+                   "109|\"%s\" is not an abbreviation");
+               return (1);
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_append.c b/dist/nvi/ex/ex_append.c
new file mode 100644 (file)
index 0000000..68b4daf
--- /dev/null
@@ -0,0 +1,270 @@
+/*     $NetBSD: ex_append.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_append.c,v 10.34 2001/06/25 15:19:14 skimo Exp (Berkeley) Date: 2001/06/25 15:19:14";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+enum which {APPEND, CHANGE, INSERT};
+
+static int ex_aci __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_append -- :[line] a[ppend][!]
+ *     Append one or more lines of new text after the specified line,
+ *     or the current line if no address is specified.
+ *
+ * PUBLIC: int ex_append __P((SCR *, EXCMD *));
+ */
+int
+ex_append(SCR *sp, EXCMD *cmdp)
+{
+       return (ex_aci(sp, cmdp, APPEND));
+}
+
+/*
+ * ex_change -- :[line[,line]] c[hange][!] [count]
+ *     Change one or more lines to the input text.
+ *
+ * PUBLIC: int ex_change __P((SCR *, EXCMD *));
+ */
+int
+ex_change(SCR *sp, EXCMD *cmdp)
+{
+       return (ex_aci(sp, cmdp, CHANGE));
+}
+
+/*
+ * ex_insert -- :[line] i[nsert][!]
+ *     Insert one or more lines of new text before the specified line,
+ *     or the current line if no address is specified.
+ *
+ * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
+ */
+int
+ex_insert(SCR *sp, EXCMD *cmdp)
+{
+       return (ex_aci(sp, cmdp, INSERT));
+}
+
+/*
+ * ex_aci --
+ *     Append, change, insert in ex.
+ */
+static int
+ex_aci(SCR *sp, EXCMD *cmdp, enum which cmd)
+{
+       CHAR_T *p, *t;
+       GS *gp;
+       TEXT *tp;
+       TEXTH tiq;
+       db_recno_t cnt, lno;
+       size_t len;
+       u_int32_t flags;
+       int need_newline;
+
+       gp = sp->gp;
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * If doing a change, replace lines for as long as possible.  Then,
+        * append more lines or delete remaining lines.  Changes to an empty
+        * file are appends, inserts are the same as appends to the previous
+        * line.
+        *
+        * !!!
+        * Set the address to which we'll append.  We set sp->lno to this
+        * address as well so that autoindent works correctly when get text
+        * from the user.
+        */
+       lno = cmdp->addr1.lno;
+       sp->lno = lno;
+       if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
+               --lno;
+
+       /*
+        * !!!
+        * If the file isn't empty, cut changes into the unnamed buffer.
+        */
+       if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
+           (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
+           del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
+               return (1);
+
+       /*
+        * !!!
+        * Anything that was left after the command separator becomes part
+        * of the inserted text.  Apparently, it was common usage to enter:
+        *
+        *      :g/pattern/append|stuff1
+        *
+        * and append the line of text "stuff1" to the lines containing the
+        * pattern.  It was also historically legal to enter:
+        *
+        *      :append|stuff1
+        *      stuff2
+        *      .
+        *
+        * and the text on the ex command line would be appended as well as
+        * the text inserted after it.  There was an historic bug however,
+        * that the user had to enter *two* terminating lines (the '.' lines)
+        * to terminate text input mode, in this case.  This whole thing
+        * could be taken too far, however.  Entering:
+        *
+        *      :append|stuff1\
+        *      stuff2
+        *      stuff3
+        *      .
+        *
+        * i.e. mixing and matching the forms confused the historic vi, and,
+        * not only did it take two terminating lines to terminate text input
+        * mode, but the trailing backslashes were retained on the input.  We
+        * match historic practice except that we discard the backslashes.
+        *
+        * Input lines specified on the ex command line lines are separated by
+        * <newline>s.  If there is a trailing delimiter an empty line was
+        * inserted.  There may also be a leading delimiter, which is ignored
+        * unless it's also a trailing delimiter.  It is possible to encounter
+        * a termination line, i.e. a single '.', in a global command, but not
+        * necessary if the text insert command was the last of the global
+        * commands.
+        */
+       if (cmdp->save_cmdlen != 0) {
+               for (p = cmdp->save_cmd,
+                   len = cmdp->save_cmdlen; len > 0; p = t) {
+                       for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
+                       if (t != p || len == 0) {
+                               if (F_ISSET(sp, SC_EX_GLOBAL) &&
+                                   t - p == 1 && p[0] == '.') {
+                                       ++t;
+                                       if (len > 0)
+                                               --len;
+                                       break;
+                               }
+                               if (db_append(sp, 1, lno++, p, t - p))
+                                       return (1);
+                       }
+                       if (len != 0) {
+                               ++t;
+                               if (--len == 0 &&
+                                   db_append(sp, 1, lno++, NULL, 0))
+                                       return (1);
+                       }
+               }
+               /*
+                * If there's any remaining text, we're in a global, and
+                * there's more command to parse.
+                *
+                * !!!
+                * We depend on the fact that non-global commands will eat the
+                * rest of the command line as text input, and before getting
+                * any text input from the user.  Otherwise, we'd have to save
+                * off the command text before or during the call to the text
+                * input function below.
+                */
+               if (len != 0)
+                       cmdp->save_cmd = t;
+               cmdp->save_cmdlen = len;
+       }
+
+       if (F_ISSET(sp, SC_EX_GLOBAL)) {
+               if ((sp->lno = lno) == 0 && db_exist(sp, 1))
+                       sp->lno = 1;
+               return (0);
+       }
+
+       /*
+        * If not in a global command, read from the terminal.
+        *
+        * If this code is called by vi, we want to reset the terminal and use
+        * ex's line get routine.  It actually works fine if we use vi's get
+        * routine, but it doesn't look as nice.  Maybe if we had a separate
+        * window or something, but getting a line at a time looks awkward.
+        * However, depending on the screen that we're using, that may not
+        * be possible.
+        */
+       if (F_ISSET(sp, SC_VI)) {
+               if (gp->scr_screen(sp, SC_EX)) {
+                       ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON);
+                       return (1);
+               }
+
+               /* If we're still in the vi screen, move out explicitly. */
+               need_newline = !F_ISSET(sp, SC_SCR_EXWROTE);
+               F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
+               if (need_newline)
+                       (void)ex_puts(sp, "\n");
+
+               /*
+                * !!!
+                * Users of historical versions of vi sometimes get confused
+                * when they enter append mode, and can't seem to get out of
+                * it.  Give them an informational message.
+                */
+               (void)ex_puts(sp,
+                   msg_cat(sp, "273|Entering ex input mode.", NULL));
+               (void)ex_puts(sp, "\n");
+               (void)ex_fflush(sp);
+       }
+
+       /*
+        * Set input flags; the ! flag turns off autoindent for append,
+        * change and insert.
+        */
+       LF_INIT(TXT_DOTTERM | TXT_NUMBER);
+       if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT))
+               LF_SET(TXT_AUTOINDENT);
+       if (O_ISSET(sp, O_BEAUTIFY))
+               LF_SET(TXT_BEAUTIFY);
+
+       /*
+        * This code can't use the common screen TEXTH structure (sp->tiq),
+        * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
+        * as we are only halfway through the text when the append code fires.
+        * Use a local structure instead.  (The ex code would have to use a
+        * local structure except that we're guaranteed to finish remaining
+        * characters in the common TEXTH structure when they were inserted
+        * into the file, above.)
+        */
+       memset(&tiq, 0, sizeof(TEXTH));
+       CIRCLEQ_INIT(&tiq);
+
+       if (ex_txt(sp, &tiq, 0, flags))
+               return (1);
+
+       for (cnt = 0, tp = tiq.cqh_first;
+           tp != (TEXT *)(void *)&tiq; ++cnt, tp = tp->q.cqe_next)
+               if (db_append(sp, 1, lno++, tp->lb, tp->len))
+                       return (1);
+
+       /*
+        * Set sp->lno to the final line number value (correcting for a
+        * possible 0 value) as that's historically correct for the final
+        * line value, whether or not the user entered any text.
+        */
+       if ((sp->lno = lno) == 0 && db_exist(sp, 1))
+               sp->lno = 1;
+
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_args.c b/dist/nvi/ex/ex_args.c
new file mode 100644 (file)
index 0000000..ae67906
--- /dev/null
@@ -0,0 +1,334 @@
+/*     $NetBSD: ex_args.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_args.c,v 10.18 2001/06/25 15:19:14 skimo Exp (Berkeley) Date: 2001/06/25 15:19:14";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+static int ex_N_next __P((SCR *, EXCMD *));
+
+/*
+ * ex_next -- :next [+cmd] [files]
+ *     Edit the next file, optionally setting the list of files.
+ *
+ * !!!
+ * The :next command behaved differently from the :rewind command in
+ * historic vi.  See nvi/docs/autowrite for details, but the basic
+ * idea was that it ignored the force flag if the autowrite flag was
+ * set.  This implementation handles them all identically.
+ *
+ * PUBLIC: int ex_next __P((SCR *, EXCMD *));
+ */
+int
+ex_next(SCR *sp, EXCMD *cmdp)
+{
+       ARGS **argv;
+       FREF *frp;
+       int noargs;
+       char **ap;
+       const CHAR_T *wp;
+       size_t wlen;
+       const char *np;
+       size_t nlen;
+
+       /* Check for file to move to. */
+       if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) {
+               msgq(sp, M_ERR, "111|No more files to edit");
+               return (1);
+       }
+
+       if (F_ISSET(cmdp, E_NEWSCREEN)) {
+               /* By default, edit the next file in the old argument list. */
+               if (cmdp->argc == 0) {
+                       CHAR2INT(sp, sp->cargv[1], strlen(sp->cargv[1]) + 1,
+                                          wp, wlen);
+                       if (argv_exp0(sp, cmdp, wp, wlen - 1))
+                               return (1);
+                       return (ex_edit(sp, cmdp));
+               }
+               return (ex_N_next(sp, cmdp));
+       }
+
+       /* Check modification. */
+       if (file_m1(sp,
+           FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
+               return (1);
+
+       /* Any arguments are a replacement file list. */
+       if (cmdp->argc) {
+               /* Free the current list. */
+               if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
+                       for (ap = sp->argv; *ap != NULL; ++ap)
+                               free(*ap);
+                       free(sp->argv);
+               }
+               F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER);
+               sp->cargv = NULL;
+
+               /* Create a new list. */
+               CALLOC_RET(sp,
+                   sp->argv, char **, cmdp->argc + 1, sizeof(char *));
+               for (ap = sp->argv,
+                   argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv) {
+                       INT2CHAR(sp, argv[0]->bp, argv[0]->len, np, nlen);
+                       if ((*ap = v_strdup(sp, np, nlen)) == NULL)
+                               return (1);
+               }
+               *ap = NULL;
+
+               /* Switch to the first file. */
+               sp->cargv = sp->argv;
+               if ((frp = file_add(sp, *sp->cargv)) == NULL)
+                       return (1);
+               noargs = 0;
+
+               /* Display a file count with the welcome message. */
+               F_SET(sp, SC_STATUS_CNT);
+       } else {
+               if ((frp = file_add(sp, sp->cargv[1])) == NULL)
+                       return (1);
+               if (F_ISSET(sp, SC_ARGRECOVER))
+                       F_SET(frp, FR_RECOVER);
+               noargs = 1;
+       }
+
+       if (file_init(sp, frp, NULL, FS_SETALT |
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+               return (1);
+       if (noargs)
+               ++sp->cargv;
+
+       F_SET(sp, SC_FSWITCH);
+       return (0);
+}
+
+/*
+ * ex_N_next --
+ *     New screen version of ex_next.
+ */
+static int
+ex_N_next(SCR *sp, EXCMD *cmdp)
+{
+       SCR *new;
+       FREF *frp;
+       const char *np;
+       size_t nlen;
+
+       /* Get a new screen. */
+       if (screen_init(sp->gp, sp, &new))
+               return (1);
+       if (vs_split(sp, new, 0)) {
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* Get a backing file. */
+       INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, np, nlen);
+       if ((frp = file_add(new, np)) == NULL ||
+           file_init(new, frp, NULL,
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
+               (void)vs_discard(new, NULL);
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* The arguments are a replacement file list. */
+       new->cargv = new->argv = ex_buildargv(sp, cmdp, NULL);
+
+       /* Display a file count with the welcome message. */
+       F_SET(new, SC_STATUS_CNT);
+
+       /* Set up the switch. */
+       sp->nextdisp = new;
+       F_SET(sp, SC_SSWITCH);
+
+       return (0);
+}
+
+/*
+ * ex_prev -- :prev
+ *     Edit the previous file.
+ *
+ * PUBLIC: int ex_prev __P((SCR *, EXCMD *));
+ */
+int
+ex_prev(SCR *sp, EXCMD *cmdp)
+{
+       FREF *frp;
+       size_t wlen;
+       const CHAR_T *wp;
+
+       if (sp->cargv == sp->argv) {
+               msgq(sp, M_ERR, "112|No previous files to edit");
+               return (1);
+       }
+
+       if (F_ISSET(cmdp, E_NEWSCREEN)) {
+               CHAR2INT(sp, sp->cargv[-1], strlen(sp->cargv[-1]) + 1,
+                                  wp, wlen);
+               if (argv_exp0(sp, cmdp, wp, wlen - 1))
+                       return (1);
+               return (ex_edit(sp, cmdp));
+       }
+
+       if (file_m1(sp,
+           FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
+               return (1);
+
+       if ((frp = file_add(sp, sp->cargv[-1])) == NULL)
+               return (1);
+
+       if (file_init(sp, frp, NULL, FS_SETALT |
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+               return (1);
+       --sp->cargv;
+
+       F_SET(sp, SC_FSWITCH);
+       return (0);
+}
+
+/*
+ * ex_rew -- :rew
+ *     Re-edit the list of files.
+ *
+ * !!!
+ * Historic practice was that all files would start editing at the beginning
+ * of the file.  We don't get this right because we may have multiple screens
+ * and we can't clear the FR_CURSORSET bit for a single screen.  I don't see
+ * anyone noticing, but if they do, we'll have to put information into the SCR
+ * structure so we can keep track of it.
+ *
+ * PUBLIC: int ex_rew __P((SCR *, EXCMD *));
+ */
+int
+ex_rew(SCR *sp, EXCMD *cmdp)
+{
+       FREF *frp;
+
+       /*
+        * !!!
+        * Historic practice -- you can rewind to the current file.
+        */
+       if (sp->argv == NULL) {
+               msgq(sp, M_ERR, "113|No previous files to rewind");
+               return (1);
+       }
+
+       if (file_m1(sp,
+           FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
+               return (1);
+
+       /* Switch to the first one. */
+       sp->cargv = sp->argv;
+       if ((frp = file_add(sp, *sp->cargv)) == NULL)
+               return (1);
+       if (file_init(sp, frp, NULL, FS_SETALT |
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+               return (1);
+
+       /* Switch and display a file count with the welcome message. */
+       F_SET(sp, SC_FSWITCH | SC_STATUS_CNT);
+
+       return (0);
+}
+
+/*
+ * ex_args -- :args
+ *     Display the list of files.
+ *
+ * PUBLIC: int ex_args __P((SCR *, EXCMD *));
+ */
+int
+ex_args(SCR *sp, EXCMD *cmdp)
+{
+       GS *gp;
+       int cnt, sep;
+       size_t col, len;
+       char **ap;
+
+       if (sp->argv == NULL) {
+               (void)msgq(sp, M_ERR, "114|No file list to display");
+               return (0);
+       }
+
+       gp = sp->gp;
+       col = len = sep = 0;
+       for (cnt = 1, ap = sp->argv; *ap != NULL; ++ap) {
+               col += len = strlen(*ap) + sep + (ap == sp->cargv ? 2 : 0);
+               if (col >= sp->cols - 1) {
+                       col = len;
+                       sep = 0;
+                       (void)ex_puts(sp, "\n");
+               } else if (cnt != 1) {
+                       sep = 1;
+                       (void)ex_puts(sp, " ");
+               }
+               ++cnt;
+
+               (void)ex_printf(sp, "%s%s%s", ap == sp->cargv ? "[" : "",
+                   *ap, ap == sp->cargv ? "]" : "");
+               if (INTERRUPTED(sp))
+                       break;
+       }
+       (void)ex_puts(sp, "\n");
+       return (0);
+}
+
+/*
+ * ex_buildargv --
+ *     Build a new file argument list.
+ *
+ * PUBLIC: char **ex_buildargv __P((SCR *, EXCMD *, char *));
+ */
+char **
+ex_buildargv(SCR *sp, EXCMD *cmdp, char *name)
+{
+       ARGS **argv;
+       int argc;
+       char **ap, **s_argv;
+       const char *np;
+       size_t nlen;
+
+       argc = cmdp == NULL ? 1 : cmdp->argc;
+       CALLOC(sp, s_argv, char **, argc + 1, sizeof(char *));
+       if ((ap = s_argv) == NULL)
+               return (NULL);
+
+       if (cmdp == NULL) {
+               if ((*ap = v_strdup(sp, name, strlen(name))) == NULL)
+                       return (NULL);
+               ++ap;
+       } else
+               for (argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv) {
+                       INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len, 
+                                np, nlen);
+                       if ((*ap = v_strdup(sp, np, nlen)) == NULL)
+                               return (NULL);
+               }
+       *ap = NULL;
+       return (s_argv);
+}
diff --git a/dist/nvi/ex/ex_argv.c b/dist/nvi/ex/ex_argv.c
new file mode 100644 (file)
index 0000000..344a142
--- /dev/null
@@ -0,0 +1,765 @@
+/*     $NetBSD: ex_argv.c,v 1.4 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_argv.c,v 10.39 2003/11/05 17:11:54 skimo Exp (Berkeley) Date: 2003/11/05 17:11:54";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+static int argv_alloc __P((SCR *, size_t));
+static int argv_comp __P((const void *, const void *));
+static int argv_fexp __P((SCR *, EXCMD *,
+       const CHAR_T *, size_t, CHAR_T *, size_t *, CHAR_T **, size_t *, int));
+static int argv_lexp __P((SCR *, EXCMD *, const char *));
+static int argv_sexp __P((SCR *, CHAR_T **, size_t *, size_t *));
+
+/*
+ * argv_init --
+ *     Build  a prototype arguments list.
+ *
+ * PUBLIC: int argv_init __P((SCR *, EXCMD *));
+ */
+int
+argv_init(SCR *sp, EXCMD *excp)
+{
+       EX_PRIVATE *exp;
+
+       exp = EXP(sp);
+       exp->argsoff = 0;
+       argv_alloc(sp, 1);
+
+       excp->argv = exp->args;
+       excp->argc = exp->argsoff;
+       return (0);
+}
+
+/*
+ * argv_exp0 --
+ *     Append a string to the argument list.
+ *
+ * PUBLIC: int argv_exp0 __P((SCR *, EXCMD *, CHAR_T *, size_t));
+ */
+int
+argv_exp0(SCR *sp, EXCMD *excp, const CHAR_T *cmd, size_t cmdlen)
+{
+       EX_PRIVATE *exp;
+
+       exp = EXP(sp);
+       argv_alloc(sp, cmdlen);
+       MEMCPY(exp->args[exp->argsoff]->bp, cmd, cmdlen);
+       exp->args[exp->argsoff]->bp[cmdlen] = '\0';
+       exp->args[exp->argsoff]->len = cmdlen;
+       ++exp->argsoff;
+       excp->argv = exp->args;
+       excp->argc = exp->argsoff;
+       return (0);
+}
+
+/*
+ * argv_exp1 --
+ *     Do file name expansion on a string, and append it to the
+ *     argument list.
+ *
+ * PUBLIC: int argv_exp1 __P((SCR *, EXCMD *, const CHAR_T *, size_t, int));
+ */
+int
+argv_exp1(SCR *sp, EXCMD *excp, const CHAR_T *cmd, size_t cmdlen, int is_bang)
+{
+       EX_PRIVATE *exp;
+       size_t blen, len;
+       CHAR_T *p, *t, *bp;
+
+       GET_SPACE_RETW(sp, bp, blen, 512);
+
+       len = 0;
+       exp = EXP(sp);
+       if (argv_fexp(sp, excp, cmd, cmdlen, bp, &len, &bp, &blen, is_bang)) {
+               FREE_SPACEW(sp, bp, blen);
+               return (1);
+       }
+
+       /* If it's empty, we're done. */
+       if (len != 0) {
+               for (p = bp, t = bp + len; p < t; ++p)
+                       if (!ISBLANK((UCHAR_T)*p))
+                               break;
+               if (p == t)
+                       goto ret;
+       } else
+               goto ret;
+
+       (void)argv_exp0(sp, excp, bp, len);
+
+ret:   FREE_SPACEW(sp, bp, blen);
+       return (0);
+}
+
+/*
+ * argv_exp2 --
+ *     Do file name and shell expansion on a string, and append it to
+ *     the argument list.
+ *
+ * PUBLIC: int argv_exp2 __P((SCR *, EXCMD *, CHAR_T *, size_t));
+ */
+int
+argv_exp2(SCR *sp, EXCMD *excp, const CHAR_T *cmd, size_t cmdlen)
+{
+       size_t blen, len, n;
+       int rval;
+       CHAR_T *bp, *p;
+       const char *mp, *np;
+
+       GET_SPACE_RETW(sp, bp, blen, 512);
+
+#define        SHELLECHO       "echo "
+#define        SHELLOFFSET     (sizeof(SHELLECHO) - 1)
+       p = bp;
+       *p++ = 'e'; 
+       *p++ = 'c'; 
+       *p++ = 'h'; 
+       *p++ = 'o'; 
+       *p++ = ' ';
+       len = SHELLOFFSET;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "file_argv: {%.*s}\n", (int)cmdlen, cmd);
+#endif
+
+       if (argv_fexp(sp, excp, cmd, cmdlen, p, &len, &bp, &blen, 0)) {
+               rval = 1;
+               goto err;
+       }
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "before shell: %d: {%s}\n", len, bp);
+#endif
+
+       /*
+        * Do shell word expansion -- it's very, very hard to figure out what
+        * magic characters the user's shell expects.  Historically, it was a
+        * union of v7 shell and csh meta characters.  We match that practice
+        * by default, so ":read \%" tries to read a file named '%'.  It would
+        * make more sense to pass any special characters through the shell,
+        * but then, if your shell was csh, the above example will behave
+        * differently in nvi than in vi.  If you want to get other characters
+        * passed through to your shell, change the "meta" option.
+        *
+        * To avoid a function call per character, we do a first pass through
+        * the meta characters looking for characters that aren't expected
+        * to be there, and then we can ignore them in the user's argument.
+        */
+       if (opts_empty(sp, O_SHELL, 1) || opts_empty(sp, O_SHELLMETA, 1))
+               n = 0;
+       else {
+               for (np = mp = O_STR(sp, O_SHELLMETA); *np != '\0'; ++np)
+                       if (isblank((unsigned char)*np) ||
+                           isalnum((unsigned char)*np))
+                               break;
+               p = bp + SHELLOFFSET;
+               n = len - SHELLOFFSET;
+               if (*p != '\0') {
+                       for (; n > 0; --n, ++p)
+                               if (strchr(mp, *p) != NULL)
+                                       break;
+               } else
+                       for (; n > 0; --n, ++p)
+                               if (!isblank((unsigned char)*p) &&
+                                   !isalnum((unsigned char)*p) && strchr(mp, *p) != NULL)
+                                       break;
+       }
+
+       /*
+        * If we found a meta character in the string, fork a shell to expand
+        * it.  Unfortunately, this is comparatively slow.  Historically, it
+        * didn't matter much, since users don't enter meta characters as part
+        * of pathnames that frequently.  The addition of filename completion
+        * broke that assumption because it's easy to use.  As a result, lots
+        * folks have complained that the expansion code is too slow.  So, we
+        * detect filename completion as a special case, and do it internally.
+        * Note that this code assumes that the <asterisk> character is the
+        * match-anything meta character.  That feels safe -- if anyone writes
+        * a shell that doesn't follow that convention, I'd suggest giving them
+        * a festive hot-lead enema.
+        */
+       switch (n) {
+       case 0:
+               p = bp + SHELLOFFSET;
+               len -= SHELLOFFSET;
+               rval = argv_exp3(sp, excp, p, len);
+               break;
+       case 1:
+               if (*p == '*') {
+                       const char *np1;
+                       char *d;
+                       size_t nlen;
+
+                       *p = '\0';
+                       INT2CHAR(sp, bp + SHELLOFFSET, 
+                                STRLEN(bp + SHELLOFFSET) + 1, np1, nlen);
+                       d = strdup(np1);
+                       rval = argv_lexp(sp, excp, d);
+                       free (d);
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               if (argv_sexp(sp, &bp, &blen, &len)) {
+                       rval = 1;
+                       goto err;
+               }
+               p = bp;
+               rval = argv_exp3(sp, excp, p, len);
+               break;
+       }
+
+err:   FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
+
+/*
+ * argv_exp3 --
+ *     Take a string and break it up into an argv, which is appended
+ *     to the argument list.
+ *
+ * PUBLIC: int argv_exp3 __P((SCR *, EXCMD *, CHAR_T *, size_t));
+ */
+int
+argv_exp3(SCR *sp, EXCMD *excp, const CHAR_T *cmd, size_t cmdlen)
+{
+       EX_PRIVATE *exp;
+       size_t len;
+       ARG_CHAR_T ch;
+       int off;
+       const CHAR_T *ap;
+       CHAR_T *p;
+
+       for (exp = EXP(sp); cmdlen > 0; ++exp->argsoff) {
+               /* Skip any leading whitespace. */
+               for (; cmdlen > 0; --cmdlen, ++cmd) {
+                       ch = (UCHAR_T)*cmd;
+                       if (!ISBLANK(ch))
+                               break;
+               }
+               if (cmdlen == 0)
+                       break;
+
+               /*
+                * Determine the length of this whitespace delimited
+                * argument.
+                *
+                * QUOTING NOTE:
+                *
+                * Skip any character preceded by the user's quoting
+                * character.
+                */
+               for (ap = cmd, len = 0; cmdlen > 0; ++cmd, --cmdlen, ++len) {
+                       ch = (UCHAR_T)*cmd;
+                       if (IS_ESCAPE(sp, excp, ch) && cmdlen > 1) {
+                               ++cmd;
+                               --cmdlen;
+                       } else if (ISBLANK(ch))
+                               break;
+               }
+
+               /*
+                * Copy the argument into place.
+                *
+                * QUOTING NOTE:
+                *
+                * Lose quote chars.
+                */
+               argv_alloc(sp, len);
+               off = exp->argsoff;
+               exp->args[off]->len = len;
+               for (p = exp->args[off]->bp; len > 0; --len, *p++ = *ap++)
+                       if (IS_ESCAPE(sp, excp, *ap))
+                               ++ap;
+               *p = '\0';
+       }
+       excp->argv = exp->args;
+       excp->argc = exp->argsoff;
+
+#if defined(DEBUG) && 0
+       for (cnt = 0; cnt < exp->argsoff; ++cnt)
+               vtrace(sp, "arg %d: {%s}\n", cnt, exp->argv[cnt]);
+#endif
+       return (0);
+}
+
+/*
+ * argv_fexp --
+ *     Do file name and bang command expansion.
+ */
+static int
+argv_fexp(SCR *sp, EXCMD *excp, const CHAR_T *cmd, size_t cmdlen, CHAR_T *p, size_t *lenp, CHAR_T **bpp, size_t *blenp, int is_bang)
+{
+       EX_PRIVATE *exp;
+       char *t;
+       size_t blen, len, off, tlen;
+       CHAR_T *bp;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /* Replace file name characters. */
+       for (bp = *bpp, blen = *blenp, len = *lenp; cmdlen > 0; --cmdlen, ++cmd)
+               switch (*cmd) {
+               case '!':
+                       if (!is_bang)
+                               goto ins_ch;
+                       exp = EXP(sp);
+                       if (exp->lastbcomm == NULL) {
+                               msgq(sp, M_ERR,
+                                   "115|No previous command to replace \"!\"");
+                               return (1);
+                       }
+                       len += tlen = STRLEN(exp->lastbcomm);
+                       off = p - bp;
+                       ADD_SPACE_RETW(sp, bp, blen, len);
+                       p = bp + off;
+                       MEMCPY(p, exp->lastbcomm, tlen);
+                       p += tlen;
+                       F_SET(excp, E_MODIFY);
+                       break;
+               case '%':
+                       if ((t = sp->frp->name) == NULL) {
+                               msgq(sp, M_ERR,
+                                   "116|No filename to substitute for %%");
+                               return (1);
+                       }
+                       tlen = strlen(t);
+                       len += tlen;
+                       off = p - bp;
+                       ADD_SPACE_RETW(sp, bp, blen, len);
+                       p = bp + off;
+                       CHAR2INT(sp, t, tlen, wp, wlen);
+                       MEMCPY(p, wp, wlen);
+                       p += wlen;
+                       F_SET(excp, E_MODIFY);
+                       break;
+               case '#':
+                       if ((t = sp->alt_name) == NULL) {
+                               msgq(sp, M_ERR,
+                                   "117|No filename to substitute for #");
+                               return (1);
+                       }
+                       len += tlen = strlen(t);
+                       off = p - bp;
+                       ADD_SPACE_RETW(sp, bp, blen, len);
+                       p = bp + off;
+                       CHAR2INT(sp, t, tlen, wp, wlen);
+                       MEMCPY(p, wp, wlen);
+                       p += tlen;
+                       F_SET(excp, E_MODIFY);
+                       break;
+               case '\\':
+                       /*
+                        * QUOTING NOTE:
+                        *
+                        * Strip any backslashes that protected the file
+                        * expansion characters.
+                        */
+                       if (cmdlen > 1 &&
+                           (cmd[1] == '%' || cmd[1] == '#' || cmd[1] == '!')) {
+                               ++cmd;
+                               --cmdlen;
+                       }
+                       /* FALLTHROUGH */
+               default:
+ins_ch:                        ++len;
+                       off = p - bp;
+                       ADD_SPACE_RETW(sp, bp, blen, len);
+                       p = bp + off;
+                       *p++ = *cmd;
+               }
+
+       /* Nul termination. */
+       ++len;
+       off = p - bp;
+       ADD_SPACE_RETW(sp, bp, blen, len);
+       p = bp + off;
+       *p = '\0';
+
+       /* Return the new string length, buffer, buffer length. */
+       *lenp = len - 1;
+       *bpp = bp;
+       *blenp = blen;
+       return (0);
+}
+
+/*
+ * argv_alloc --
+ *     Make more space for arguments.
+ */
+static int
+argv_alloc(SCR *sp, size_t len)
+{
+       ARGS *ap;
+       EX_PRIVATE *exp;
+       int cnt, off;
+
+       /*
+        * Allocate room for another argument, always leaving
+        * enough room for an ARGS structure with a length of 0.
+        */
+#define        INCREMENT       20
+       exp = EXP(sp);
+       off = exp->argsoff;
+       if (exp->argscnt == 0 || off + 2 >= exp->argscnt - 1) {
+               cnt = exp->argscnt + INCREMENT;
+               REALLOC(sp, exp->args, ARGS **, cnt * sizeof(ARGS *));
+               if (exp->args == NULL) {
+                       (void)argv_free(sp);
+                       goto mem;
+               }
+               memset(&exp->args[exp->argscnt], 0, INCREMENT * sizeof(ARGS *));
+               exp->argscnt = cnt;
+       }
+
+       /* First argument. */
+       if (exp->args[off] == NULL) {
+               CALLOC(sp, exp->args[off], ARGS *, 1, sizeof(ARGS));
+               if (exp->args[off] == NULL)
+                       goto mem;
+       }
+
+       /* First argument buffer. */
+       ap = exp->args[off];
+       ap->len = 0;
+       if (ap->blen < len + 1) {
+               ap->blen = len + 1;
+               REALLOC(sp, ap->bp, CHAR_T *, ap->blen * sizeof(CHAR_T));
+               if (ap->bp == NULL) {
+                       ap->bp = NULL;
+                       ap->blen = 0;
+                       F_CLR(ap, A_ALLOCATED);
+mem:                   msgq(sp, M_SYSERR, NULL);
+                       return (1);
+               }
+               F_SET(ap, A_ALLOCATED);
+       }
+
+       /* Second argument. */
+       if (exp->args[++off] == NULL) {
+               CALLOC(sp, exp->args[off], ARGS *, 1, sizeof(ARGS));
+               if (exp->args[off] == NULL)
+                       goto mem;
+       }
+       /* 0 length serves as end-of-argument marker. */
+       exp->args[off]->len = 0;
+       return (0);
+}
+
+/*
+ * argv_free --
+ *     Free up argument structures.
+ *
+ * PUBLIC: int argv_free __P((SCR *));
+ */
+int
+argv_free(SCR *sp)
+{
+       EX_PRIVATE *exp;
+       int off;
+
+       exp = EXP(sp);
+       if (exp->args != NULL) {
+               for (off = 0; off < exp->argscnt; ++off) {
+                       if (exp->args[off] == NULL)
+                               continue;
+                       if (F_ISSET(exp->args[off], A_ALLOCATED))
+                               free(exp->args[off]->bp);
+                       free(exp->args[off]);
+               }
+               free(exp->args);
+       }
+       exp->args = NULL;
+       exp->argscnt = 0;
+       exp->argsoff = 0;
+       return (0);
+}
+
+/*
+ * argv_lexp --
+ *     Find all file names matching the prefix and append them to the
+ *     buffer.
+ */
+static int
+argv_lexp(SCR *sp, EXCMD *excp, const char *path)
+{
+       struct dirent *dp;
+       DIR *dirp;
+       EX_PRIVATE *exp;
+       int off;
+       size_t dlen, len, nlen;
+       const char *dname, *name;
+       char *p;
+       size_t wlen;
+       const CHAR_T *wp;
+       CHAR_T *n;
+
+       exp = EXP(sp);
+
+       /* Set up the name and length for comparison. */
+       if ((p = strrchr(path, '/')) == NULL) {
+               dname = ".";
+               dlen = 0;
+               name = path;
+       } else { 
+               if (p == path) {
+                       dname = "/";
+                       dlen = 1;
+               } else {
+                       *p = '\0';
+                       dname = path;
+                       dlen = strlen(path);
+               }
+               name = p + 1;
+       }
+       nlen = strlen(name);
+
+       /*
+        * XXX
+        * We don't use the d_namlen field, it's not portable enough; we
+        * assume that d_name is nul terminated, instead.
+        */
+       if ((dirp = opendir(dname)) == NULL) {
+               msgq_str(sp, M_SYSERR, dname, "%s");
+               return (1);
+       }
+       for (off = exp->argsoff; (dp = readdir(dirp)) != NULL;) {
+               if (nlen == 0) {
+                       if (dp->d_name[0] == '.')
+                               continue;
+                       len = strlen(dp->d_name);
+               } else {
+                       len = strlen(dp->d_name);
+                       if (len < nlen || memcmp(dp->d_name, name, nlen))
+                               continue;
+               }
+
+               /* Directory + name + slash + null. */
+               argv_alloc(sp, dlen + len + 2);
+               n = exp->args[exp->argsoff]->bp;
+               if (dlen != 0) {
+                       CHAR2INT(sp, dname, dlen, wp, wlen);
+                       MEMCPY(n, wp, wlen);
+                       n += dlen;
+                       if (dlen > 1 || dname[0] != '/')
+                               *n++ = '/';
+               }
+               CHAR2INT(sp, dp->d_name, len + 1, wp, wlen);
+               MEMCPY(n, wp, wlen);
+               exp->args[exp->argsoff]->len = dlen + len + 1;
+               ++exp->argsoff;
+               excp->argv = exp->args;
+               excp->argc = exp->argsoff;
+       }
+       closedir(dirp);
+
+       if (off == exp->argsoff) {
+               /*
+                * If we didn't find a match, complain that the expansion
+                * failed.  We can't know for certain that's the error, but
+                * it's a good guess, and it matches historic practice. 
+                */
+               msgq(sp, M_ERR, "304|Shell expansion failed");
+               return (1);
+       }
+       qsort(exp->args + off, exp->argsoff - off, sizeof(ARGS *), argv_comp);
+       return (0);
+}
+
+/*
+ * argv_comp --
+ *     Alphabetic comparison.
+ */
+static int
+argv_comp(const void *a, const void *b)
+{
+       return (STRCMP((*(const ARGS * const*)a)->bp, (*(const ARGS * const*)b)->bp));
+}
+
+static pid_t
+runcmd(SCR *sp, const char *sh_path, const char *sh, const char *np,
+    int *std_output)
+{
+       pid_t pid;
+       /*
+        * Do the minimal amount of work possible, the shell is going to run
+        * briefly and then exit.  We sincerely hope.
+        */
+       switch (pid = vfork()) {
+       case -1:                        /* Error. */
+               msgq(sp, M_SYSERR, "vfork");
+               return (pid_t)-1;
+       case 0:                         /* Utility. */
+               /* Redirect stdout to the write end of the pipe. */
+               (void)dup2(std_output[1], STDOUT_FILENO);
+
+               /* Close the utility's file descriptors. */
+               (void)close(std_output[0]);
+               (void)close(std_output[1]);
+               (void)close(STDERR_FILENO);
+
+               /*
+                * XXX
+                * Assume that all shells have -c.
+                */
+               execl(sh_path, sh, "-c", np, (char *)NULL);
+               msgq_str(sp, M_SYSERR, sh_path, "118|Error: execl: %s");
+               _exit(127);
+       default:                        /* Parent. */
+               /* Close the pipe ends the parent won't use. */
+               (void)close(std_output[1]);
+               return pid;
+       }
+}
+
+/*
+ * argv_sexp --
+ *     Fork a shell, pipe a command through it, and read the output into
+ *     a buffer.
+ */
+static int
+argv_sexp(SCR *sp, CHAR_T **bpp, size_t *blenp, size_t *lenp)
+{
+       enum { SEXP_ERR, SEXP_EXPANSION_ERR, SEXP_OK } rval;
+       FILE *ifp;
+       pid_t pid;
+       size_t blen, len;
+       int ch, std_output[2];
+       CHAR_T *bp, *p;
+       const char *sh, *sh_path;
+       const char *np;
+       size_t nlen;
+
+       /* Secure means no shell access. */
+       if (O_ISSET(sp, O_SECURE)) {
+               msgq(sp, M_ERR,
+"289|Shell expansions not supported when the secure edit option is set");
+               return (1);
+       }
+
+       sh_path = O_STR(sp, O_SHELL);
+       if ((sh = strrchr(sh_path, '/')) == NULL)
+               sh = sh_path;
+       else
+               ++sh;
+
+       /* Local copies of the buffer variables. */
+       bp = *bpp;
+       blen = *blenp;
+
+       /*
+        * There are two different processes running through this code, named
+        * the utility (the shell) and the parent. The utility reads standard
+        * input and writes standard output and standard error output.  The
+        * parent writes to the utility, reads its standard output and ignores
+        * its standard error output.  Historically, the standard error output
+        * was discarded by vi, as it produces a lot of noise when file patterns
+        * don't match.
+        *
+        * The parent reads std_output[0], and the utility writes std_output[1].
+        */
+       ifp = NULL;
+       std_output[0] = std_output[1] = -1;
+       if (pipe(std_output) < 0) {
+               msgq(sp, M_SYSERR, "pipe");
+               return (1);
+       }
+       if ((ifp = fdopen(std_output[0], "r")) == NULL) {
+               msgq(sp, M_SYSERR, "fdopen");
+               goto err;
+       }
+       INT2CHAR(sp, bp, STRLEN(bp)+1, np, nlen);
+       pid = runcmd(sp, sh_path, sh, np, std_output);
+       if (pid == -1)
+               goto err;
+
+       /*
+        * Copy process standard output into a buffer.
+        *
+        * !!!
+        * Historic vi apparently discarded leading \n and \r's from
+        * the shell output stream.  We don't on the grounds that any
+        * shell that does that is broken.
+        */
+       for (p = bp, len = 0, ch = EOF;
+           (ch = getc(ifp)) != EOF; *p++ = ch, blen-=sizeof(CHAR_T), ++len)
+               if (blen < 5) {
+                       ADD_SPACE_GOTOW(sp, bp, *blenp, *blenp * 2);
+                       p = bp + len;
+                       blen = *blenp - len;
+               }
+
+       /* Delete the final newline, nul terminate the string. */
+       if (p > bp && (p[-1] == '\n' || p[-1] == '\r')) {
+               --p;
+               --len;
+       }
+       *p = '\0';
+       *lenp = len;
+       *bpp = bp;              /* *blenp is already updated. */
+
+       if (ferror(ifp))
+               goto ioerr;
+       if (fclose(ifp)) {
+ioerr:         msgq_str(sp, M_ERR, sh, "119|I/O error: %s");
+alloc_err:     rval = SEXP_ERR;
+       } else
+               rval = SEXP_OK;
+
+       /*
+        * Wait for the process.  If the shell process fails (e.g., "echo $q"
+        * where q wasn't a defined variable) or if the returned string has
+        * no characters or only blank characters, (e.g., "echo $5"), complain
+        * that the shell expansion failed.  We can't know for certain that's
+        * the error, but it's a good guess, and it matches historic practice.
+        * This won't catch "echo foo_$5", but that's not a common error and
+        * historic vi didn't catch it either.
+        */
+       if (proc_wait(sp, (long)pid, sh, 1, 0))
+               rval = SEXP_EXPANSION_ERR;
+
+       for (p = bp; len; ++p, --len)
+               if (!ISBLANK((UCHAR_T)*p))
+                       break;
+       if (len == 0)
+               rval = SEXP_EXPANSION_ERR;
+
+       if (rval == SEXP_EXPANSION_ERR)
+               msgq(sp, M_ERR, "304|Shell expansion failed");
+
+       return (rval == SEXP_OK ? 0 : 1);
+err:   if (ifp != NULL)
+               (void)fclose(ifp);
+       else if (std_output[0] != -1)
+               close(std_output[0]);
+       if (std_output[1] != -1)
+               close(std_output[0]);
+       return 1;
+}
diff --git a/dist/nvi/ex/ex_at.c b/dist/nvi/ex/ex_at.c
new file mode 100644 (file)
index 0000000..23d7b03
--- /dev/null
@@ -0,0 +1,126 @@
+/*     $NetBSD: ex_at.c,v 1.3 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_at.c,v 10.16 2001/06/25 15:19:14 skimo Exp (Berkeley) Date: 2001/06/25 15:19:14";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_at -- :@[@ | buffer]
+ *         :*[* | buffer]
+ *
+ *     Execute the contents of the buffer.
+ *
+ * PUBLIC: int ex_at __P((SCR *, EXCMD *));
+ */
+int
+ex_at(SCR *sp, EXCMD *cmdp)
+{
+       CB *cbp;
+       ARG_CHAR_T name;
+       EXCMD *ecp;
+       RANGE *rp;
+       TEXT *tp;
+       size_t len;
+       CHAR_T *p;
+
+       /*
+        * !!!
+        * Historically, [@*]<carriage-return> and [@*][@*] executed the most
+        * recently executed buffer in ex mode.
+        */
+       name = FL_ISSET(cmdp->iflags, E_C_BUFFER) ? cmdp->buffer : '@';
+       if (name == '@' || name == '*') {
+               if (!F_ISSET(sp, SC_AT_SET)) {
+                       ex_emsg(sp, NULL, EXM_NOPREVBUF);
+                       return (1);
+               }
+               name = sp->at_lbuf;
+       }
+       sp->at_lbuf = name;
+       F_SET(sp, SC_AT_SET);
+
+       CBNAME(sp, cbp, name);
+       if (cbp == NULL) {
+               ex_emsg(sp, (char *)KEY_NAME(sp, name), EXM_EMPTYBUF);
+               return (1);
+       }
+
+       /*
+        * !!!
+        * Historically the @ command took a range of lines, and the @ buffer
+        * was executed once per line.  The historic vi could be trashed by
+        * this because it didn't notice if the underlying file changed, or,
+        * for that matter, if there were no more lines on which to operate.
+        * For example, take a 10 line file, load "%delete" into a buffer,
+        * and enter :8,10@<buffer>.
+        *
+        * The solution is a bit tricky.  If the user specifies a range, take
+        * the same approach as for global commands, and discard the command
+        * if exit or switch to a new file/screen.  If the user doesn't specify
+        * the  range, continue to execute after a file/screen switch, which
+        * means @ buffers are still useful in a multi-screen environment.
+        */
+       CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
+       CIRCLEQ_INIT(&ecp->rq);
+       CALLOC_RET(sp, rp, RANGE *, 1, sizeof(RANGE));
+       rp->start = cmdp->addr1.lno;
+       if (F_ISSET(cmdp, E_ADDR_DEF)) {
+               rp->stop = rp->start;
+               FL_SET(ecp->agv_flags, AGV_AT_NORANGE);
+       } else {
+               rp->stop = cmdp->addr2.lno;
+               FL_SET(ecp->agv_flags, AGV_AT);
+       }
+       CIRCLEQ_INSERT_HEAD(&ecp->rq, rp, q);
+
+       /*
+        * Buffers executed in ex mode or from the colon command line in vi
+        * were ex commands.  We can't push it on the terminal queue, since
+        * it has to be executed immediately, and we may be in the middle of
+        * an ex command already.  Push the command on the ex command stack.
+        * Build two copies of the command.  We need two copies because the
+        * ex parser may step on the command string when it's parsing it.
+        */
+       for (len = 0, tp = cbp->textq.cqh_last;
+           tp != (void *)&cbp->textq; tp = tp->q.cqe_prev)
+               len += tp->len + 1;
+
+       MALLOC_RET(sp, ecp->cp, CHAR_T *, len * 2 * sizeof(CHAR_T));
+       ecp->o_cp = ecp->cp;
+       ecp->o_clen = len;
+       ecp->cp[len] = '\0';
+
+       /* Copy the buffer into the command space. */
+       for (p = ecp->cp + len, tp = cbp->textq.cqh_last;
+           tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) {
+               MEMCPYW(p, tp->lb, tp->len);
+               p += tp->len;
+               *p++ = '\n';
+       }
+
+       LIST_INSERT_HEAD(&sp->wp->ecq, ecp, q);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_bang.c b/dist/nvi/ex/ex_bang.c
new file mode 100644 (file)
index 0000000..e88c533
--- /dev/null
@@ -0,0 +1,191 @@
+/*     $NetBSD: ex_bang.c,v 1.3 2009/11/14 23:40:11 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_bang.c,v 10.36 2001/06/25 15:19:14 skimo Exp (Berkeley) Date: 2001/06/25 15:19:14";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_bang -- :[line [,line]] ! command
+ *
+ * Pass the rest of the line after the ! character to the program named by
+ * the O_SHELL option.
+ *
+ * Historical vi did NOT do shell expansion on the arguments before passing
+ * them, only file name expansion.  This means that the O_SHELL program got
+ * "$t" as an argument if that is what the user entered.  Also, there's a
+ * special expansion done for the bang command.  Any exclamation points in
+ * the user's argument are replaced by the last, expanded ! command.
+ *
+ * There's some fairly amazing slop in this routine to make the different
+ * ways of getting here display the right things.  It took a long time to
+ * get it right (wrong?), so be careful.
+ *
+ * PUBLIC: int ex_bang __P((SCR *, EXCMD *));
+ */
+int
+ex_bang(SCR *sp, EXCMD *cmdp)
+{
+       enum filtertype ftype;
+       ARGS *ap;
+       EX_PRIVATE *exp;
+       MARK rm;
+       db_recno_t lno;
+       int rval;
+       const char *msg;
+       const char *np;
+       size_t nlen;
+
+       ap = cmdp->argv[0];
+       if (ap->len == 0) {
+               ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+               return (1);
+       }
+
+       /* Set the "last bang command" remembered value. */
+       exp = EXP(sp);
+       if (exp->lastbcomm != NULL)
+               free(exp->lastbcomm);
+       if ((exp->lastbcomm = v_wstrdup(sp, ap->bp, ap->len)) == NULL) {
+               msgq(sp, M_SYSERR, NULL);
+               return (1);
+       }
+
+       /*
+        * If the command was modified by the expansion, it was historically
+        * redisplayed.
+        */
+       if (F_ISSET(cmdp, E_MODIFY) && !F_ISSET(sp, SC_EX_SILENT)) {
+               /*
+                * Display the command if modified.  Historic ex/vi displayed
+                * the command if it was modified due to file name and/or bang
+                * expansion.  If piping lines in vi, it would be immediately
+                * overwritten by any error or line change reporting.
+                */
+               if (F_ISSET(sp, SC_VI))
+                       vs_update(sp, "!", ap->bp);
+               else {
+                       INT2CHAR(sp, ap->bp, ap->len+1, np, nlen);
+                       (void)ex_printf(sp, "!%s\n", np);
+                       (void)ex_fflush(sp);
+               }
+       }
+
+       /*
+        * If no addresses were specified, run the command.  If there's an
+        * underlying file, it's been modified and autowrite is set, write
+        * the file back.  If the file has been modified, autowrite is not
+        * set and the warn option is set, tell the user about the file.
+        */
+       if (cmdp->addrcnt == 0) {
+               msg = NULL;
+               if (sp->ep != NULL && F_ISSET(sp->ep, F_MODIFIED)) {
+                       if (O_ISSET(sp, O_AUTOWRITE)) {
+                               if (file_aw(sp, FS_ALL))
+                                       return (0);
+                       } else if (O_ISSET(sp, O_WARN) &&
+                           !F_ISSET(sp, SC_EX_SILENT))
+                               msg = msg_cat(sp,
+                                   "303|File modified since last write.",
+                                   NULL);
+               }
+
+               /* If we're still in a vi screen, move out explicitly. */
+               INT2CHAR(sp, ap->bp, ap->len+1, np, nlen);
+               (void)ex_exec_proc(sp,
+                   cmdp, np, msg, !F_ISSET(sp, SC_EX | SC_SCR_EXWROTE));
+       }
+
+       /*
+        * If addresses were specified, pipe lines from the file through the
+        * command.
+        *
+        * Historically, vi lines were replaced by both the stdout and stderr
+        * lines of the command, but ex lines by only the stdout lines.  This
+        * makes no sense to me, so nvi makes it consistent for both, and
+        * matches vi's historic behavior.
+        */
+       else {
+               NEEDFILE(sp, cmdp);
+
+               /* Autoprint is set historically, even if the command fails. */
+               F_SET(cmdp, E_AUTOPRINT);
+
+               /*
+                * !!!
+                * Historical vi permitted "!!" in an empty file.  When this
+                * happens, we arrive here with two addresses of 1,1 and a
+                * bad attitude.  The simple solution is to turn it into a
+                * FILTER_READ operation, with the exception that stdin isn't
+                * opened for the utility, and the cursor position isn't the
+                * same.  The only historic glitch (I think) is that we don't
+                * put an empty line into the default cut buffer, as historic
+                * vi did.  Imagine, if you can, my disappointment.
+                */
+               ftype = FILTER_BANG;
+               if (cmdp->addr1.lno == 1 && cmdp->addr2.lno == 1) {
+                       if (db_last(sp, &lno))
+                               return (1);
+                       if (lno == 0) {
+                               cmdp->addr1.lno = cmdp->addr2.lno = 0;
+                               ftype = FILTER_RBANG;
+                       }
+               }
+               rval = ex_filter(sp, cmdp,
+                   &cmdp->addr1, &cmdp->addr2, &rm, ap->bp, ftype);
+
+               /*
+                * If in vi mode, move to the first nonblank.
+                *
+                * !!!
+                * Historic vi wasn't consistent in this area -- if you used
+                * a forward motion it moved to the first nonblank, but if you
+                * did a backward motion it didn't.  And, if you followed a
+                * backward motion with a forward motion, it wouldn't move to
+                * the nonblank for either.  Going to the nonblank generally
+                * seems more useful and consistent, so we do it.
+                */
+               sp->lno = rm.lno;
+               if (F_ISSET(sp, SC_VI)) {
+                       sp->cno = 0;
+                       (void)nonblank(sp, sp->lno, &sp->cno);
+               } else
+                       sp->cno = rm.cno;
+       }
+
+       /* Ex terminates with a bang, even if the command fails. */
+       if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
+               (void)ex_puts(sp, "!\n");
+
+       /*
+        * XXX
+        * The ! commands never return an error, so that autoprint always
+        * happens in the ex parser.
+        */
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_cd.c b/dist/nvi/ex/ex_cd.c
new file mode 100644 (file)
index 0000000..836f154
--- /dev/null
@@ -0,0 +1,129 @@
+/*     $NetBSD: ex_cd.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_cd.c,v 10.12 2001/06/25 15:19:14 skimo Exp (Berkeley) Date: 2001/06/25 15:19:14";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_cd -- :cd[!] [directory]
+ *     Change directories.
+ *
+ * PUBLIC: int ex_cd __P((SCR *, EXCMD *));
+ */
+int
+ex_cd(SCR *sp, EXCMD *cmdp)
+{
+       struct passwd *pw;
+       ARGS *ap;
+       const char *p, *t;      /* XXX: END OF THE STACK, DON'T TRUST GETCWD. */
+       const char *dir;
+       char buf[MAXPATHLEN * 2];
+       size_t dlen;
+
+       /*
+        * !!!
+        * Historic practice is that the cd isn't attempted if the file has
+        * been modified, unless its name begins with a leading '/' or the
+        * force flag is set.
+        */
+       if (F_ISSET(sp->ep, F_MODIFIED) &&
+           !FL_ISSET(cmdp->iflags, E_C_FORCE) && sp->frp->name[0] != '/') {
+               msgq(sp, M_ERR,
+    "120|File modified since last complete write; write or use ! to override");
+               return (1);
+       }
+
+       switch (cmdp->argc) {
+       case 0:
+               /* If no argument, change to the user's home directory. */
+               if ((dir = getenv("HOME")) == NULL) {
+                       if ((pw = getpwuid(getuid())) == NULL ||
+                           pw->pw_dir == NULL || pw->pw_dir[0] == '\0') {
+                               msgq(sp, M_ERR,
+                          "121|Unable to find home directory location");
+                               return (1);
+                       }
+                       dir = pw->pw_dir;
+               }
+               break;
+       case 1:
+               INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, 
+                        dir, dlen);
+               break;
+       default:
+               abort();
+       }
+
+       /*
+        * Try the current directory first.  If this succeeds, don't display
+        * a message, vi didn't historically, and it should be obvious to the
+        * user where they are.
+        */
+       if (!chdir(dir))
+               return (0);
+
+       /*
+        * If moving to the user's home directory, or, the path begins with
+        * "/", "./" or "../", it's the only place we try.
+        */
+       if (cmdp->argc == 0 ||
+           (ap = cmdp->argv[0])->bp[0] == '/' ||
+           (ap->len == 1 && ap->bp[0] == '.') ||
+           (ap->len >= 2 && ap->bp[0] == '.' && ap->bp[1] == '.' &&
+           (ap->bp[2] == '/' || ap->bp[2] == '\0')))
+               goto err;
+
+       /* Try the O_CDPATH option values. */
+       for (p = t = O_STR(sp, O_CDPATH);; ++p)
+               if (*p == '\0' || *p == ':') {
+                       /*
+                        * Empty strings specify ".".  The only way to get an
+                        * empty string is a leading colon, colons in a row,
+                        * or a trailing colon.  Or, to put it the other way,
+                        * if the length is 1 or less, then we're dealing with
+                        * ":XXX", "XXX::XXXX" , "XXX:", or "".  Since we've
+                        * already tried dot, we ignore tham all.
+                        */
+                       if (t < p - 1) {
+                               (void)snprintf(buf,
+                                   sizeof(buf), "%.*s/%s", (int)(p - t),
+                                       t, dir);
+                               if (!chdir(buf)) {
+                                       if (getcwd(buf, sizeof(buf)) != NULL)
+               msgq_str(sp, M_INFO, buf, "122|New current directory: %s");
+                                       return (0);
+                               }
+                       }
+                       t = p + 1;
+                       if (*p == '\0')
+                               break;
+               }
+
+err:   msgq_str(sp, M_SYSERR, dir, "%s");
+       return (1);
+}
diff --git a/dist/nvi/ex/ex_cmd.c b/dist/nvi/ex/ex_cmd.c
new file mode 100644 (file)
index 0000000..d339421
--- /dev/null
@@ -0,0 +1,474 @@
+/*     $NetBSD: ex_cmd.c,v 1.3 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_cmd.c,v 10.25 2001/06/10 10:23:44 skimo Exp (Berkeley) Date: 2001/06/10 10:23:44";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * This array maps ex command names to command functions.
+ *
+ * The order in which command names are listed below is important --
+ * ambiguous abbreviations are resolved to be the first possible match,
+ * e.g. "r" means "read", not "rewind", because "read" is listed before
+ * "rewind".
+ *
+ * The syntax of the ex commands is unbelievably irregular, and a special
+ * case from beginning to end.  Each command has an associated "syntax
+ * script" which describes the "arguments" that are possible.  The script
+ * syntax is as follows:
+ *
+ *     !               -- ! flag
+ *     1               -- flags: [+-]*[pl#][+-]*
+ *     2               -- flags: [-.+^]
+ *     3               -- flags: [-.+^=]
+ *     b               -- buffer
+ *     c[01+a]         -- count (0-N, 1-N, signed 1-N, address offset)
+ *     f[N#][or]       -- file (a number or N, optional or required)
+ *     l               -- line
+ *     S               -- string with file name expansion
+ *     s               -- string
+ *     W               -- word string
+ *     w[N#][or]       -- word (a number or N, optional or required)
+ */
+EXCMDLIST const cmds[] = {
+/* C_SCROLL */
+       {L("\004"),     ex_pr,          E_ADDR2,
+           "",
+           "^D",
+           "scroll lines"},
+/* C_BANG */
+       {L("!"),                ex_bang,        E_ADDR2_NONE|E_SECURE,
+           "S",
+           "[line [,line]] ! command",
+           "filter lines through commands or run commands"},
+/* C_HASH */
+       {L("#"),                ex_number,      E_ADDR2|E_CLRFLAG,
+           "ca1",
+           "[line [,line]] # [count] [l]",
+           "display numbered lines"},
+/* C_SUBAGAIN */
+       {L("&"),                ex_subagain,    E_ADDR2|E_ADDR_ZERO,
+           "s",
+           "[line [,line]] & [cgr] [count] [#lp]",
+           "repeat the last subsitution"},
+/* C_STAR */
+       {L("*"),                ex_at,          0,
+           "b",
+           "* [buffer]",
+           "execute a buffer"},
+/* C_SHIFTL */
+       {L("<"),                ex_shiftl,      E_ADDR2|E_AUTOPRINT,
+           "ca1",
+           "[line [,line]] <[<...] [count] [flags]",
+           "shift lines left"},
+/* C_EQUAL */
+       {L("="),                ex_equal,       E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
+           "1",
+           "[line] = [flags]",
+           "display line number"},
+/* C_SHIFTR */
+       {L(">"),                ex_shiftr,      E_ADDR2|E_AUTOPRINT,
+           "ca1",
+           "[line [,line]] >[>...] [count] [flags]",
+           "shift lines right"},
+/* C_AT */
+       {L("@"),                ex_at,          E_ADDR2,
+           "b",
+           "@ [buffer]",
+           "execute a buffer"},
+/* C_APPEND */
+       {L("append"),   ex_append,      E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
+           "!",
+           "[line] a[ppend][!]",
+           "append input to a line"},
+/* C_ABBR */
+       {L("abbreviate"),       ex_abbr,        0,
+           "W",
+           "ab[brev] [word replace]",
+           "specify an input abbreviation"},
+/* C_ARGS */
+       {L("args"),     ex_args,        0,
+           "",
+           "ar[gs]",
+           "display file argument list"},
+/* C_BG */
+       {L("bg"),               ex_bg,          E_VIONLY,
+           "",
+           "bg",
+           "put a foreground screen into the background"},
+/* C_CHANGE */
+       {L("change"),   ex_change,      E_ADDR2|E_ADDR_ZERODEF,
+           "!ca",
+           "[line [,line]] c[hange][!] [count]",
+           "change lines to input"},
+/* C_CD */
+       {L("cd"),               ex_cd,          0,
+           "!f1o",
+           "cd[!] [directory]",
+           "change the current directory"},
+/* C_CHDIR */
+       {L("chdir"),    ex_cd,          0,
+           "!f1o",
+           "chd[ir][!] [directory]",
+           "change the current directory"},
+/* C_COPY */
+       {L("copy"),     ex_copy,        E_ADDR2|E_AUTOPRINT,
+           "l1",
+           "[line [,line]] co[py] line [flags]",
+           "copy lines elsewhere in the file"},
+/* C_CSCOPE */
+       {L("cscope"),      ex_cscope,      0,
+           "!s",
+           "cs[cope] command [args]",
+           "create a set of tags using a cscope command"},
+/*
+ * !!!
+ * Adding new commands starting with 'd' may break the delete command code
+ * in ex_cmd() (the ex parser).  Read through the comments there, first.
+ */
+/* C_DELETE */
+       {L("delete"),   ex_delete,      E_ADDR2|E_AUTOPRINT,
+           "bca1",
+           "[line [,line]] d[elete][flags] [buffer] [count] [flags]",
+           "delete lines from the file"},
+/* C_DISPLAY */
+       {L("display"),  ex_display,     0,
+           "w1r",
+           "display b[uffers] | c[onnections] | s[creens] | t[ags]",
+           "display buffers, connections, screens or tags"},
+/* C_EDIT */
+       {L("edit"),     ex_edit,        E_NEWSCREEN,
+           "f1o",
+           "[Ee][dit][!] [+cmd] [file]",
+           "begin editing another file"},
+/* C_EX */
+       {L("ex"),               ex_edit,        E_NEWSCREEN,
+           "f1o",
+           "[Ee]x[!] [+cmd] [file]",
+           "begin editing another file"},
+/* C_EXUSAGE */
+       {L("exusage"),  ex_usage,       0,
+           "w1o",
+           "[exu]sage [command]",
+           "display ex command usage statement"},
+/* C_FILE */
+       {L("file"),     ex_file,        0,
+           "f1o",
+           "f[ile] [name]",
+           "display (and optionally set) file name"},
+/* C_FG */
+       {L("fg"),               ex_fg,          E_NEWSCREEN|E_VIONLY,
+           "f1o",
+           "[Ff]g [file]",
+           "bring a backgrounded screen into the foreground"},
+/* C_GLOBAL */
+       {L("global"),   ex_global,      E_ADDR2_ALL,
+           "!s",
+           "[line [,line]] g[lobal][!] [;/]RE[;/] [commands]",
+           "execute a global command on lines matching an RE"},
+/* C_HELP */
+       {L("help"),     ex_help,        0,
+           "",
+           "he[lp]",
+           "display help statement"},
+/* C_INSERT */
+       {L("insert"),   ex_insert,      E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
+           "!",
+           "[line] i[nsert][!]",
+           "insert input before a line"},
+/* C_JOIN */
+       {L("join"),     ex_join,        E_ADDR2|E_AUTOPRINT,
+           "!ca1",
+           "[line [,line]] j[oin][!] [count] [flags]",
+           "join lines into a single line"},
+/* C_K */
+       {L("k"),                ex_mark,        E_ADDR1,
+           "w1r",
+           "[line] k key",
+           "mark a line position"},
+/* C_LIST */
+       {L("list"),     ex_list,        E_ADDR2|E_CLRFLAG,
+           "ca1",
+           "[line [,line]] l[ist] [count] [#]",
+           "display lines in an unambiguous form"},
+/* C_MOVE */
+       {L("move"),     ex_move,        E_ADDR2|E_AUTOPRINT,
+           "l",
+           "[line [,line]] m[ove] line",
+           "move lines elsewhere in the file"},
+/* C_MARK */
+       {L("mark"),     ex_mark,        E_ADDR1,
+           "w1r",
+           "[line] ma[rk] key",
+           "mark a line position"},
+/* C_MAP */
+       {L("map"),              ex_map,         0,
+           "!W",
+           "map[!] [keys replace]",
+           "map input or commands to one or more keys"},
+/* C_MKEXRC */
+       {L("mkexrc"),   ex_mkexrc,      0,
+           "!f1r",
+           "mkexrc[!] file",
+           "write a .exrc file"},
+/* C_NEXT */
+       {L("next"),     ex_next,        E_NEWSCREEN,
+           "!fN",
+           "[Nn][ext][!] [+cmd] [file ...]",
+           "edit (and optionally specify) the next file"},
+/* C_NUMBER */
+       {L("number"),   ex_number,      E_ADDR2|E_CLRFLAG,
+           "ca1",
+           "[line [,line]] nu[mber] [count] [l]",
+           "change display to number lines"},
+/* C_OPEN */
+       {L("open"),     ex_open,        E_ADDR1,
+           "s",
+           "[line] o[pen] [/RE/] [flags]",
+           "enter \"open\" mode (not implemented)"},
+/* C_PRINT */
+       {L("print"),    ex_pr,          E_ADDR2|E_CLRFLAG,
+           "ca1",
+           "[line [,line]] p[rint] [count] [#l]",
+           "display lines"},
+/* C_PERLCMD */
+       {L("perl"),     ex_perl,        E_ADDR2_ALL|E_ADDR_ZERO|
+                                           E_ADDR_ZERODEF|E_SECURE,
+           "s",
+           "pe[rl] cmd",
+           "run the perl interpreter with the command"},
+/* C_PERLDOCMD */
+       {L("perldo"),   ex_perl,        E_ADDR2|E_ADDR_ZERO|
+                                           E_ADDR_ZERODEF|E_SECURE,
+           "s",
+           "perld[o] cmd",
+           "run the perl interpreter with the command, on each line"},
+/* C_PRESERVE */
+       {L("preserve"), ex_preserve,    0,
+           "",
+           "pre[serve]",
+           "preserve an edit session for recovery"},
+/* C_PREVIOUS */
+       {L("previous"), ex_prev,        E_NEWSCREEN,
+           "!",
+           "[Pp]rev[ious][!]",
+           "edit the previous file in the file argument list"},
+/* C_PUT */
+       {L("put"),              ex_put, 
+           E_ADDR1|E_AUTOPRINT|E_ADDR_ZERO|E_ADDR_ZERODEF,
+           "b",
+           "[line] pu[t] [buffer]",
+           "append a cut buffer to the line"},
+/* C_QUIT */
+       {L("quit"),     ex_quit,        0,
+           "!",
+           "q[uit][!]",
+           "exit ex/vi"},
+/* C_READ */
+       {L("read"),     ex_read,        E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
+           "s",
+           "[line] r[ead] [!cmd | [file]]",
+           "append input from a command or file to the line"},
+/* C_RECOVER */
+       {L("recover"),  ex_recover,     0,
+           "!f1r",
+           "recover[!] file",
+           "recover a saved file"},
+/* C_RESIZE */
+       {L("resize"),   ex_resize,      E_VIONLY,
+           "c+",
+           "resize [+-]rows",
+           "grow or shrink the current screen"},
+/* C_REWIND */
+       {L("rewind"),   ex_rew,         0,
+           "!",
+           "rew[ind][!]",
+           "re-edit all the files in the file argument list"},
+#ifdef GTAGS
+/* C_RTAG */
+       {L("rtag"),     ex_rtag_push,   E_NEWSCREEN,
+           "!w1o",
+           "rta[g][!] [string]",
+           "edit the file containing the tag"},
+#endif
+/*
+ * !!!
+ * Adding new commands starting with 's' may break the substitute command code
+ * in ex_cmd() (the ex parser).  Read through the comments there, first.
+ */
+/* C_SUBSTITUTE */
+       {L("s"),                ex_s,           E_ADDR2|E_ADDR_ZERO,
+           "s",
+           "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]",
+           "substitute on lines matching an RE"},
+/* C_SCRIPT */
+       {L("script"),   ex_script,      E_SECURE,
+           "!f1o",
+           "sc[ript][!] [file]",
+           "run a shell in a screen"},
+/* C_SET */
+       {L("set"),              ex_set,         0,
+           "wN",
+           "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]",
+           "set options (use \":set all\" to see all options)"},
+/* C_SHELL */
+       {L("shell"),    ex_shell,       E_SECURE,
+           "",
+           "sh[ell]",
+           "suspend editing and run a shell"},
+/* C_SOURCE */
+       {L("source"),   ex_source,      0,
+           "f1r",
+           "so[urce] file",
+           "read a file of ex commands"},
+/* C_STOP */
+       {L("stop"),     ex_stop,        E_SECURE,
+           "!",
+           "st[op][!]",
+           "suspend the edit session"},
+/* C_SUSPEND */
+       {L("suspend"),  ex_stop,        E_SECURE,
+           "!",
+           "su[spend][!]",
+           "suspend the edit session"},
+/* C_T */
+       {L("t"),                ex_copy,        E_ADDR2|E_AUTOPRINT,
+           "l1",
+           "[line [,line]] t line [flags]",
+           "copy lines elsewhere in the file"},
+/* C_TAG */
+       {L("tag"),              ex_tag_push,    E_NEWSCREEN,
+           "!w1o",
+           "[Tt]a[g][!] [string]",
+           "edit the file containing the tag"},
+/* C_TAGNEXT */
+       {L("tagnext"),  ex_tag_next,    0,
+           "!",
+           "tagn[ext][!]",
+           "move to the next tag"},
+/* C_TAGPOP */
+       {L("tagpop"),   ex_tag_pop,     0,
+           "!w1o",
+           "tagp[op][!] [number | file]",
+           "return to the previous group of tags"},
+/* C_TAGPREV */
+       {L("tagprev"),  ex_tag_prev,    0,
+           "!",
+           "tagpr[ev][!]",
+           "move to the previous tag"},
+/* C_TAGTOP */
+       {L("tagtop"),   ex_tag_top,     0,
+           "!",
+           "tagt[op][!]",
+           "discard all tags"},
+/* C_TCLCMD */
+       {L("tcl"),              ex_tcl,         E_ADDR2_ALL|E_ADDR_ZERO|
+                                           E_ADDR_ZERODEF|E_SECURE,
+           "s",
+           "tc[l] cmd",
+           "run the tcl interpreter with the command"},
+/* C_UNDO */
+       {L("undo"),     ex_undo,        E_AUTOPRINT,
+           "",
+           "u[ndo]",
+           "undo the most recent change"},
+/* C_UNABBREVIATE */
+       {L("unabbreviate"),ex_unabbr,   0,
+           "w1r",
+           "una[bbrev] word",
+           "delete an abbreviation"},
+/* C_UNMAP */
+       {L("unmap"),    ex_unmap,       0,
+           "!w1r",
+           "unm[ap][!] word",
+           "delete an input or command map"},
+/* C_V */
+       {L("v"),                ex_v,           E_ADDR2_ALL,
+           "s",
+           "[line [,line]] v [;/]RE[;/] [commands]",
+           "execute a global command on lines NOT matching an RE"},
+/* C_VERSION */
+       {L("version"),  ex_version,     0,
+           "",
+           "version",
+           "display the program version information"},
+/* C_VISUAL_EX */
+       {L("visual"),   ex_visual,      E_ADDR1|E_ADDR_ZERODEF,
+           "2c11",
+           "[line] vi[sual] [-|.|+|^] [window_size] [flags]",
+           "enter visual (vi) mode from ex mode"},
+/* C_VISUAL_VI */
+       {L("visual"),   ex_edit,        E_NEWSCREEN,
+           "f1o",
+           "[Vv]i[sual][!] [+cmd] [file]",
+           "edit another file (from vi mode only)"},
+/* C_VIUSAGE */
+       {L("viusage"),  ex_viusage,     0,
+           "w1o",
+           "[viu]sage [key]",
+           "display vi key usage statement"},
+/* C_VSPLIT */
+       {L("vsplit"),   ex_edit,        E_VIONLY,
+           "f1o",
+           "vs[plit] [+cmd] [file]",
+           "split the current screen vertically"},
+/* C_WRITE */
+       {L("write"),    ex_write,       E_ADDR2_ALL|E_ADDR_ZERODEF,
+           "!s",
+           "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]",
+           "write the file"},
+/* C_WN */
+       {L("wn"),               ex_wn,          E_ADDR2_ALL|E_ADDR_ZERODEF,
+           "!s",
+           "[line [,line]] wn[!] [>>] [file]",
+           "write the file and switch to the next file"},
+/* C_WQ */
+       {L("wq"),               ex_wq,          E_ADDR2_ALL|E_ADDR_ZERODEF,
+           "!s",
+           "[line [,line]] wq[!] [>>] [file]",
+           "write the file and exit"},
+/* C_XIT */
+       {L("xit"),              ex_xit,         E_ADDR2_ALL|E_ADDR_ZERODEF,
+           "!f1o",
+           "[line [,line]] x[it][!] [file]",
+           "exit"},
+/* C_YANK */
+       {L("yank"),     ex_yank,        E_ADDR2,
+           "bca",
+           "[line [,line]] ya[nk] [buffer] [count]",
+           "copy lines to a cut buffer"},
+/* C_Z */
+       {L("z"),                ex_z,           E_ADDR1,
+           "3c01",
+           "[line] z [-|.|+|^|=] [count] [flags]",
+           "display different screens of the file"},
+/* C_SUBTILDE */
+       {L("~"),                ex_subtilde,    E_ADDR2|E_ADDR_ZERO,
+           "s",
+           "[line [,line]] ~ [cgr] [count] [#lp]",
+           "replace previous RE with previous replacement string,"},
+       {NULL,                  NULL,           0,
+            NULL,
+            NULL,
+            NULL,},
+};
diff --git a/dist/nvi/ex/ex_cscope.c b/dist/nvi/ex/ex_cscope.c
new file mode 100644 (file)
index 0000000..cf39649
--- /dev/null
@@ -0,0 +1,1042 @@
+/*     $NetBSD: ex_cscope.c,v 1.8 2011/06/22 03:57:46 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1994, 1996
+ *     Rob Mayoff.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_cscope.c,v 10.21 2003/11/05 17:11:54 skimo Exp (Berkeley) Date: 2003/11/05 17:11:54";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>         /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "pathnames.h"
+#include "tag.h"
+
+#define        CSCOPE_DBFILE           "cscope.out"
+#define        CSCOPE_PATHS            "cscope.tpath"
+
+/*
+ * 0name       find all uses of name
+ * 1name       find definition of name
+ * 2name       find all function calls made from name
+ * 3name       find callers of name
+ * 4string     find text string (cscope 12.9)
+ * 4name       find assignments to name (cscope 13.3)
+ * 5pattern    change pattern -- NOT USED
+ * 6pattern    find pattern
+ * 7name       find files with name as substring
+ * 8name       find files #including name
+ */
+#define        FINDHELP "\
+find c|d|e|f|g|i|s|t buffer|pattern\n\
+      c: find callers of name\n\
+      d: find all function calls made from name\n\
+      e: find pattern\n\
+      f: find files with name as substring\n\
+      g: find definition of name\n\
+      i: find files #including name\n\
+      s: find all uses of name\n\
+      t: find assignments to name"
+
+static int cscope_add __P((SCR *, EXCMD *, const CHAR_T *));
+static int cscope_find __P((SCR *, EXCMD*, const CHAR_T *));
+static int cscope_help __P((SCR *, EXCMD *, const CHAR_T *));
+static int cscope_kill __P((SCR *, EXCMD *, const CHAR_T *));
+static int cscope_reset __P((SCR *, EXCMD *, const CHAR_T *));
+
+typedef struct _cc {
+       const char       *name;
+       int     (*function) __P((SCR *, EXCMD *, const CHAR_T *));
+       const char       *help_msg;
+       const char       *usage_msg;
+} CC;
+
+static CC const cscope_cmds[] = {
+       { "add",   cscope_add,
+         "Add a new cscope database", "add file | directory" },
+       { "find",  cscope_find,
+         "Query the databases for a pattern", FINDHELP },
+       { "help",  cscope_help,
+         "Show help for cscope commands", "help [command]" },
+       { "kill",  cscope_kill,
+         "Kill a cscope connection", "kill number" },
+       { "reset", cscope_reset,
+         "Discard all current cscope connections", "reset" },
+       { NULL, NULL, NULL, NULL }
+};
+
+static TAGQ    *create_cs_cmd __P((SCR *, const char *, size_t *));
+static int      csc_help __P((SCR *, const char *));
+static void     csc_file __P((SCR *,
+                   CSC *, char *, char **, size_t *, int *));
+static int      get_paths __P((SCR *, CSC *));
+static CC const        *lookup_ccmd __P((const char *));
+static int      parse __P((SCR *, CSC *, TAGQ *, int *));
+static int      read_prompt __P((SCR *, CSC *));
+static int      run_cscope __P((SCR *, CSC *, const char *));
+static int      start_cscopes __P((SCR *, EXCMD *));
+static int      terminate __P((SCR *, CSC *, int));
+
+/*
+ * ex_cscope --
+ *     Perform an ex cscope.
+ *
+ * PUBLIC: int ex_cscope __P((SCR *, EXCMD *));
+ */
+int
+ex_cscope(SCR *sp, EXCMD *cmdp)
+{
+       CC const *ccp;
+       EX_PRIVATE *exp;
+       int i;
+       CHAR_T *cmd;
+       CHAR_T *p;
+       const char *np;
+       size_t nlen;
+
+       /* Initialize the default cscope directories. */
+       exp = EXP(sp);
+       if (!F_ISSET(exp, EXP_CSCINIT) && start_cscopes(sp, cmdp))
+               return (1);
+       F_SET(exp, EXP_CSCINIT);
+
+       /* Skip leading whitespace. */
+       for (p = cmdp->argv[0]->bp, i = cmdp->argv[0]->len; i > 0; --i, ++p)
+               if (!ISBLANK((UCHAR_T)*p))
+                       break;
+       if (i == 0)
+               goto usage;
+
+       /* Skip the command to any arguments. */
+       for (cmd = p; i > 0; --i, ++p)
+               if (ISBLANK((UCHAR_T)*p))
+                       break;
+       if (*p != '\0') {
+               *p++ = '\0';
+               for (; *p && ISBLANK((UCHAR_T)*p); ++p);
+       }
+
+       INT2CHAR(sp, cmd, STRLEN(cmd) + 1, np, nlen);
+       if ((ccp = lookup_ccmd(np)) == NULL) {
+usage:         msgq(sp, M_ERR, "309|Use \"cscope help\" for help");
+               return (1);
+       }
+
+       /* Call the underlying function. */
+       return (ccp->function(sp, cmdp, p));
+}
+
+/*
+ * start_cscopes --
+ *     Initialize the cscope package.
+ */
+static int
+start_cscopes(SCR *sp, EXCMD *cmdp)
+{
+       size_t blen, len;
+       char *bp, *cscopes, *p, *t;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /*
+        * EXTENSION #1:
+        *
+        * If the CSCOPE_DIRS environment variable is set, we treat it as a
+        * list of cscope directories that we're using, similar to the tags
+        * edit option.
+        *
+        * XXX
+        * This should probably be an edit option, although that implies that
+        * we start/stop cscope processes periodically, instead of once when
+        * the editor starts.
+        */
+       if ((cscopes = getenv("CSCOPE_DIRS")) == NULL)
+               return (0);
+       len = strlen(cscopes);
+       GET_SPACE_RETC(sp, bp, blen, len);
+       memcpy(bp, cscopes, len + 1);
+
+       for (cscopes = t = bp; (p = strsep(&t, "\t :")) != NULL;)
+               if (*p != '\0') {
+                       CHAR2INT(sp, p, strlen(p) + 1, wp, wlen);
+                       (void)cscope_add(sp, cmdp, wp);
+               }
+
+       FREE_SPACE(sp, bp, blen);
+       return (0);
+}
+
+/*
+ * cscope_add --
+ *     The cscope add command.
+ */
+static int
+cscope_add(SCR *sp, EXCMD *cmdp, const CHAR_T *dname)
+{
+       struct stat sb;
+       EX_PRIVATE *exp;
+       CSC *csc;
+       size_t len;
+       int cur_argc;
+       const char *dbname;
+       char path[MAXPATHLEN];
+       const char *np;
+       char *npp;
+       size_t nlen;
+
+       exp = EXP(sp);
+
+       /*
+        *  0 additional args: usage.
+        *  1 additional args: matched a file.
+        * >1 additional args: object, too many args.
+        */
+       cur_argc = cmdp->argc;
+       if (argv_exp2(sp, cmdp, dname, STRLEN(dname))) {
+               return (1);
+       }
+       if (cmdp->argc == cur_argc) {
+               (void)csc_help(sp, "add");
+               return (1);
+       }
+       if (cmdp->argc == cur_argc + 1)
+               dname = cmdp->argv[cur_argc]->bp;
+       else {
+               ex_emsg(sp, np, EXM_FILECOUNT);
+               return (1);
+       }
+
+       INT2CHAR(sp, dname, STRLEN(dname)+1, np, nlen);
+
+       /*
+        * The user can specify a specific file (so they can have multiple
+        * Cscope databases in a single directory) or a directory.  If the
+        * file doesn't exist, we're done.  If it's a directory, append the
+        * standard database file name and try again.  Store the directory
+        * name regardless so that we can use it as a base for searches.
+        */
+       if (stat(np, &sb)) {
+               msgq(sp, M_SYSERR, "%s", np);
+               return (1);
+       }
+       if (S_ISDIR(sb.st_mode)) {
+               (void)snprintf(path, sizeof(path),
+                   "%s/%s", np, CSCOPE_DBFILE);
+               if (stat(path, &sb)) {
+                       msgq(sp, M_SYSERR, "%s", path);
+                       return (1);
+               }
+               dbname = CSCOPE_DBFILE;
+       } else if ((npp = strrchr(np, '/')) != NULL) {
+               *npp = '\0';
+               dbname = npp + 1;
+       } else {
+               dbname = np;
+               np = ".";
+       }
+
+       /* Allocate a cscope connection structure and initialize its fields. */
+       len = strlen(np);
+       CALLOC_RET(sp, csc, CSC *, 1, sizeof(CSC) + len);
+       csc->dname = csc->buf;
+       csc->dlen = len;
+       memcpy(csc->dname, np, len);
+       csc->mtime = sb.st_mtime;
+
+       /* Get the search paths for the cscope. */
+       if (get_paths(sp, csc))
+               goto err;
+
+       /* Start the cscope process. */
+       if (run_cscope(sp, csc, dbname))
+               goto err;
+
+       /*
+        * Add the cscope connection to the screen's list.  From now on, 
+        * on error, we have to call terminate, which expects the csc to
+        * be on the chain.
+        */
+       LIST_INSERT_HEAD(&exp->cscq, csc, q);
+
+       /* Read the initial prompt from the cscope to make sure it's okay. */
+       return read_prompt(sp, csc);
+
+err:   free(csc);
+       return (1);
+}
+
+/*
+ * get_paths --
+ *     Get the directories to search for the files associated with this
+ *     cscope database.
+ */
+static int
+get_paths(SCR *sp, CSC *csc)
+{
+       struct stat sb;
+       int fd, nentries;
+       size_t len;
+       char *p, **pathp, buf[MAXPATHLEN * 2];
+
+       /*
+        * EXTENSION #2:
+        *
+        * If there's a cscope directory with a file named CSCOPE_PATHS, it
+        * contains a colon-separated list of paths in which to search for
+        * files returned by cscope.
+        *
+        * XXX
+        * These paths are absolute paths, and not relative to the cscope
+        * directory.  To fix this, rewrite the each path using the cscope
+        * directory as a prefix.
+        */
+       (void)snprintf(buf, sizeof(buf), "%s/%s", csc->dname, CSCOPE_PATHS);
+       if (stat(buf, &sb) == 0) {
+               /* Read in the CSCOPE_PATHS file. */
+               len = sb.st_size;
+               MALLOC_RET(sp, csc->pbuf, char *, len + 1);
+               if ((fd = open(buf, O_RDONLY, 0)) < 0 ||
+                   (size_t)read(fd, csc->pbuf, len) != len) {
+                        msgq_str(sp, M_SYSERR, buf, "%s");
+                        if (fd >= 0)
+                               (void)close(fd);
+                        return (1);
+               }
+               (void)close(fd);
+               csc->pbuf[len] = '\0';
+
+               /* Count up the entries. */
+               for (nentries = 0, p = csc->pbuf; *p != '\0'; ++p)
+                       if (p[0] == ':' && p[1] != '\0')
+                               ++nentries;
+
+               /* Build an array of pointers to the paths. */
+               CALLOC_GOTO(sp,
+                   csc->paths, char **, nentries + 1, sizeof(char **));
+               for (pathp = csc->paths, p = strtok(csc->pbuf, ":");
+                   p != NULL; p = strtok(NULL, ":"))
+                       *pathp++ = p;
+               return (0);
+       }
+
+       /*
+        * If the CSCOPE_PATHS file doesn't exist, we look for files
+        * relative to the cscope directory.
+        */
+       if ((csc->pbuf = strdup(csc->dname)) == NULL) {
+               msgq(sp, M_SYSERR, NULL);
+               return (1);
+       }
+       CALLOC_GOTO(sp, csc->paths, char **, 2, sizeof(char *));
+       csc->paths[0] = csc->pbuf;
+       return (0);
+
+alloc_err:
+       if (csc->pbuf != NULL) {
+               free(csc->pbuf);
+               csc->pbuf = NULL;
+       }
+       return (1);
+}
+
+/*
+ * run_cscope --
+ *     Fork off the cscope process.
+ */
+static int
+run_cscope(SCR *sp, CSC *csc, const char *dbname)
+{
+       int to_cs[2], from_cs[2];
+       char cmd[MAXPATHLEN * 2];
+
+       /*
+        * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
+        * from_cs[0] and writes to to_cs[1].
+        */
+       to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1;
+       if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
+               msgq(sp, M_SYSERR, "pipe");
+               goto err;
+       }
+       switch (csc->pid = vfork()) {
+       case -1:
+               msgq(sp, M_SYSERR, "vfork");
+err:           if (to_cs[0] != -1)
+                       (void)close(to_cs[0]);
+               if (to_cs[1] != -1)
+                       (void)close(to_cs[1]);
+               if (from_cs[0] != -1)
+                       (void)close(from_cs[0]);
+               if (from_cs[1] != -1)
+                       (void)close(from_cs[1]);
+               return (1);
+       case 0:                         /* child: run cscope. */
+               (void)dup2(to_cs[0], STDIN_FILENO);
+               (void)dup2(from_cs[1], STDOUT_FILENO);
+               (void)dup2(from_cs[1], STDERR_FILENO);
+
+               /* Close unused file descriptors. */
+               (void)close(to_cs[1]);
+               (void)close(from_cs[0]);
+
+               /* Run the cscope command. */
+#define        CSCOPE_CMD_FMT          "cd '%s' && exec cscope -dl -f %s"
+               (void)snprintf(cmd, sizeof(cmd),
+                   CSCOPE_CMD_FMT, csc->dname, dbname);
+               (void)execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL);
+               msgq_str(sp, M_SYSERR, cmd, "execl: %s");
+               _exit (127);
+               /* NOTREACHED */
+       default:                        /* parent. */
+               /* Close unused file descriptors. */
+               (void)close(to_cs[0]);
+               (void)close(from_cs[1]);
+
+               /*
+                * Save the file descriptors for later duplication, and
+                * reopen as streams.
+                */
+               csc->to_fd = to_cs[1];
+               csc->to_fp = fdopen(to_cs[1], "w");
+               csc->from_fd = from_cs[0];
+               csc->from_fp = fdopen(from_cs[0], "r");
+               break;
+       }
+       return (0);
+}
+
+/*
+ * cscope_find --
+ *     The cscope find command.
+ */
+static int
+cscope_find(SCR *sp, EXCMD *cmdp, const CHAR_T *pattern)
+{
+       CSC *csc, *csc_next;
+       EX_PRIVATE *exp;
+       FREF *frp;
+       TAGQ *rtqp, *tqp;
+       TAG *rtp;
+       db_recno_t lno;
+       size_t cno, search;
+       int force, istmp, matches;
+       const char *np = NULL;
+       size_t nlen;
+
+       exp = EXP(sp);
+
+       /* Check for connections. */
+       if (exp->cscq.lh_first == NULL) {
+               msgq(sp, M_ERR, "310|No cscope connections running");
+               return (1);
+       }
+
+       /*
+        * Allocate all necessary memory before doing anything hard.  If the
+        * tags stack is empty, we'll need the `local context' TAGQ structure
+        * later.
+        */
+       rtp = NULL;
+       rtqp = NULL;
+       if (exp->tq.cqh_first == (void *)&exp->tq) {
+               /* Initialize the `local context' tag queue structure. */
+               CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
+               CIRCLEQ_INIT(&rtqp->tagq);
+
+               /* Initialize and link in its tag structure. */
+               CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
+               CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
+               rtqp->current = rtp; 
+       }
+
+       /* Create the cscope command. */
+       INT2CHAR(sp, pattern, STRLEN(pattern) + 1, np, nlen);
+       np = strdup(np);
+       if ((tqp = create_cs_cmd(sp, np, &search)) == NULL)
+               goto err;
+
+       /*
+        * Stick the current context in a convenient place, we'll lose it
+        * when we switch files.
+        */
+       frp = sp->frp;
+       lno = sp->lno;
+       cno = sp->cno;
+       istmp = F_ISSET(sp->frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN);
+
+       /* Search all open connections for a match. */
+       matches = 0;
+       for (csc = exp->cscq.lh_first; csc != NULL; csc = csc_next) {
+               /* Copy csc->q.lh_next here in case csc is killed. */
+               csc_next = csc->q.le_next;
+
+               /*
+                * Send the command to the cscope program.  (We skip the
+                * first two bytes of the command, because we stored the
+                * search cscope command character and a leading space
+                * there.)
+                */
+               (void)fprintf(csc->to_fp, "%zu%s\n", search, tqp->tag + 2);
+               (void)fflush(csc->to_fp);
+
+               /* Read the output. */
+               if (parse(sp, csc, tqp, &matches)) {
+                       if (rtqp != NULL)
+                               free(rtqp);
+                       tagq_free(sp, tqp);
+                       return (1);
+               }
+       }
+
+       if (matches == 0) {
+               msgq(sp, M_INFO, "278|No matches for query");
+               return (0);
+       }
+
+       tqp->current = tqp->tagq.cqh_first;
+
+       /* Try to switch to the first tag. */
+       force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+       if (F_ISSET(cmdp, E_NEWSCREEN)) {
+               if (ex_tag_Nswitch(sp, tqp->current, force))
+                       goto err;
+
+               /* Everything else gets done in the new screen. */
+               sp = sp->nextdisp;
+               exp = EXP(sp);
+       } else
+               if (ex_tag_nswitch(sp, tqp->current, force))
+                       goto err;
+
+       /*
+        * If this is the first tag, put a `current location' queue entry
+        * in place, so we can pop all the way back to the current mark.
+        * Note, it doesn't point to much of anything, it's a placeholder.
+        */
+       if (exp->tq.cqh_first == (void *)&exp->tq) {
+               CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
+       } else
+               rtqp = exp->tq.cqh_first;
+
+       /* Link the current TAGQ structure into place. */
+       CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
+
+       (void)cscope_search(sp, tqp, tqp->current);
+
+       /*
+        * Move the current context from the temporary save area into the
+        * right structure.
+        *
+        * If we were in a temporary file, we don't have a context to which
+        * we can return, so just make it be the same as what we're moving
+        * to.  It will be a little odd that ^T doesn't change anything, but
+        * I don't think it's a big deal.
+        */
+       if (istmp) {
+               rtqp->current->frp = sp->frp;
+               rtqp->current->lno = sp->lno;
+               rtqp->current->cno = sp->cno;
+       } else {
+               rtqp->current->frp = frp;
+               rtqp->current->lno = lno;
+               rtqp->current->cno = cno;
+       }
+
+       return (0);
+
+err:
+alloc_err:
+       if (rtqp != NULL)
+               free(rtqp);
+       if (rtp != NULL)
+               free(rtp);
+       if (np != NULL)
+               free(__UNCONST(np));
+       return (1);
+}
+
+/*
+ * create_cs_cmd --
+ *     Build a cscope command, creating and initializing the base TAGQ.
+ */
+static TAGQ *
+create_cs_cmd(SCR *sp, const char *pattern, size_t *searchp)
+{
+       CB *cbp;
+       TAGQ *tqp;
+       size_t tlen;
+       const char *p;
+
+       /*
+        * Cscope supports a "change pattern" command which we never use,
+        * cscope command 5.  Set CSCOPE_QUERIES[5] to " " since the user
+        * can't pass " " as the first character of pattern.  That way the
+        * user can't ask for pattern 5 so we don't need any special-case
+        * code.
+        */
+#define        CSCOPE_QUERIES          "sgdct efi"
+
+       if (pattern == NULL)
+               goto usage;
+
+       /* Skip leading blanks, check for command character. */
+       for (; isblank((unsigned char)pattern[0]); ++pattern);
+       if (pattern[0] == '\0' || !isblank((unsigned char)pattern[1]))
+               goto usage;
+       for (*searchp = 0, p = CSCOPE_QUERIES;
+           *p != '\0' && *p != pattern[0]; ++*searchp, ++p);
+       if (*p == '\0') {
+               msgq(sp, M_ERR,
+                   "311|%s: unknown search type: use one of %s",
+                   KEY_NAME(sp, pattern[0]), CSCOPE_QUERIES);
+               return (NULL);
+       }
+
+       /* Skip <blank> characters to the pattern. */
+       for (p = pattern + 1; *p != '\0' && isblank((unsigned char)*p); ++p);
+       if (*p == '\0') {
+usage:         (void)csc_help(sp, "find");
+               return (NULL);
+       }
+
+       /* The user can specify the contents of a buffer as the pattern. */
+       cbp = NULL;
+       if (p[0] == '"' && p[1] != '\0' && p[2] == '\0')
+               CBNAME(sp, cbp, p[1]);
+       if (cbp != NULL) {
+               INT2CHAR(sp, cbp->textq.cqh_first->lb,
+                       cbp->textq.cqh_first->len, p, tlen);
+       } else
+               tlen = strlen(p);
+
+       /* Allocate and initialize the TAGQ structure. */
+       CALLOC(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + tlen + 3);
+       if (tqp == NULL)
+               return (NULL);
+       CIRCLEQ_INIT(&tqp->tagq);
+       tqp->tag = tqp->buf;
+       tqp->tag[0] = pattern[0];
+       tqp->tag[1] = ' ';
+       tqp->tlen = tlen + 2;
+       memcpy(tqp->tag + 2, p, tlen);
+       tqp->tag[tlen + 2] = '\0';
+       F_SET(tqp, TAG_CSCOPE);
+
+       return (tqp);
+}
+
+/*
+ * parse --
+ *     Parse the cscope output.
+ */
+static int
+parse(SCR *sp, CSC *csc, TAGQ *tqp, int *matchesp)
+{
+       TAG *tp;
+       db_recno_t slno = 0;
+       size_t dlen, nlen = 0, slen = 0;
+       int ch, i, isolder = 0, nlines;
+       char *dname = NULL, *name = NULL, *search, *p, *t, dummy[2], buf[2048];
+
+       for (;;) {
+               if (!fgets(buf, sizeof(buf), csc->from_fp))
+                       goto io_err;
+
+               /*
+                * If the database is out of date, or there's some other
+                * problem, cscope will output error messages before the
+                * number-of-lines output.  Display/discard any output
+                * that doesn't match what we want.
+                */
+#define        CSCOPE_NLINES_FMT       "cscope: %d lines%1[\n]"
+               if (sscanf(buf, CSCOPE_NLINES_FMT, &nlines, dummy) == 2)
+                       break;
+               if ((p = strchr(buf, '\n')) != NULL)
+                       *p = '\0';
+               msgq(sp, M_ERR, "%s: \"%s\"", csc->dname, buf);
+       }
+
+       while (nlines--) {
+               if (fgets(buf, sizeof(buf), csc->from_fp) == NULL)
+                       goto io_err;
+
+               /* If the line's too long for the buffer, discard it. */
+               if ((p = strchr(buf, '\n')) == NULL) {
+                       while ((ch = getc(csc->from_fp)) != EOF && ch != '\n');
+                       continue;
+               }
+               *p = '\0';
+
+               /*
+                * The cscope output is in the following format:
+                *
+                *      <filename> <context> <line number> <pattern>
+                *
+                * Figure out how long everything is so we can allocate in one
+                * swell foop, but discard anything that looks wrong.
+                */
+               for (p = buf, i = 0;
+                   i < 3 && (t = strsep(&p, "\t ")) != NULL; ++i)
+                       switch (i) {
+                       case 0:                 /* Filename. */
+                               name = t;
+                               nlen = strlen(name);
+                               break;
+                       case 1:                 /* Context. */
+                               break;
+                       case 2:                 /* Line number. */
+                               slno = (db_recno_t)atol(t);
+                               break;
+                       }
+               if (i != 3 || p == NULL || t == NULL)
+                       continue;
+
+               /* The rest of the string is the search pattern. */
+               search = p;
+               slen = strlen(p);
+
+               /* Resolve the file name. */
+               csc_file(sp, csc, name, &dname, &dlen, &isolder);
+
+               /*
+                * If the file is older than the cscope database, that is,
+                * the database was built since the file was last modified,
+                * or there wasn't a search string, use the line number.
+                */
+               if (isolder || strcmp(search, "<unknown>") == 0) {
+                       search = NULL;
+                       slen = 0;
+               }
+
+               /*
+                * Allocate and initialize a tag structure plus the variable
+                * length cscope information that follows it.
+                */
+               CALLOC_RET(sp, tp,
+                   TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + slen + 1);
+               tp->fname = (char *)tp->buf;
+               if (dlen != 0) {
+                       memcpy(tp->fname, dname, dlen);
+                       tp->fname[dlen] = '/';
+                       ++dlen;
+               }
+               memcpy(tp->fname + dlen, name, nlen + 1);
+               tp->fnlen = dlen + nlen;
+               tp->slno = slno;
+               if (slen != 0) {
+                       tp->search = (CHAR_T*)(tp->fname + tp->fnlen + 1);
+                       MEMCPYW(tp->search, search, (tp->slen = slen) + 1);
+               }
+               CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+
+               ++*matchesp;
+       }
+
+       return read_prompt(sp, csc);
+
+io_err:        if (feof(csc->from_fp))
+               errno = EIO;
+       msgq_str(sp, M_SYSERR, "%s", csc->dname);
+       terminate(sp, csc, 0);
+       return (1);
+}
+
+/*
+ * csc_file --
+ *     Search for the right path to this file.
+ */
+static void
+csc_file(SCR *sp, CSC *csc, char *name, char **dirp, size_t *dlenp, int *isolderp)
+{
+       struct stat sb;
+       char **pp, buf[MAXPATHLEN];
+
+       /*
+        * Check for the file in all of the listed paths.  If we don't
+        * find it, we simply return it unchanged.  We have to do this
+        * now, even though it's expensive, because if the user changes
+        * directories, we can't change our minds as to where the file
+        * lives.
+        */
+       for (pp = csc->paths; *pp != NULL; ++pp) {
+               (void)snprintf(buf, sizeof(buf), "%s/%s", *pp, name);
+               if (stat(buf, &sb) == 0) {
+                       *dirp = *pp;
+                       *dlenp = strlen(*pp);
+                       *isolderp = sb.st_mtime < csc->mtime;
+                       return;
+               }
+       }
+       *dlenp = 0;
+}
+
+/*
+ * cscope_help --
+ *     The cscope help command.
+ */
+static int
+cscope_help(SCR *sp, EXCMD *cmdp, const CHAR_T *subcmd)
+{
+       const char *np;
+       size_t nlen;
+
+       INT2CHAR(sp, subcmd, STRLEN(subcmd) + 1, np, nlen);
+       return (csc_help(sp, np));
+}
+
+/*
+ * csc_help --
+ *     Display help/usage messages.
+ */
+static int
+csc_help(SCR *sp, const char *cmd)
+{
+       CC const *ccp;
+
+       if (cmd != NULL && *cmd != '\0') {
+               if ((ccp = lookup_ccmd(cmd)) == NULL) {
+                       ex_printf(sp,
+                           "%s doesn't match any cscope command\n", cmd);
+                       return (1);
+               } else {
+                       ex_printf(sp,
+                         "Command: %s (%s)\n", ccp->name, ccp->help_msg);
+                       ex_printf(sp, "  Usage: %s\n", ccp->usage_msg);
+                       return (0);
+               }
+       }
+
+       ex_printf(sp, "cscope commands:\n");
+       for (ccp = cscope_cmds; ccp->name != NULL; ++ccp)
+               ex_printf(sp, "  %*s: %s\n", 5, ccp->name, ccp->help_msg);
+       return (0);
+}
+
+/*
+ * cscope_kill --
+ *     The cscope kill command.
+ */
+static int
+cscope_kill(SCR *sp, EXCMD *cmdp, const CHAR_T *cn)
+{
+       const char *np;
+       size_t nlen;
+
+       INT2CHAR(sp, cn, STRLEN(cn) + 1, np, nlen);
+       return (terminate(sp, NULL, atoi(np)));
+}
+
+/*
+ * terminate --
+ *     Detach from a cscope process.
+ */
+static int
+terminate(SCR *sp, CSC *csc, int n)
+{
+       EX_PRIVATE *exp;
+       int i, pstat;
+
+       exp = EXP(sp);
+
+       /*
+        * We either get a csc structure or a number.  If not provided a
+        * csc structure, find the right one.
+        */
+       if (csc == NULL) {
+               if (n < 1)
+                       goto badno;
+               for (i = 1, csc = exp->cscq.lh_first;
+                   csc != NULL; csc = csc->q.le_next, i++)
+                       if (i == n)
+                               break;
+               if (csc == NULL) {
+badno:                 msgq(sp, M_ERR, "312|%d: no such cscope session", n);
+                       return (1);
+               }
+       }
+
+       /*
+        * XXX
+        * Theoretically, we have the only file descriptors to the process,
+        * so closing them should let it exit gracefully, deleting temporary
+        * files, etc.  The original vi cscope integration sent the cscope
+        * connection a SIGTERM signal, so I'm not sure if closing the file
+        * descriptors is sufficient.
+        */
+       if (csc->from_fp != NULL)
+               (void)fclose(csc->from_fp);
+       if (csc->to_fp != NULL)
+               (void)fclose(csc->to_fp);
+       (void)waitpid(csc->pid, &pstat, 0);
+
+       /* Discard cscope connection information. */
+       LIST_REMOVE(csc, q);
+       if (csc->pbuf != NULL)
+               free(csc->pbuf);
+       if (csc->paths != NULL)
+               free(csc->paths);
+       free(csc);
+       return (0);
+}
+
+/*
+ * cscope_reset --
+ *     The cscope reset command.
+ */
+static int
+cscope_reset(SCR *sp, EXCMD *cmdp, const CHAR_T *notusedp)
+{
+       EX_PRIVATE *exp;
+
+       for (exp = EXP(sp); exp->cscq.lh_first != NULL;) {
+               static CHAR_T one[] = {'1', 0};
+               if (cscope_kill(sp, cmdp, one))
+                       return (1);
+       }
+       return (0);
+}
+
+/*
+ * cscope_display --
+ *     Display current connections.
+ *
+ * PUBLIC: int cscope_display __P((SCR *));
+ */
+int
+cscope_display(SCR *sp)
+{
+       EX_PRIVATE *exp;
+       CSC *csc;
+       int i;
+
+       exp = EXP(sp);
+       if (exp->cscq.lh_first == NULL) {
+               ex_printf(sp, "No cscope connections.\n");
+               return (0);
+       }
+       for (i = 1,
+           csc = exp->cscq.lh_first; csc != NULL; ++i, csc = csc->q.le_next)
+               ex_printf(sp,
+                   "%2d %s (process %lu)\n", i, csc->dname, (u_long)csc->pid);
+       return (0);
+}
+
+/*
+ * cscope_search --
+ *     Search a file for a cscope entry.
+ *
+ * PUBLIC: int cscope_search __P((SCR *, TAGQ *, TAG *));
+ */
+int
+cscope_search(SCR *sp, TAGQ *tqp, TAG *tp)
+{
+       MARK m;
+
+       /* If we don't have a search pattern, use the line number. */
+       if (tp->search == NULL) {
+               if (!db_exist(sp, tp->slno)) {
+                       tag_msg(sp, TAG_BADLNO, tqp->tag);
+                       return (1);
+               }
+               m.lno = tp->slno;
+       } else {
+               /*
+                * Search for the tag; cheap fallback for C functions
+                * if the name is the same but the arguments have changed.
+                */
+               m.lno = 1;
+               m.cno = 0;
+               if (f_search(sp, &m, &m,
+                   tp->search, tp->slen, NULL, SEARCH_CSCOPE | SEARCH_FIRST)) {
+                       tag_msg(sp, TAG_SEARCH, tqp->tag);
+                       return (1);
+               }
+
+               /*
+                * !!!
+                * Historically, tags set the search direction if it wasn't
+                * already set.
+                */
+               if (sp->searchdir == NOTSET)
+                       sp->searchdir = FORWARD;
+       }
+
+       /*
+        * !!!
+        * Tags move to the first non-blank, NOT the search pattern start.
+        */
+       sp->lno = m.lno;
+       sp->cno = 0;
+       (void)nonblank(sp, sp->lno, &sp->cno);
+       return (0);
+}
+
+
+/*
+ * lookup_ccmd --
+ *     Return a pointer to the command structure.
+ */
+static CC const *
+lookup_ccmd(const char *name)
+{
+       CC const *ccp;
+       size_t len;
+
+       len = strlen(name);
+       for (ccp = cscope_cmds; ccp->name != NULL; ++ccp)
+               if (strncmp(name, ccp->name, len) == 0)
+                       return (ccp);
+       return (NULL);
+}
+
+/*
+ * read_prompt --
+ *     Read a prompt from cscope.
+ */
+static int
+read_prompt(SCR *sp, CSC *csc)
+{
+       int ch;
+
+#define        CSCOPE_PROMPT           ">> "
+       for (;;) {
+               while ((ch =
+                   getc(csc->from_fp)) != EOF && ch != CSCOPE_PROMPT[0]);
+               if (ch == EOF) {
+                       terminate(sp, csc, 0);
+                       return (1);
+               }
+               if (getc(csc->from_fp) != CSCOPE_PROMPT[1])
+                       continue;
+               if (getc(csc->from_fp) != CSCOPE_PROMPT[2])
+                       continue;
+               break;
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_def.h b/dist/nvi/ex/ex_def.h
new file mode 100644 (file)
index 0000000..8854f4b
--- /dev/null
@@ -0,0 +1,83 @@
+/*     $NetBSD: ex_def.h,v 1.2 2008/10/29 17:50:49 christos Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+#define C_SCROLL 0
+#define C_BANG 1
+#define C_HASH 2
+#define C_SUBAGAIN 3
+#define C_STAR 4
+#define C_SHIFTL 5
+#define C_EQUAL 6
+#define C_SHIFTR 7
+#define C_AT 8
+#define C_APPEND 9
+#define C_ABBR 10
+#define C_ARGS 11
+#define C_BG 12
+#define C_CHANGE 13
+#define C_CD 14
+#define C_CHDIR 15
+#define C_COPY 16
+#define C_CSCOPE 17
+#define C_DELETE 18
+#define C_DISPLAY 19
+#define C_EDIT 20
+#define C_EX 21
+#define C_EXUSAGE 22
+#define C_FILE 23
+#define C_FG 24
+#define C_GLOBAL 25
+#define C_HELP 26
+#define C_INSERT 27
+#define C_JOIN 28
+#define C_K 29
+#define C_LIST 30
+#define C_MOVE 31
+#define C_MARK 32
+#define C_MAP 33
+#define C_MKEXRC 34
+#define C_NEXT 35
+#define C_NUMBER 36
+#define C_OPEN 37
+#define C_PRINT 38
+#define C_PERLCMD 39
+#define C_PERLDOCMD 40
+#define C_PRESERVE 41
+#define C_PREVIOUS 42
+#define C_PUT 43
+#define C_QUIT 44
+#define C_READ 45
+#define C_RECOVER 46
+#define C_RESIZE 47
+#define C_REWIND 48
+#define C_RTAG 49
+#define C_SUBSTITUTE 50
+#define C_SCRIPT 51
+#define C_SET 52
+#define C_SHELL 53
+#define C_SOURCE 54
+#define C_STOP 55
+#define C_SUSPEND 56
+#define C_T 57
+#define C_TAG 58
+#define C_TAGNEXT 59
+#define C_TAGPOP 60
+#define C_TAGPREV 61
+#define C_TAGTOP 62
+#define C_TCLCMD 63
+#define C_UNDO 64
+#define C_UNABBREVIATE 65
+#define C_UNMAP 66
+#define C_V 67
+#define C_VERSION 68
+#define C_VISUAL_EX 69
+#define C_VISUAL_VI 70
+#define C_VIUSAGE 71
+#define C_VSPLIT 72
+#define C_WRITE 73
+#define C_WN 74
+#define C_WQ 75
+#define C_XIT 76
+#define C_YANK 77
+#define C_Z 78
+#define C_SUBTILDE 79
diff --git a/dist/nvi/ex/ex_delete.c b/dist/nvi/ex/ex_delete.c
new file mode 100644 (file)
index 0000000..9d8e149
--- /dev/null
@@ -0,0 +1,65 @@
+/*     $NetBSD: ex_delete.c,v 1.1.1.2 2008/05/18 14:31:14 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_delete.c,v 10.11 2001/06/25 15:19:15 skimo Exp (Berkeley) Date: 2001/06/25 15:19:15";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_delete: [line [,line]] d[elete] [buffer] [count] [flags]
+ *
+ *     Delete lines from the file.
+ *
+ * PUBLIC: int ex_delete __P((SCR *, EXCMD *));
+ */
+int
+ex_delete(SCR *sp, EXCMD *cmdp)
+{
+       db_recno_t lno;
+
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * !!!
+        * Historically, lines deleted in ex were not placed in the numeric
+        * buffers.  We follow historic practice so that we don't overwrite
+        * vi buffers accidentally.
+        */
+       if (cut(sp,
+           FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
+           &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
+               return (1);
+
+       /* Delete the lines. */
+       if (del(sp, &cmdp->addr1, &cmdp->addr2, 1))
+               return (1);
+
+       /* Set the cursor to the line after the last line deleted. */
+       sp->lno = cmdp->addr1.lno;
+
+       /* Or the last line in the file if deleted to the end of the file. */
+       if (db_last(sp, &lno))
+               return (1);
+       if (sp->lno > lno)
+               sp->lno = lno;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_display.c b/dist/nvi/ex/ex_display.c
new file mode 100644 (file)
index 0000000..1ef1c6e
--- /dev/null
@@ -0,0 +1,142 @@
+/*     $NetBSD: ex_display.c,v 1.3 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_display.c,v 10.15 2001/06/25 15:19:15 skimo Exp (Berkeley) Date: 2001/06/25 15:19:15";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "tag.h"
+
+static int     bdisplay __P((SCR *));
+static void    db __P((SCR *, CB *, const char *));
+
+/*
+ * ex_display -- :display b[uffers] | c[onnections] | s[creens] | t[ags]
+ *
+ *     Display cscope connections, buffers, tags or screens.
+ *
+ * PUBLIC: int ex_display __P((SCR *, EXCMD *));
+ */
+int
+ex_display(SCR *sp, EXCMD *cmdp)
+{
+       switch (cmdp->argv[0]->bp[0]) {
+       case 'b':
+#undef ARG
+#define        ARG     "buffers"
+               if (cmdp->argv[0]->len >= sizeof(ARG) ||
+                   memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+                       break;
+               return (bdisplay(sp));
+       case 'c':
+#undef ARG
+#define        ARG     "connections"
+               if (cmdp->argv[0]->len >= sizeof(ARG) ||
+                   memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+                       break;
+               return (cscope_display(sp));
+       case 's':
+#undef ARG
+#define        ARG     "screens"
+               if (cmdp->argv[0]->len >= sizeof(ARG) ||
+                   memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+                       break;
+               return (ex_sdisplay(sp));
+       case 't':
+#undef ARG
+#define        ARG     "tags"
+               if (cmdp->argv[0]->len >= sizeof(ARG) ||
+                   memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+                       break;
+               return (ex_tag_display(sp));
+       }
+       ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+       return (1);
+}
+
+/*
+ * bdisplay --
+ *
+ *     Display buffers.
+ */
+static int
+bdisplay(SCR *sp)
+{
+       CB *cbp;
+
+       if (sp->wp->cutq.lh_first == NULL && sp->wp->dcbp == NULL) {
+               msgq(sp, M_INFO, "123|No cut buffers to display");
+               return (0);
+       }
+
+       /* Display regular cut buffers. */
+       for (cbp = sp->wp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
+               if (ISDIGIT(cbp->name))
+                       continue;
+               if (cbp->textq.cqh_first != (void *)&cbp->textq)
+                       db(sp, cbp, NULL);
+               if (INTERRUPTED(sp))
+                       return (0);
+       }
+       /* Display numbered buffers. */
+       for (cbp = sp->wp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
+               if (!ISDIGIT(cbp->name))
+                       continue;
+               if (cbp->textq.cqh_first != (void *)&cbp->textq)
+                       db(sp, cbp, NULL);
+               if (INTERRUPTED(sp))
+                       return (0);
+       }
+       /* Display default buffer. */
+       if ((cbp = sp->wp->dcbp) != NULL)
+               db(sp, cbp, "default buffer");
+       return (0);
+}
+
+/*
+ * db --
+ *     Display a buffer.
+ */
+static void
+db(SCR *sp, CB *cbp, const char *np)
+{
+       CHAR_T *p;
+       GS *gp;
+       TEXT *tp;
+       size_t len;
+       const unsigned char *name = (const void *)np;
+
+       gp = sp->gp;
+       (void)ex_printf(sp, "********** %s%s\n",
+           name == NULL ? KEY_NAME(sp, cbp->name) : name,
+           F_ISSET(cbp, CB_LMODE) ? " (line mode)" : " (character mode)");
+       for (tp = cbp->textq.cqh_first;
+           tp != (void *)&cbp->textq; tp = tp->q.cqe_next) {
+               for (len = tp->len, p = tp->lb; len--; ++p) {
+                       (void)ex_puts(sp, (char *)KEY_NAME(sp, *p));
+                       if (INTERRUPTED(sp))
+                               return;
+               }
+               (void)ex_puts(sp, "\n");
+       }
+}
diff --git a/dist/nvi/ex/ex_edit.c b/dist/nvi/ex/ex_edit.c
new file mode 100644 (file)
index 0000000..af088f2
--- /dev/null
@@ -0,0 +1,155 @@
+/*     $NetBSD: ex_edit.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_edit.c,v 10.14 2001/08/28 13:29:15 skimo Exp (Berkeley) Date: 2001/08/28 13:29:15";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+static int ex_N_edit __P((SCR *, EXCMD *, FREF *, int));
+
+/*
+ * ex_edit --  :e[dit][!] [+cmd] [file]
+ *             :ex[!] [+cmd] [file]
+ *             :vi[sual][!] [+cmd] [file]
+ *
+ * Edit a file; if none specified, re-edit the current file.  The third
+ * form of the command can only be executed while in vi mode.  See the
+ * hack in ex.c:ex_cmd().
+ *
+ * !!!
+ * Historic vi didn't permit the '+' command form without specifying
+ * a file name as well.  This seems unreasonable, so we support it
+ * regardless.
+ *
+ * PUBLIC: int ex_edit __P((SCR *, EXCMD *));
+ */
+int
+ex_edit(SCR *sp, EXCMD *cmdp)
+{
+       FREF *frp;
+       int attach, setalt;
+       const char *np;
+       size_t nlen;
+
+       switch (cmdp->argc) {
+       case 0:
+               /*
+                * If the name has been changed, we edit that file, not the
+                * original name.  If the user was editing a temporary file
+                * (or wasn't editing any file), create another one.  The
+                * reason for not reusing temporary files is that there is
+                * special exit processing of them, and reuse is tricky.
+                */
+               frp = sp->frp;
+               if (sp->ep == NULL || F_ISSET(frp, FR_TMPFILE)) {
+                       if ((frp = file_add(sp, NULL)) == NULL)
+                               return (1);
+                       attach = 0;
+               } else
+                       attach = 1;
+               setalt = 0;
+               break;
+       case 1:
+               INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, 
+                        np, nlen);
+               if ((frp = file_add(sp, np)) == NULL)
+                       return (1);
+               attach = 0;
+               setalt = 1;
+               set_alt_name(sp, np);
+               break;
+       default:
+               abort();
+       }
+
+       if (F_ISSET(cmdp, E_NEWSCREEN) || cmdp->cmd == &cmds[C_VSPLIT])
+               return (ex_N_edit(sp, cmdp, frp, attach));
+
+       /*
+        * Check for modifications.
+        *
+        * !!!
+        * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit.
+        */
+       if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+               return (1);
+
+       /* Switch files. */
+       if (file_init(sp, frp, NULL, (setalt ? FS_SETALT : 0) |
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+               return (1);
+
+       F_SET(sp, SC_FSWITCH);
+       return (0);
+}
+
+/*
+ * ex_N_edit --
+ *     New screen version of ex_edit.
+ */
+static int
+ex_N_edit(SCR *sp, EXCMD *cmdp, FREF *frp, int attach)
+{
+       SCR *new;
+
+       /* Get a new screen. */
+       if (screen_init(sp->gp, sp, &new))
+               return (1);
+       if ((cmdp->cmd == &cmds[C_VSPLIT] && vs_vsplit(sp, new)) ||
+           (cmdp->cmd != &cmds[C_VSPLIT] && vs_split(sp, new, 0))) {
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* Get a backing file. */
+       if (attach) {
+               /* Copy file state, keep the screen and cursor the same. */
+               new->ep = sp->ep;
+               ++new->ep->refcnt;
+               CIRCLEQ_INSERT_HEAD(&new->ep->scrq, new, eq);
+
+               new->frp = frp;
+               new->frp->flags = sp->frp->flags;
+
+               new->lno = sp->lno;
+               new->cno = sp->cno;
+       } else if (file_init(new, frp, NULL,
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
+               (void)vs_discard(new, NULL);
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* Create the argument list. */
+       new->cargv = new->argv = ex_buildargv(sp, NULL, frp->name);
+
+       /* Set up the switch. */
+       sp->nextdisp = new;
+       F_SET(sp, SC_SSWITCH);
+
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_equal.c b/dist/nvi/ex/ex_equal.c
new file mode 100644 (file)
index 0000000..ea10007
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: ex_equal.c,v 1.2 2009/11/14 23:40:11 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_equal.c,v 10.12 2001/06/25 15:19:15 skimo Exp (Berkeley) Date: 2001/06/25 15:19:15";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_equal -- :address =
+ *
+ * PUBLIC: int ex_equal __P((SCR *, EXCMD *));
+ */
+int
+ex_equal(SCR *sp, EXCMD *cmdp)
+{
+       db_recno_t lno;
+
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * Print out the line number matching the specified address,
+        * or the number of the last line in the file if no address
+        * specified.
+        *
+        * !!!
+        * Historically, ":0=" displayed 0, and ":=" or ":1=" in an
+        * empty file displayed 1.  Until somebody complains loudly,
+        * we're going to do it right.  The tables in excmd.c permit
+        * lno to get away with any address from 0 to the end of the
+        * file, which, in an empty file, is 0.
+        */
+       if (F_ISSET(cmdp, E_ADDR_DEF)) {
+               if (db_last(sp, &lno))
+                       return (1);
+       } else
+               lno = cmdp->addr1.lno;
+
+       (void)ex_printf(sp, "%ld\n", (unsigned long)lno);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_file.c b/dist/nvi/ex/ex_file.c
new file mode 100644 (file)
index 0000000..be02abc
--- /dev/null
@@ -0,0 +1,83 @@
+/*     $NetBSD: ex_file.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_file.c,v 10.14 2001/06/25 15:19:16 skimo Exp (Berkeley) Date: 2001/06/25 15:19:16";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_file -- :f[ile] [name]
+ *     Change the file's name and display the status line.
+ *
+ * PUBLIC: int ex_file __P((SCR *, EXCMD *));
+ */
+int
+ex_file(SCR *sp, EXCMD *cmdp)
+{
+       char *p;
+       FREF *frp;
+       const char *np;
+       size_t nlen;
+
+       NEEDFILE(sp, cmdp);
+
+       switch (cmdp->argc) {
+       case 0:
+               break;
+       case 1:
+               frp = sp->frp;
+
+               /* Make sure can allocate enough space. */
+               INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, 
+                           np, nlen);
+               if ((p = v_strdup(sp, np, nlen - 1)) == NULL)
+                       return (1);
+
+               /* If already have a file name, it becomes the alternate. */
+               if (!F_ISSET(frp, FR_TMPFILE))
+                       set_alt_name(sp, frp->name);
+
+               /* Free the previous name. */
+               free(frp->name);
+               frp->name = p;
+
+               /*
+                * The file has a real name, it's no longer a temporary,
+                * clear the temporary file flags.
+                */
+               F_CLR(frp, FR_TMPEXIT | FR_TMPFILE);
+
+               /* Have to force a write if the file exists, next time. */
+               F_SET(frp, FR_NAMECHANGE);
+
+               /* Notify the screen. */
+               (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+               break;
+       default:
+               abort();
+       }
+       msgq_status(sp, sp->lno, MSTAT_SHOWLAST);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_filter.c b/dist/nvi/ex/ex_filter.c
new file mode 100644 (file)
index 0000000..a23419f
--- /dev/null
@@ -0,0 +1,328 @@
+/*     $NetBSD: ex_filter.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_filter.c,v 10.44 2003/11/05 17:11:54 skimo Exp (Berkeley) Date: 2003/11/05 17:11:54";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+static int filter_ldisplay __P((SCR *, FILE *));
+
+static pid_t
+runcmd(SCR *sp, const char *np, int* input, int *output)
+{
+       pid_t pid;
+       const char *name;
+       switch (pid = vfork()) {
+       case -1:                        /* Error. */
+               msgq(sp, M_SYSERR, "vfork");
+               return -1;
+       case 0:                         /* Utility. */
+               /*
+                * Redirect stdin from the read end of the input pipe, and
+                * redirect stdout/stderr to the write end of the output pipe.
+                *
+                * !!!
+                * Historically, ex only directed stdout into the input pipe,
+                * letting stderr come out on the terminal as usual.  Vi did
+                * not, directing both stdout and stderr into the input pipe.
+                * We match that practice in both ex and vi for consistency.
+                */
+               if (input[0] != -1)
+                       (void)dup2(input[0], STDIN_FILENO);
+               (void)dup2(output[1], STDOUT_FILENO);
+               (void)dup2(output[1], STDERR_FILENO);
+
+               /* Close the utility's file descriptors. */
+               if (input[0] != -1)
+                       (void)close(input[0]);
+               if (input[1] != -1)
+                       (void)close(input[1]);
+               (void)close(output[0]);
+               (void)close(output[1]);
+
+               if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
+                       name = O_STR(sp, O_SHELL);
+               else
+                       ++name;
+
+               execl(O_STR(sp, O_SHELL), name, "-c", np, (char *)NULL);
+               msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
+               _exit (127);
+               /* NOTREACHED */
+       default:                        /* Parent-reader, parent-writer. */
+               /* Close the pipe ends neither parent will use. */
+               if (input[0] != -1)
+                       (void)close(input[0]);
+               (void)close(output[1]);
+               return pid;
+       }
+}
+
+/*
+ * ex_filter --
+ *     Run a range of lines through a filter utility and optionally
+ *     replace the original text with the stdout/stderr output of
+ *     the utility.
+ *
+ * PUBLIC: int ex_filter __P((SCR *, 
+ * PUBLIC:    EXCMD *, MARK *, MARK *, MARK *, CHAR_T *, enum filtertype));
+ */
+int
+ex_filter(SCR *sp, EXCMD *cmdp, MARK *fm, MARK *tm, MARK *rp, CHAR_T *cmd, enum filtertype ftype)
+{
+       FILE *ifp, *ofp;
+       pid_t parent_writer_pid, utility_pid;
+       db_recno_t nread;
+       int input[2], output[2], rval;
+       const char *np;
+       size_t nlen;
+
+       rval = 0;
+
+       /* Set return cursor position, which is never less than line 1. */
+       *rp = *fm;
+       if (rp->lno == 0)
+               rp->lno = 1;
+
+       /* We're going to need a shell. */
+       if (opts_empty(sp, O_SHELL, 0))
+               return (1);
+
+       /*
+        * There are three different processes running through this code.
+        * They are the utility, the parent-writer and the parent-reader.
+        * The parent-writer is the process that writes from the file to
+        * the utility, the parent reader is the process that reads from
+        * the utility.
+        *
+        * Input and output are named from the utility's point of view.
+        * The utility reads from input[0] and the parent(s) write to
+        * input[1].  The parent(s) read from output[0] and the utility
+        * writes to output[1].
+        *
+        * !!!
+        * Historically, in the FILTER_READ case, the utility reads from
+        * the terminal (e.g. :r! cat works).  Otherwise open up utility
+        * input pipe.
+        */
+       ofp = NULL;
+       input[0] = input[1] = output[0] = output[1] = -1;
+       if (ftype != FILTER_READ && pipe(input) < 0) {
+               msgq(sp, M_SYSERR, "pipe");
+               goto err;
+       }
+
+       /* Open up utility output pipe. */
+       if (pipe(output) < 0) {
+               msgq(sp, M_SYSERR, "pipe");
+               goto err;
+       }
+       if ((ofp = fdopen(output[0], "r")) == NULL) {
+               msgq(sp, M_SYSERR, "fdopen");
+               goto err;
+       }
+
+       /* Fork off the utility process. */
+       INT2SYS(sp, cmd, STRLEN(cmd)+1, np, nlen);
+       utility_pid = runcmd(sp, np, input, output);
+
+       /*
+        * FILTER_RBANG, FILTER_READ:
+        *
+        * Reading is the simple case -- we don't need a parent writer,
+        * so the parent reads the output from the read end of the output
+        * pipe until it finishes, then waits for the child.  Ex_readfp
+        * appends to the MARK, and closes ofp.
+        *
+        * For FILTER_RBANG, there is nothing to write to the utility.
+        * Make sure it doesn't wait forever by closing its standard
+        * input.
+        *
+        * !!!
+        * Set the return cursor to the last line read in for FILTER_READ.
+        * Historically, this behaves differently from ":r file" command,
+        * which leaves the cursor at the first line read in.  Check to
+        * make sure that it's not past EOF because we were reading into an
+        * empty file.
+        */
+       if (ftype == FILTER_RBANG || ftype == FILTER_READ) {
+               if (ftype == FILTER_RBANG)
+                       (void)close(input[1]);
+
+               if (ex_readfp(sp, "filter", ofp, fm, &nread, 1))
+                       rval = 1;
+               sp->rptlines[L_ADDED] += nread;
+               if (ftype == FILTER_READ) {
+                       if (fm->lno == 0)
+                               rp->lno = nread;
+                       else
+                               rp->lno += nread;
+               }
+               goto uwait;
+       }
+
+       /*
+        * FILTER_BANG, FILTER_WRITE
+        *
+        * Here we need both a reader and a writer.  Temporary files are
+        * expensive and we'd like to avoid disk I/O.  Using pipes has the
+        * obvious starvation conditions.  It's done as follows:
+        *
+        *      fork
+        *      child
+        *              write lines out
+        *              exit
+        *      parent
+        *              FILTER_BANG:
+        *                      read lines into the file
+        *                      delete old lines
+        *              FILTER_WRITE
+        *                      read and display lines
+        *              wait for child
+        *
+        * XXX
+        * We get away without locking the underlying database because we know
+        * that none of the records that we're reading will be modified until
+        * after we've read them.  This depends on the fact that the current
+        * B+tree implementation doesn't balance pages or similar things when
+        * it inserts new records.  When the DB code has locking, we should
+        * treat vi as if it were multiple applications sharing a database, and
+        * do the required locking.  If necessary a work-around would be to do
+        * explicit locking in the line.c:db_get() code, based on the flag set
+        * here.
+        */
+       F_SET(sp->ep, F_MULTILOCK);
+       switch (parent_writer_pid = fork()) {
+       case -1:                        /* Error. */
+               msgq(sp, M_SYSERR, "fork");
+               (void)close(input[1]);
+               (void)close(output[0]);
+               rval = 1;
+               break;
+       case 0:                         /* Parent-writer. */
+               /*
+                * Write the selected lines to the write end of the input
+                * pipe.  This instance of ifp is closed by ex_writefp.
+                */
+               (void)close(output[0]);
+               if ((ifp = fdopen(input[1], "w")) == NULL)
+                       _exit (1);
+               _exit(ex_writefp(sp, "filter", ifp, fm, tm, NULL, NULL, 1));
+
+               /* NOTREACHED */
+       default:                        /* Parent-reader. */
+               (void)close(input[1]);
+               if (ftype == FILTER_WRITE) {
+                       /*
+                        * Read the output from the read end of the output
+                        * pipe and display it.  Filter_ldisplay closes ofp.
+                        */
+                       if (filter_ldisplay(sp, ofp))
+                               rval = 1;
+               } else {
+                       /*
+                        * Read the output from the read end of the output
+                        * pipe.  Ex_readfp appends to the MARK and closes
+                        * ofp.
+                        */
+                       if (ex_readfp(sp, "filter", ofp, tm, &nread, 1))
+                               rval = 1;
+                       sp->rptlines[L_ADDED] += nread;
+               }
+
+               /* Wait for the parent-writer. */
+               if (proc_wait(sp,
+                   (long)parent_writer_pid, "parent-writer", 0, 1))
+                       rval = 1;
+
+               /* Delete any lines written to the utility. */
+               if (rval == 0 && ftype == FILTER_BANG &&
+                   (cut(sp, NULL, fm, tm, CUT_LINEMODE) ||
+                   del(sp, fm, tm, 1))) {
+                       rval = 1;
+                       break;
+               }
+
+               /*
+                * If the filter had no output, we may have just deleted
+                * the cursor.  Don't do any real error correction, we'll
+                * try and recover later.
+                */
+                if (rp->lno > 1 && !db_exist(sp, rp->lno))
+                       --rp->lno;
+               break;
+       }
+       F_CLR(sp->ep, F_MULTILOCK);
+
+       /*
+        * !!!
+        * Ignore errors on vi file reads, to make reads prettier.  It's
+        * completely inconsistent, and historic practice.
+        */
+uwait: INT2CHAR(sp, cmd, STRLEN(cmd) + 1, np, nlen);
+       return (proc_wait(sp, (long)utility_pid, np,
+           ftype == FILTER_READ && F_ISSET(sp, SC_VI) ? 1 : 0, 0) || rval);
+err:   if (input[0] != -1)
+               (void)close(input[0]);
+       if (input[1] != -1)
+               (void)close(input[1]);
+       if (ofp != NULL)
+               (void)fclose(ofp);
+       else if (output[0] != -1)
+               (void)close(output[0]);
+       if (output[1] != -1)
+               (void)close(output[1]);
+       return 1;
+}
+
+/*
+ * filter_ldisplay --
+ *     Display output from a utility.
+ *
+ * !!!
+ * Historically, the characters were passed unmodified to the terminal.
+ * We use the ex print routines to make sure they're printable.
+ */
+static int
+filter_ldisplay(SCR *sp, FILE *fp)
+{
+       size_t len;
+       size_t wlen;
+       const CHAR_T *wp;
+
+       EX_PRIVATE *exp;
+
+       for (exp = EXP(sp); !ex_getline(sp, fp, &len) && !INTERRUPTED(sp);) {
+               FILE2INT5(sp, exp->ibcw, exp->ibp, len, wp, wlen);
+               if (ex_ldisplay(sp, wp, wlen, 0, 0))
+                       break;
+       }
+       if (ferror(fp))
+               msgq(sp, M_SYSERR, "filter read");
+       (void)fclose(fp);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_global.c b/dist/nvi/ex/ex_global.c
new file mode 100644 (file)
index 0000000..ff6ae52
--- /dev/null
@@ -0,0 +1,321 @@
+/*     $NetBSD: ex_global.c,v 1.4 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_global.c,v 10.30 2001/06/25 15:19:16 skimo Exp (Berkeley) Date: 2001/06/25 15:19:16";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+enum which {GLOBAL, V};
+
+static int ex_g_setup __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_global -- [line [,line]] g[lobal][!] /pattern/ [commands]
+ *     Exec on lines matching a pattern.
+ *
+ * PUBLIC: int ex_global __P((SCR *, EXCMD *));
+ */
+int
+ex_global(SCR *sp, EXCMD *cmdp)
+{
+       return (ex_g_setup(sp,
+           cmdp, FL_ISSET(cmdp->iflags, E_C_FORCE) ? V : GLOBAL));
+}
+
+/*
+ * ex_v -- [line [,line]] v /pattern/ [commands]
+ *     Exec on lines not matching a pattern.
+ *
+ * PUBLIC: int ex_v __P((SCR *, EXCMD *));
+ */
+int
+ex_v(SCR *sp, EXCMD *cmdp)
+{
+       return (ex_g_setup(sp, cmdp, V));
+}
+
+/*
+ * ex_g_setup --
+ *     Ex global and v commands.
+ */
+static int
+ex_g_setup(SCR *sp, EXCMD *cmdp, enum which cmd)
+{
+       CHAR_T *ptrn, *p, *t;
+       EXCMD *ecp;
+       MARK myabs;
+       RANGE *rp;
+       busy_t btype;
+       db_recno_t start, end;
+       regex_t *re;
+       regmatch_t match[1];
+       size_t len;
+       int cnt, delim, eval;
+       CHAR_T *dbp;
+
+       NEEDFILE(sp, cmdp);
+
+       if (F_ISSET(sp, SC_EX_GLOBAL)) {
+               msgq_wstr(sp, M_ERR, cmdp->cmd->name,
+       "124|The %s command can't be used as part of a global or v command");
+               return (1);
+       }
+
+       /*
+        * Skip leading white space.  Historic vi allowed any non-alphanumeric
+        * to serve as the global command delimiter.
+        */
+       if (cmdp->argc == 0)
+               goto usage;
+       for (p = cmdp->argv[0]->bp; ISBLANK(*p); ++p);
+       if (*p == '\0' || ISALNUM((UCHAR_T)*p) ||
+           *p == '\\' || *p == '|' || *p == '\n') {
+usage:         ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+               return (1);
+       }
+       delim = *p++;
+
+       /*
+        * Get the pattern string, toss escaped characters.
+        *
+        * QUOTING NOTE:
+        * Only toss an escaped character if it escapes a delimiter.
+        */
+       for (ptrn = t = p;;) {
+               if (p[0] == '\0' || p[0] == delim) {
+                       if (p[0] == delim)
+                               ++p;
+                       /*
+                        * !!!
+                        * Nul terminate the pattern string -- it's passed
+                        * to regcomp which doesn't understand anything else.
+                        */
+                       *t = L('\0');
+                       break;
+               }
+               if (p[0] == L('\\')) {
+                       if (p[1] == delim)
+                               ++p;
+                       else if (p[1] == L('\\'))
+                               *t++ = *p++;
+               }
+               *t++ = *p++;
+       }
+
+       /* If the pattern string is empty, use the last one. */
+       if (*ptrn == L('\0')) {
+               if (sp->re == NULL) {
+                       ex_emsg(sp, NULL, EXM_NOPREVRE);
+                       return (1);
+               }
+
+               /* Re-compile the RE if necessary. */
+               if (!F_ISSET(sp, SC_RE_SEARCH) &&
+                   re_compile(sp, sp->re, sp->re_len,
+                   NULL, NULL, &sp->re_c, SEARCH_CSEARCH | SEARCH_MSG))
+                       return (1);
+       } else {
+               /* Compile the RE. */
+               if (re_compile(sp, ptrn, t - ptrn, &sp->re,
+                   &sp->re_len, &sp->re_c, SEARCH_CSEARCH | SEARCH_MSG))
+                       return (1);
+
+               /*
+                * Set saved RE.  Historic practice is that globals set
+                * direction as well as the RE.
+                */
+               sp->searchdir = FORWARD;
+       }
+       re = &sp->re_c;
+
+       /* The global commands always set the previous context mark. */
+       myabs.lno = sp->lno;
+       myabs.cno = sp->cno;
+       if (mark_set(sp, ABSMARK1, &myabs, 1))
+               return (1);
+
+       /* Get an EXCMD structure. */
+       CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
+       CIRCLEQ_INIT(&ecp->rq);
+
+       /*
+        * Get a copy of the command string; the default command is print.
+        * Don't worry about a set of <blank>s with no command, that will
+        * default to print in the ex parser.  We need to have two copies
+        * because the ex parser may step on the command string when it's
+        * parsing it.
+        */
+       if ((len = cmdp->argv[0]->len - (p - cmdp->argv[0]->bp)) == 0) {
+               p = __UNCONST(L("p"));
+               len = 1;
+       }
+
+       MALLOC_RET(sp, ecp->cp, CHAR_T *, (len * 2) * sizeof(CHAR_T));
+       ecp->o_cp = ecp->cp;
+       ecp->o_clen = len;
+       MEMCPYW(ecp->cp + len, p, len);
+       ecp->range_lno = OOBLNO;
+       FL_SET(ecp->agv_flags, cmd == GLOBAL ? AGV_GLOBAL : AGV_V);
+       LIST_INSERT_HEAD(&sp->wp->ecq, ecp, q);
+
+       /*
+        * For each line...  The semantics of global matching are that we first
+        * have to decide which lines are going to get passed to the command,
+        * and then pass them to the command, ignoring other changes.  There's
+        * really no way to do this in a single pass, since arbitrary line
+        * creation, deletion and movement can be done in the ex command.  For
+        * example, a good vi clone test is ":g/X/mo.-3", or "g/X/.,.+1d".
+        * What we do is create linked list of lines that are tracked through
+        * each ex command.  There's a callback routine which the DB interface
+        * routines call when a line is created or deleted.  This doesn't help
+        * the layering much.
+        */
+       btype = BUSY_ON;
+       cnt = INTERRUPT_CHECK;
+       for (start = cmdp->addr1.lno,
+           end = cmdp->addr2.lno; start <= end; ++start) {
+               if (cnt-- == 0) {
+                       if (INTERRUPTED(sp)) {
+                               LIST_REMOVE(ecp, q);
+                               free(ecp->cp);
+                               free(ecp);
+                               break;
+                       }
+                       search_busy(sp, btype);
+                       btype = BUSY_UPDATE;
+                       cnt = INTERRUPT_CHECK;
+               }
+               if (db_get(sp, start, DBG_FATAL, &dbp, &len))
+                       return (1);
+               match[0].rm_so = 0;
+               match[0].rm_eo = len;
+               switch (eval =
+                   regexec(&sp->re_c, dbp, 0, match, REG_STARTEND)) {
+               case 0:
+                       if (cmd == V)
+                               continue;
+                       break;
+               case REG_NOMATCH:
+                       if (cmd == GLOBAL)
+                               continue;
+                       break;
+               default:
+                       re_error(sp, eval, &sp->re_c);
+                       break;
+               }
+
+               /* If follows the last entry, extend the last entry's range. */
+               if ((rp = ecp->rq.cqh_last) != (void *)&ecp->rq &&
+                   rp->stop == start - 1) {
+                       ++rp->stop;
+                       continue;
+               }
+
+               /* Allocate a new range, and append it to the list. */
+               CALLOC(sp, rp, RANGE *, 1, sizeof(RANGE));
+               if (rp == NULL)
+                       return (1);
+               rp->start = rp->stop = start;
+               CIRCLEQ_INSERT_TAIL(&ecp->rq, rp, q);
+       }
+       search_busy(sp, BUSY_OFF);
+       return (0);
+}
+
+/*
+ * ex_g_insdel --
+ *     Update the ranges based on an insertion or deletion.
+ *
+ * PUBLIC: int ex_g_insdel __P((SCR *, lnop_t, db_recno_t));
+ */
+int
+ex_g_insdel(SCR *sp, lnop_t op, db_recno_t lno)
+{
+       EXCMD *ecp;
+       RANGE *nrp, *rp;
+
+       /* All insert/append operations are done as inserts. */
+       if (op == LINE_APPEND)
+               abort();
+
+       if (op == LINE_RESET)
+               return (0);
+
+       for (ecp = sp->wp->ecq.lh_first; ecp != NULL; ecp = ecp->q.le_next) {
+               if (!FL_ISSET(ecp->agv_flags, AGV_AT | AGV_GLOBAL | AGV_V))
+                       continue;
+               for (rp = ecp->rq.cqh_first; rp != (void *)&ecp->rq; rp = nrp) {
+                       nrp = rp->q.cqe_next;
+
+                       /* If range less than the line, ignore it. */
+                       if (rp->stop < lno)
+                               continue;
+                       
+                       /*
+                        * If range greater than the line, decrement or
+                        * increment the range.
+                        */
+                       if (rp->start > lno) {
+                               if (op == LINE_DELETE) {
+                                       --rp->start;
+                                       --rp->stop;
+                               } else {
+                                       ++rp->start;
+                                       ++rp->stop;
+                               }
+                               continue;
+                       }
+
+                       /*
+                        * Lno is inside the range, decrement the end point
+                        * for deletion, and split the range for insertion.
+                        * In the latter case, since we're inserting a new
+                        * element, neither range can be exhausted.
+                        */
+                       if (op == LINE_DELETE) {
+                               if (rp->start > --rp->stop) {
+                                       CIRCLEQ_REMOVE(&ecp->rq, rp, q);
+                                       free(rp);
+                               }
+                       } else {
+                               CALLOC_RET(sp, nrp, RANGE *, 1, sizeof(RANGE));
+                               nrp->start = lno + 1;
+                               nrp->stop = rp->stop + 1;
+                               rp->stop = lno - 1;
+                               CIRCLEQ_INSERT_AFTER(&ecp->rq, rp, nrp, q);
+                               rp = nrp;
+                       }
+               }
+
+               /*
+                * If the command deleted/inserted lines, the cursor moves to
+                * the line after the deleted/inserted line.
+                */
+               ecp->range_lno = lno;
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_init.c b/dist/nvi/ex/ex_init.c
new file mode 100644 (file)
index 0000000..e8a044d
--- /dev/null
@@ -0,0 +1,409 @@
+/*     $NetBSD: ex_init.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_init.c,v 10.31 2001/06/25 15:19:16 skimo Exp (Berkeley) Date: 2001/06/25 15:19:16";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>         /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tag.h"
+#include "pathnames.h"
+
+enum rc { NOEXIST, NOPERM, RCOK };
+static enum rc exrc_isok __P((SCR *, struct stat *, const char *, int, int));
+
+static int ex_run_file __P((SCR *, const char *));
+
+/*
+ * ex_screen_copy --
+ *     Copy ex screen.
+ *
+ * PUBLIC: int ex_screen_copy __P((SCR *, SCR *));
+ */
+int
+ex_screen_copy(SCR *orig, SCR *sp)
+{
+       EX_PRIVATE *oexp, *nexp;
+
+       /* Create the private ex structure. */
+       CALLOC_RET(orig, nexp, EX_PRIVATE *, 1, sizeof(EX_PRIVATE));
+       sp->ex_private = nexp;
+
+       /* Initialize queues. */
+       CIRCLEQ_INIT(&nexp->tq);
+       TAILQ_INIT(&nexp->tagfq);
+       LIST_INIT(&nexp->cscq);
+
+       if (orig == NULL) {
+       } else {
+               oexp = EXP(orig);
+
+               if (oexp->lastbcomm != NULL &&
+                   (nexp->lastbcomm = v_wstrdup(sp, oexp->lastbcomm, 
+                                    STRLEN(oexp->lastbcomm))) == NULL) {
+                       msgq(sp, M_SYSERR, NULL);
+                       return(1);
+               }
+               if (ex_tag_copy(orig, sp))
+                       return (1);
+       }
+       return (0);
+}
+
+/*
+ * ex_screen_end --
+ *     End a vi screen.
+ *
+ * PUBLIC: int ex_screen_end __P((SCR *));
+ */
+int
+ex_screen_end(SCR *sp)
+{
+       EX_PRIVATE *exp;
+       int rval;
+
+       if ((exp = EXP(sp)) == NULL)
+               return (0);
+
+       rval = 0;
+
+       /* Close down script connections. */
+       if (F_ISSET(sp, SC_SCRIPT) && sscr_end(sp))
+               rval = 1;
+
+       if (argv_free(sp))
+               rval = 1;
+
+       if (exp->ibp != NULL)
+               free(exp->ibp);
+
+       if (exp->lastbcomm != NULL)
+               free(exp->lastbcomm);
+
+       if (ex_tag_free(sp))
+               rval = 1;
+
+       /* Free private memory. */
+       free(exp);
+       sp->ex_private = NULL;
+
+       return (rval);
+}
+
+/*
+ * ex_optchange --
+ *     Handle change of options for ex.
+ *
+ * PUBLIC: int ex_optchange __P((SCR *, int, const char *, u_long *));
+ */
+int
+ex_optchange(SCR *sp, int offset, const char *str, u_long *valp)
+{
+       switch (offset) {
+       case O_TAGS:
+               return (ex_tagf_alloc(sp, str));
+       }
+       return (0);
+}
+
+/*
+ * ex_exrc --
+ *     Read the EXINIT environment variable and the startup exrc files,
+ *     and execute their commands.
+ *
+ * PUBLIC: int ex_exrc __P((SCR *));
+ */
+int
+ex_exrc(SCR *sp)
+{
+       struct stat hsb, lsb;
+       char *p, path[MAXPATHLEN];
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /*
+        * Source the system, environment, $HOME and local .exrc values.
+        * Vi historically didn't check $HOME/.exrc if the environment
+        * variable EXINIT was set.  This is all done before the file is
+        * read in, because things in the .exrc information can set, for
+        * example, the recovery directory.
+        *
+        * !!!
+        * While nvi can handle any of the options settings of historic vi,
+        * the converse is not true.  Since users are going to have to have
+        * files and environmental variables that work with both, we use nvi
+        * versions of both the $HOME and local startup files if they exist,
+        * otherwise the historic ones.
+        *
+        * !!!
+        * For a discussion of permissions and when what .exrc files are
+        * read, see the comment above the exrc_isok() function below.
+        *
+        * !!!
+        * If the user started the historic of vi in $HOME, vi read the user's
+        * .exrc file twice, as $HOME/.exrc and as ./.exrc.  We avoid this, as
+        * it's going to make some commands behave oddly, and I can't imagine
+        * anyone depending on it.
+        */
+       switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1, 0)) {
+       case NOEXIST:
+       case NOPERM:
+               break;
+       case RCOK:
+               if (ex_run_file(sp, _PATH_SYSEXRC))
+                       return (1);
+               break;
+       }
+
+       /* Run the commands. */
+       if (EXCMD_RUNNING(sp->wp))
+               (void)ex_cmd(sp);
+       if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+               return (0);
+
+       if ((p = getenv("NEXINIT")) != NULL) {
+               CHAR2INT(sp, p, strlen(p) + 1, wp, wlen);
+               if (ex_run_str(sp, "NEXINIT", wp, wlen - 1, 1, 0))
+                       return (1);
+       } else if ((p = getenv("EXINIT")) != NULL) {
+               CHAR2INT(sp, p, strlen(p) + 1, wp, wlen);
+               if (ex_run_str(sp, "EXINIT", wp, wlen - 1, 1, 0))
+                       return (1);
+       } else if ((p = getenv("HOME")) != NULL && *p) {
+               (void)snprintf(path, sizeof(path), "%s/%s", p, _PATH_NEXRC);
+               switch (exrc_isok(sp, &hsb, path, 0, 1)) {
+               case NOEXIST:
+                       (void)snprintf(path,
+                           sizeof(path), "%s/%s", p, _PATH_EXRC);
+                       if (exrc_isok(sp,
+                           &hsb, path, 0, 1) == RCOK && ex_run_file(sp, path))
+                               return (1);
+                       break;
+               case NOPERM:
+                       break;
+               case RCOK:
+                       if (ex_run_file(sp, path))
+                               return (1);
+                       break;
+               }
+       }
+
+       /* Run the commands. */
+       if (EXCMD_RUNNING(sp->wp))
+               (void)ex_cmd(sp);
+       if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+               return (0);
+
+       /* Previous commands may have set the exrc option. */
+       if (O_ISSET(sp, O_EXRC)) {
+               switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) {
+               case NOEXIST:
+                       if (exrc_isok(sp, &lsb, _PATH_EXRC, 0, 0) == RCOK &&
+                           (lsb.st_dev != hsb.st_dev ||
+                           lsb.st_ino != hsb.st_ino) &&
+                           ex_run_file(sp, _PATH_EXRC))
+                               return (1);
+                       break;
+               case NOPERM:
+                       break;
+               case RCOK:
+                       if ((lsb.st_dev != hsb.st_dev ||
+                           lsb.st_ino != hsb.st_ino) &&
+                           ex_run_file(sp, _PATH_NEXRC))
+                               return (1);
+                       break;
+               }
+               /* Run the commands. */
+               if (EXCMD_RUNNING(sp->wp))
+                       (void)ex_cmd(sp);
+               if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+                       return (0);
+       }
+
+       return (0);
+}
+
+/*
+ * ex_run_file --
+ *     Set up a file of ex commands to run.
+ */
+static int
+ex_run_file(SCR *sp, const char *name)
+{
+       EXCMD cmd;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       ex_cinit(sp, &cmd, C_SOURCE, 0, OOBLNO, OOBLNO, 0);
+       CHAR2INT(sp, name, strlen(name)+1, wp, wlen);
+       argv_exp0(sp, &cmd, wp, wlen - 1);
+       return (ex_source(sp, &cmd));
+}
+
+/*
+ * ex_run_str --
+ *     Set up a string of ex commands to run.
+ *
+ * PUBLIC: int ex_run_str __P((SCR *, char *, CHAR_T *, size_t, int, int));
+ */
+int
+ex_run_str(SCR *sp, const char *name, const CHAR_T *str, size_t len, int ex_flags, int nocopy)
+{
+       WIN *wp;
+       EXCMD *ecp;
+
+       wp = sp->wp;
+       if (EXCMD_RUNNING(wp)) {
+               CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
+               LIST_INSERT_HEAD(&wp->ecq, ecp, q);
+       } else
+               ecp = &wp->excmd;
+
+       F_INIT(ecp,
+           ex_flags ? E_BLIGNORE | E_NOAUTO | E_NOPRDEF | E_VLITONLY : 0);
+
+       if (nocopy)
+               ecp->cp = __UNCONST(str);
+       else
+               if ((ecp->cp = v_wstrdup(sp, str, len)) == NULL)
+                       return (1);
+       ecp->clen = len;
+
+       if (name == NULL)
+               ecp->if_name = NULL;
+       else {
+               if ((ecp->if_name = v_strdup(sp, name, strlen(name))) == NULL)
+                       return (1);
+               ecp->if_lno = 1;
+               F_SET(ecp, E_NAMEDISCARD);
+       }
+
+       return (0);
+}
+
+/*
+ * exrc_isok --
+ *     Check a .exrc file for source-ability.
+ *
+ * !!!
+ * Historically, vi read the $HOME and local .exrc files if they were owned
+ * by the user's real ID, or the "sourceany" option was set, regardless of
+ * any other considerations.  We no longer support the sourceany option as
+ * it's a security problem of mammoth proportions.  We require the system
+ * .exrc file to be owned by root, the $HOME .exrc file to be owned by the
+ * user's effective ID (or that the user's effective ID be root) and the
+ * local .exrc files to be owned by the user's effective ID.  In all cases,
+ * the file cannot be writeable by anyone other than its owner.
+ *
+ * In O'Reilly ("Learning the VI Editor", Fifth Ed., May 1992, page 106),
+ * it notes that System V release 3.2 and later has an option "[no]exrc".
+ * The behavior is that local .exrc files are read only if the exrc option
+ * is set.  The default for the exrc option was off, so, by default, local
+ * .exrc files were not read.  The problem this was intended to solve was
+ * that System V permitted users to give away files, so there's no possible
+ * ownership or writeability test to ensure that the file is safe.
+ *
+ * POSIX 1003.2-1992 standardized exrc as an option.  It required the exrc
+ * option to be off by default, thus local .exrc files are not to be read
+ * by default.  The Rationale noted (incorrectly) that this was a change
+ * to historic practice, but correctly noted that a default of off improves
+ * system security.  POSIX also required that vi check the effective user
+ * ID instead of the real user ID, which is why we've switched from historic
+ * practice.
+ *
+ * We initialize the exrc variable to off.  If it's turned on by the system
+ * or $HOME .exrc files, and the local .exrc file passes the ownership and
+ * writeability tests, then we read it.  This breaks historic 4BSD practice,
+ * but it gives us a measure of security on systems where users can give away
+ * files.
+ */
+static enum rc
+exrc_isok(SCR *sp, struct stat *sbp, const char *path, int rootown, int rootid)
+{
+       enum { ROOTOWN, OWN, WRITER } etype;
+       uid_t euid;
+       int nf1, nf2;
+       char *a, *b, buf[MAXPATHLEN];
+
+       /* Check for the file's existence. */
+       if (stat(path, sbp))
+               return (NOEXIST);
+
+       /* Check ownership permissions. */
+       euid = geteuid();
+       if (!(rootown && sbp->st_uid == 0) &&
+           !(rootid && euid == 0) && sbp->st_uid != euid) {
+               etype = rootown ? ROOTOWN : OWN;
+               goto denied;
+       }
+
+       /* Check writeability. */
+       if (sbp->st_mode & (S_IWGRP | S_IWOTH)) {
+               etype = WRITER;
+               goto denied;
+       }
+       return (RCOK);
+
+denied:        a = msg_print(sp, path, &nf1);
+       if (strchr(path, '/') == NULL && getcwd(buf, sizeof(buf)) != NULL) {
+               b = msg_print(sp, buf, &nf2);
+               switch (etype) {
+               case ROOTOWN:
+                       msgq(sp, M_ERR,
+                           "125|%s/%s: not sourced: not owned by you or root",
+                           b, a);
+                       break;
+               case OWN:
+                       msgq(sp, M_ERR,
+                           "126|%s/%s: not sourced: not owned by you", b, a);
+                       break;
+               case WRITER:
+                       msgq(sp, M_ERR,
+    "127|%s/%s: not sourced: writeable by a user other than the owner", b, a);
+                       break;
+               }
+               if (nf2)
+                       FREE_SPACE(sp, b, 0);
+       } else
+               switch (etype) {
+               case ROOTOWN:
+                       msgq(sp, M_ERR,
+                           "128|%s: not sourced: not owned by you or root", a);
+                       break;
+               case OWN:
+                       msgq(sp, M_ERR,
+                           "129|%s: not sourced: not owned by you", a);
+                       break;
+               case WRITER:
+                       msgq(sp, M_ERR,
+           "130|%s: not sourced: writeable by a user other than the owner", a);
+                       break;
+               }
+
+       if (nf1)
+               FREE_SPACE(sp, a, 0);
+       return (NOPERM);
+}
diff --git a/dist/nvi/ex/ex_join.c b/dist/nvi/ex/ex_join.c
new file mode 100644 (file)
index 0000000..bdaedbe
--- /dev/null
@@ -0,0 +1,172 @@
+/*     $NetBSD: ex_join.c,v 1.3 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_join.c,v 10.17 2004/03/16 14:14:04 skimo Exp (Berkeley) Date: 2004/03/16 14:14:04";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_join -- :[line [,line]] j[oin][!] [count] [flags]
+ *     Join lines.
+ *
+ * PUBLIC: int ex_join __P((SCR *, EXCMD *));
+ */
+int
+ex_join(SCR *sp, EXCMD *cmdp)
+{
+       db_recno_t from, to;
+       size_t blen, clen, len, tlen;
+       ARG_CHAR_T echar = 0;
+       int extra, first;
+       CHAR_T *bp, *tbp = NULL;
+       CHAR_T *p;
+
+       NEEDFILE(sp, cmdp);
+
+       from = cmdp->addr1.lno;
+       to = cmdp->addr2.lno;
+
+       /* Check for no lines to join. */
+       if (!db_exist(sp, from + 1)) {
+               msgq(sp, M_ERR, "131|No following lines to join");
+               return (1);
+       }
+
+       GET_SPACE_RETW(sp, bp, blen, 256);
+
+       /*
+        * The count for the join command was off-by-one,
+        * historically, to other counts for other commands.
+        */
+       if (F_ISSET(cmdp, E_ADDR_DEF) || cmdp->addrcnt == 1)
+               ++cmdp->addr2.lno;
+
+       clen = tlen = 0;
+        for (first = 1,
+           from = cmdp->addr1.lno, to = cmdp->addr2.lno; from <= to; ++from) {
+               /*
+                * Get next line.  Historic versions of vi allowed "10J" while
+                * less than 10 lines from the end-of-file, so we do too.
+                */
+               if (db_get(sp, from, 0, &p, &len)) {
+                       cmdp->addr2.lno = from - 1;
+                       break;
+               }
+
+               /* Empty lines just go away. */
+               if (len == 0)
+                       continue;
+
+               /*
+                * Get more space if necessary.  Note, tlen isn't the length
+                * of the new line, it's roughly the amount of space needed.
+                * tbp - bp is the length of the new line.
+                */
+               tlen += len + 2;
+               ADD_SPACE_RETW(sp, bp, blen, tlen);
+               tbp = bp + clen;
+
+               /*
+                * Historic practice:
+                *
+                * If force specified, join without modification.
+                * If the current line ends with whitespace, strip leading
+                *    whitespace from the joined line.
+                * If the next line starts with a ), do nothing.
+                * If the current line ends with ., insert two spaces.
+                * Else, insert one space.
+                *
+                * One change -- add ? and ! to the list of characters for
+                * which we insert two spaces.  I expect that POSIX 1003.2
+                * will require this as well.
+                *
+                * Echar is the last character in the last line joined.
+                */
+               extra = 0;
+               if (!first && !FL_ISSET(cmdp->iflags, E_C_FORCE)) {
+                       if (ISBLANK(echar))
+                               for (; len && ISBLANK((UCHAR_T)*p); --len, ++p);
+                       else if (p[0] != ')') {
+                               if (STRCHR(L(".?!"), echar)) {
+                                       *tbp++ = ' ';
+                                       ++clen;
+                                       extra = 1;
+                               }
+                               *tbp++ = ' ';
+                               ++clen;
+                               for (; len && ISBLANK((UCHAR_T)*p); --len, ++p);
+                       }
+               }
+
+               if (len != 0) {
+                       MEMCPYW(tbp, p, len);
+                       tbp += len;
+                       clen += len;
+                       echar = p[len - 1];
+               } else
+                       echar = ' ';
+
+               /*
+                * Historic practice for vi was to put the cursor at the first
+                * inserted whitespace character, if there was one, or the
+                * first character of the joined line, if there wasn't, or the
+                * last character of the line if joined to an empty line.  If
+                * a count was specified, the cursor was moved as described
+                * for the first line joined, ignoring subsequent lines.  If
+                * the join was a ':' command, the cursor was placed at the
+                * first non-blank character of the line unless the cursor was
+                * "attracted" to the end of line when the command was executed
+                * in which case it moved to the new end of line.  There are
+                * probably several more special cases, but frankly, my dear,
+                * I don't give a damn.  This implementation puts the cursor
+                * on the first inserted whitespace character, the first
+                * character of the joined line, or the last character of the
+                * line regardless.  Note, if the cursor isn't on the joined
+                * line (possible with : commands), it is reset to the starting
+                * line.
+                */
+               if (first) {
+                       sp->cno = (tbp - bp) - (1 + extra);
+                       first = 0;
+               } else
+                       sp->cno = (tbp - bp) - len - (1 + extra);
+       }
+       sp->lno = cmdp->addr1.lno;
+
+       /* Delete the joined lines. */
+        for (from = cmdp->addr1.lno, to = cmdp->addr2.lno; to > from; --to)
+               if (db_delete(sp, to))
+                       goto err;
+
+       /* If the original line changed, reset it. */
+       if (!first && db_set(sp, from, bp, tbp - bp)) {
+err:           FREE_SPACEW(sp, bp, blen);
+               return (1);
+       }
+       FREE_SPACEW(sp, bp, blen);
+
+       sp->rptlines[L_JOINED] += (cmdp->addr2.lno - cmdp->addr1.lno) + 1;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_map.c b/dist/nvi/ex/ex_map.c
new file mode 100644 (file)
index 0000000..4e53932
--- /dev/null
@@ -0,0 +1,119 @@
+/*     $NetBSD: ex_map.c,v 1.2 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_map.c,v 10.11 2001/06/25 15:19:17 skimo Exp (Berkeley) Date: 2001/06/25 15:19:17";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_map -- :map[!] [input] [replacement]
+ *     Map a key/string or display mapped keys.
+ *
+ * Historical note:
+ *     Historic vi maps were fairly bizarre, and likely to differ in
+ *     very subtle and strange ways from this implementation.  Two
+ *     things worth noting are that vi would often hang or drop core
+ *     if the map was strange enough (ex: map X "xy$@x^V), or, simply
+ *     not work.  One trick worth remembering is that if you put a
+ *     mark at the start of the map, e.g. map X mx"xy ...), or if you
+ *     put the map in a .exrc file, things would often work much better.
+ *     No clue why.
+ *
+ * PUBLIC: int ex_map __P((SCR *, EXCMD *));
+ */
+int
+ex_map(SCR *sp, EXCMD *cmdp)
+{
+       seq_t stype;
+       CHAR_T *input, *p;
+
+       stype = FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND;
+
+       switch (cmdp->argc) {
+       case 0:
+               if (seq_dump(sp, stype, 1) == 0)
+                       msgq(sp, M_INFO, stype == SEQ_INPUT ?
+                           "132|No input map entries" :
+                           "133|No command map entries");
+               return (0);
+       case 2:
+               input = cmdp->argv[0]->bp;
+               break;
+       default:
+               abort();
+       }
+
+       /*
+        * If the mapped string is #[0-9]* (and wasn't quoted) then store the
+        * function key mapping.  If the screen specific routine has been set,
+        * call it as well.  Note, the SEQ_FUNCMAP type is persistent across
+        * screen types, maybe the next screen type will get it right.
+        */
+       if (input[0] == '#' && ISDIGIT((UCHAR_T)input[1])) {
+               for (p = input + 2; ISDIGIT((UCHAR_T)*p); ++p);
+               if (p[0] != '\0')
+                       goto nofunc;
+
+               if (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
+                   cmdp->argv[1]->bp, cmdp->argv[1]->len, stype,
+                   SEQ_FUNCMAP | SEQ_USERDEF))
+                       return (1);
+               return (sp->gp->scr_fmap == NULL ? 0 :
+                   sp->gp->scr_fmap(sp, stype, input, cmdp->argv[0]->len,
+                   cmdp->argv[1]->bp, cmdp->argv[1]->len));
+       }
+
+       /* Some single keys may not be remapped in command mode. */
+nofunc:        if (stype == SEQ_COMMAND && input[1] == '\0')
+               switch (KEY_VAL(sp, input[0])) {
+               case K_COLON:
+               case K_ESCAPE:
+               case K_NL:
+                       msgq(sp, M_ERR,
+                           "134|The %s character may not be remapped",
+                           KEY_NAME(sp, input[0]));
+                       return (1);
+               }
+       return (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
+           cmdp->argv[1]->bp, cmdp->argv[1]->len, stype, SEQ_USERDEF));
+}
+
+/*
+ * ex_unmap -- (:unmap[!] key)
+ *     Unmap a key.
+ *
+ * PUBLIC: int ex_unmap __P((SCR *, EXCMD *));
+ */
+int
+ex_unmap(SCR *sp, EXCMD *cmdp)
+{
+       if (seq_delete(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len,
+           FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND)) {
+               msgq_wstr(sp, M_INFO,
+                   cmdp->argv[0]->bp, "135|\"%s\" isn't currently mapped");
+               return (1);
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_mark.c b/dist/nvi/ex/ex_mark.c
new file mode 100644 (file)
index 0000000..3e52c10
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: ex_mark.c,v 1.1.1.2 2008/05/18 14:31:16 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_mark.c,v 10.9 2001/06/25 15:19:17 skimo Exp (Berkeley) Date: 2001/06/25 15:19:17";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_mark -- :mark char
+ *           :k char
+ *     Mark lines.
+ *
+ *
+ * PUBLIC: int ex_mark __P((SCR *, EXCMD *));
+ */
+int
+ex_mark(SCR *sp, EXCMD *cmdp)
+{
+       NEEDFILE(sp, cmdp);
+
+       if (cmdp->argv[0]->len != 1) {
+               msgq(sp, M_ERR, "136|Mark names must be a single character");
+               return (1);
+       }
+       return (mark_set(sp, cmdp->argv[0]->bp[0], &cmdp->addr1, 1));
+}
diff --git a/dist/nvi/ex/ex_mkexrc.c b/dist/nvi/ex/ex_mkexrc.c
new file mode 100644 (file)
index 0000000..5305d09
--- /dev/null
@@ -0,0 +1,101 @@
+/*     $NetBSD: ex_mkexrc.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_mkexrc.c,v 10.13 2001/06/25 15:19:17 skimo Exp (Berkeley) Date: 2001/06/25 15:19:17";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "pathnames.h"
+
+/*
+ * ex_mkexrc -- :mkexrc[!] [file]
+ *
+ * Create (or overwrite) a .exrc file with the current info.
+ *
+ * PUBLIC: int ex_mkexrc __P((SCR *, EXCMD *));
+ */
+int
+ex_mkexrc(SCR *sp, EXCMD *cmdp)
+{
+       struct stat sb;
+       FILE *fp;
+       int fd, sverrno;
+       const char *fname;
+       size_t flen;
+
+       switch (cmdp->argc) {
+       case 0:
+               fname = _PATH_EXRC;
+               INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, 
+                           fname, flen);
+               set_alt_name(sp, fname);
+               break;
+       default:
+               abort();
+       }
+
+       if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && !stat(fname, &sb)) {
+               msgq_str(sp, M_ERR, fname,
+                   "137|%s exists, not written; use ! to override");
+               return (1);
+       }
+
+       /* Create with max permissions of rw-r--r--. */
+       if ((fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY,
+           S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
+               msgq_str(sp, M_SYSERR, fname, "%s");
+               return (1);
+       }
+
+       if ((fp = fdopen(fd, "w")) == NULL) {
+               sverrno = errno;
+               (void)close(fd);
+               goto e2;
+       }
+
+       if (seq_save(sp, fp, "abbreviate ", SEQ_ABBREV) || ferror(fp))
+               goto e1;
+       if (seq_save(sp, fp, "map ", SEQ_COMMAND) || ferror(fp))
+               goto e1;
+       if (seq_save(sp, fp, "map! ", SEQ_INPUT) || ferror(fp))
+               goto e1;
+       if (opts_save(sp, fp) || ferror(fp))
+               goto e1;
+       if (fclose(fp)) {
+               sverrno = errno;
+               goto e2;
+       }
+
+       msgq_str(sp, M_INFO, fname, "138|New exrc file: %s");
+       return (0);
+
+e1:    sverrno = errno;
+       (void)fclose(fp);
+e2:    errno = sverrno;
+       msgq_str(sp, M_SYSERR, fname, "%s");
+       return (1);
+}
diff --git a/dist/nvi/ex/ex_move.c b/dist/nvi/ex/ex_move.c
new file mode 100644 (file)
index 0000000..cecc537
--- /dev/null
@@ -0,0 +1,197 @@
+/*     $NetBSD: ex_move.c,v 1.2 2012/01/27 16:41:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_move.c,v 10.15 2001/06/25 15:19:17 skimo Exp (Berkeley) Date: 2001/06/25 15:19:17";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_copy -- :[line [,line]] co[py] line [flags]
+ *     Copy selected lines.
+ *
+ * PUBLIC: int ex_copy __P((SCR *, EXCMD *));
+ */
+int
+ex_copy(SCR *sp, EXCMD *cmdp)
+{
+       CB cb;
+       MARK fm1, fm2, m, tm;
+       db_recno_t cnt;
+       int rval;
+
+       rval = 0;
+
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * It's possible to copy things into the area that's being
+        * copied, e.g. "2,5copy3" is legitimate.  Save the text to
+        * a cut buffer.
+        */
+       fm1 = cmdp->addr1;
+       fm2 = cmdp->addr2;
+       memset(&cb, 0, sizeof(cb));
+       CIRCLEQ_INIT(&cb.textq);
+       for (cnt = fm1.lno; cnt <= fm2.lno; ++cnt)
+               if (cut_line(sp, cnt, 0, ENTIRE_LINE, &cb)) {
+                       rval = 1;
+                       goto err;
+               }
+       cb.flags |= CB_LMODE;
+
+       /* Put the text into place. */
+       tm.lno = cmdp->lineno;
+       tm.cno = 0;
+       if (put(sp, &cb, NULL, &tm, &m, 1))
+               rval = 1;
+       else {
+               /*
+                * Copy puts the cursor on the last line copied.  The cursor
+                * returned by the put routine is the first line put, not the
+                * last, because that's the historic semantic of vi.
+                */
+               cnt = (fm2.lno - fm1.lno) + 1;
+               sp->lno = m.lno + (cnt - 1);
+               sp->cno = 0;
+       }
+err:   text_lfree(&cb.textq);
+       return (rval);
+}
+
+/*
+ * ex_move -- :[line [,line]] mo[ve] line
+ *     Move selected lines.
+ *
+ * PUBLIC: int ex_move __P((SCR *, EXCMD *));
+ */
+int
+ex_move(SCR *sp, EXCMD *cmdp)
+{
+       LMARK *lmp;
+       MARK fm1, fm2;
+       db_recno_t cnt, diff, fl, tl, mfl, mtl;
+       size_t blen, len;
+       int mark_reset;
+       CHAR_T *bp;
+       CHAR_T *p;
+
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * It's not possible to move things into the area that's being
+        * moved.
+        */
+       fm1 = cmdp->addr1;
+       fm2 = cmdp->addr2;
+       if (cmdp->lineno >= fm1.lno && cmdp->lineno <= fm2.lno) {
+               msgq(sp, M_ERR, "139|Destination line is inside move range");
+               return (1);
+       }
+
+       /*
+        * Log the positions of any marks in the to-be-deleted lines.  This
+        * has to work with the logging code.  What happens is that we log
+        * the old mark positions, make the changes, then log the new mark
+        * positions.  Then the marks end up in the right positions no matter
+        * which way the log is traversed.
+        *
+        * XXX
+        * Reset the MARK_USERSET flag so that the log can undo the mark.
+        * This isn't very clean, and should probably be fixed.
+        */
+       fl = fm1.lno;
+       tl = cmdp->lineno;
+
+       /* Log the old positions of the marks. */
+       mark_reset = 0;
+       for (lmp = sp->ep->marks.lh_first; lmp != NULL; lmp = lmp->q.le_next)
+               if (lmp->name != ABSMARK1 &&
+                   lmp->lno >= fl && lmp->lno <= tl) {
+                       mark_reset = 1;
+                       F_CLR(lmp, MARK_USERSET);
+                       (void)log_mark(sp, lmp);
+               }
+
+       /* Get memory for the copy. */
+       GET_SPACE_RETW(sp, bp, blen, 256);
+
+       /* Move the lines. */
+       diff = (fm2.lno - fm1.lno) + 1;
+       if (tl > fl) {                          /* Destination > source. */
+               mfl = tl - diff;
+               mtl = tl;
+               for (cnt = diff; cnt--;) {
+                       if (db_get(sp, fl, DBG_FATAL, &p, &len))
+                               return (1);
+                       BINC_RETW(sp, bp, blen, len);
+                       MEMCPYW(bp, p, len);
+                       if (db_append(sp, 1, tl, bp, len))
+                               return (1);
+                       if (mark_reset)
+                               for (lmp = sp->ep->marks.lh_first;
+                                   lmp != NULL; lmp = lmp->q.le_next)
+                                       if (lmp->name != ABSMARK1 &&
+                                           lmp->lno == fl)
+                                               lmp->lno = tl + 1;
+                       if (db_delete(sp, fl))
+                               return (1);
+               }
+       } else {                                /* Destination < source. */
+               mfl = tl;
+               mtl = tl + diff;
+               for (cnt = diff; cnt--;) {
+                       if (db_get(sp, fl, DBG_FATAL, &p, &len))
+                               return (1);
+                       BINC_RETW(sp, bp, blen, len);
+                       MEMCPYW(bp, p, len);
+                       if (db_append(sp, 1, tl++, bp, len))
+                               return (1);
+                       if (mark_reset)
+                               for (lmp = sp->ep->marks.lh_first;
+                                   lmp != NULL; lmp = lmp->q.le_next)
+                                       if (lmp->name != ABSMARK1 &&
+                                           lmp->lno == fl)
+                                               lmp->lno = tl;
+                       ++fl;
+                       if (db_delete(sp, fl))
+                               return (1);
+               }
+       }
+       FREE_SPACEW(sp, bp, blen);
+
+       sp->lno = tl;                           /* Last line moved. */
+       sp->cno = 0;
+
+       /* Log the new positions of the marks. */
+       if (mark_reset)
+               for (lmp = sp->ep->marks.lh_first;
+                   lmp != NULL; lmp = lmp->q.le_next)
+                       if (lmp->name != ABSMARK1 &&
+                           lmp->lno >= mfl && lmp->lno <= mtl)
+                               (void)log_mark(sp, lmp);
+
+
+       sp->rptlines[L_MOVED] += diff;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_open.c b/dist/nvi/ex/ex_open.c
new file mode 100644 (file)
index 0000000..45e018b
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: ex_open.c,v 1.1.1.2 2008/05/18 14:31:16 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_open.c,v 10.8 2001/06/25 15:19:17 skimo Exp (Berkeley) Date: 2001/06/25 15:19:17";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_open -- :[line] o[pen] [/pattern/] [flags]
+ *
+ *     Switch to single line "open" mode.
+ *
+ * PUBLIC: int ex_open __P((SCR *, EXCMD *));
+ */
+int
+ex_open(SCR *sp, EXCMD *cmdp)
+{
+       /* If open option off, disallow open command. */
+       if (!O_ISSET(sp, O_OPEN)) {
+               msgq(sp, M_ERR,
+           "140|The open command requires that the open option be set");
+               return (1);
+       }
+
+       msgq(sp, M_ERR, "141|The open command is not yet implemented");
+       return (1);
+}
diff --git a/dist/nvi/ex/ex_perl.c b/dist/nvi/ex/ex_perl.c
new file mode 100644 (file)
index 0000000..a53dd23
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: ex_perl.c,v 1.2 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1995
+ *     George V. Neville-Neil. All rights reserved.
+ * Copyright (c) 1996
+ *     Sven Verdoolaege. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_perl.c,v 8.11 2001/06/25 15:19:18 skimo Exp (Berkeley) Date: 2001/06/25 15:19:18";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/* 
+ * ex_perl -- :[line [,line]] perl [command]
+ *     Run a command through the perl interpreter.
+ *
+ * ex_perldo -- :[line [,line]] perldo [command]
+ *     Run a set of lines through the perl interpreter.
+ *
+ * PUBLIC: int ex_perl __P((SCR*, EXCMD *));
+ */
+int 
+ex_perl(SCR *sp, EXCMD *cmdp)
+{
+#ifdef HAVE_PERL_INTERP
+       CHAR_T *p;
+       size_t len;
+
+       /* Skip leading white space. */
+       if (cmdp->argc != 0)
+               for (p = cmdp->argv[0]->bp,
+                   len = cmdp->argv[0]->len; len > 0; --len, ++p)
+                       if (!ISBLANK((UCHAR_T)*p))
+                               break;
+       if (cmdp->argc == 0 || len == 0) {
+               ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+               return (1);
+       }
+       return (cmdp->cmd == &cmds[C_PERLCMD] ?
+           perl_ex_perl(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno) :
+           perl_ex_perldo(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno));
+#else
+       msgq(sp, M_ERR, "306|Vi was not loaded with a Perl interpreter");
+       return (1);
+#endif
+}
diff --git a/dist/nvi/ex/ex_preserve.c b/dist/nvi/ex/ex_preserve.c
new file mode 100644 (file)
index 0000000..51577f4
--- /dev/null
@@ -0,0 +1,105 @@
+/*     $NetBSD: ex_preserve.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_preserve.c,v 10.15 2001/06/25 15:19:18 skimo Exp (Berkeley) Date: 2001/06/25 15:19:18";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_preserve -- :pre[serve]
+ *     Push the file to recovery.
+ *
+ * PUBLIC: int ex_preserve __P((SCR *, EXCMD *));
+ */
+int
+ex_preserve(SCR *sp, EXCMD *cmdp)
+{
+       db_recno_t lno;
+
+       NEEDFILE(sp, cmdp);
+
+       if (!F_ISSET(sp->ep, F_RCV_ON)) {
+               msgq(sp, M_ERR, "142|Preservation of this file not possible");
+               return (1);
+       }
+
+       /* If recovery not initialized, do so. */
+       if (F_ISSET(sp->ep, F_FIRSTMODIFY) && rcv_init(sp))
+               return (1);
+
+       /* Force the file to be read in, in case it hasn't yet. */
+       if (db_last(sp, &lno))
+               return (1);
+
+       /* Sync to disk. */
+       if (rcv_sync(sp, RCV_SNAPSHOT))
+               return (1);
+
+       msgq(sp, M_INFO, "143|File preserved");
+       return (0);
+}
+
+/*
+ * ex_recover -- :rec[over][!] file
+ *     Recover the file.
+ *
+ * PUBLIC: int ex_recover __P((SCR *, EXCMD *));
+ */
+int
+ex_recover(SCR *sp, EXCMD *cmdp)
+{
+       ARGS *ap;
+       FREF *frp;
+       const char *np;
+       size_t nlen;
+
+       ap = cmdp->argv[0];
+
+       /* Set the alternate file name. */
+       INT2CHAR(sp, ap->bp, ap->len+1, np, nlen);
+       set_alt_name(sp, np);
+
+       /*
+        * Check for modifications.  Autowrite did not historically
+        * affect :recover.
+        */
+       if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+               return (1);
+
+       /* Get a file structure for the file. */
+       INT2CHAR(sp, ap->bp, ap->len+1, np, nlen);
+       if ((frp = file_add(sp, np)) == NULL)
+               return (1);
+
+       /* Set the recover bit. */
+       F_SET(frp, FR_RECOVER);
+
+       /* Switch files. */
+       if (file_init(sp, frp, NULL, FS_SETALT |
+           (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+               return (1);
+
+       F_SET(sp, SC_FSWITCH);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_print.c b/dist/nvi/ex/ex_print.c
new file mode 100644 (file)
index 0000000..6ce2d9e
--- /dev/null
@@ -0,0 +1,345 @@
+/*     $NetBSD: ex_print.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_print.c,v 10.24 2001/07/29 19:07:29 skimo Exp (Berkeley) Date: 2001/07/29 19:07:29";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "../common/common.h"
+
+static int ex_prchars __P((SCR *, const CHAR_T *, size_t *, size_t, 
+                           u_int, int));
+
+/*
+ * ex_list -- :[line [,line]] l[ist] [count] [flags]
+ *
+ *     Display the addressed lines such that the output is unambiguous.
+ *
+ * PUBLIC: int ex_list __P((SCR *, EXCMD *));
+ */
+int
+ex_list(SCR *sp, EXCMD *cmdp)
+{
+       if (ex_print(sp, cmdp,
+           &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
+               return (1);
+       sp->lno = cmdp->addr2.lno;
+       sp->cno = cmdp->addr2.cno;
+       return (0);
+}
+
+/*
+ * ex_number -- :[line [,line]] nu[mber] [count] [flags]
+ *
+ *     Display the addressed lines with a leading line number.
+ *
+ * PUBLIC: int ex_number __P((SCR *, EXCMD *));
+ */
+int
+ex_number(SCR *sp, EXCMD *cmdp)
+{
+       if (ex_print(sp, cmdp,
+           &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
+               return (1);
+       sp->lno = cmdp->addr2.lno;
+       sp->cno = cmdp->addr2.cno;
+       return (0);
+}
+
+/*
+ * ex_pr -- :[line [,line]] p[rint] [count] [flags]
+ *
+ *     Display the addressed lines.
+ *
+ * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
+ */
+int
+ex_pr(SCR *sp, EXCMD *cmdp)
+{
+       if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
+               return (1);
+       sp->lno = cmdp->addr2.lno;
+       sp->cno = cmdp->addr2.cno;
+       return (0);
+}
+
+/*
+ * ex_print --
+ *     Print the selected lines.
+ *
+ * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
+ */
+int
+ex_print(SCR *sp, EXCMD *cmdp, MARK *fp, MARK *tp, u_int32_t flags)
+{
+       GS *gp;
+       db_recno_t from, to;
+       size_t col, len;
+       const CHAR_T *p;
+       CHAR_T buf[10];
+       CHAR_T *q;
+
+       NEEDFILE(sp, cmdp);
+
+       gp = sp->gp;
+       for (from = fp->lno, to = tp->lno; from <= to; ++from) {
+               col = 0;
+
+               /*
+                * Display the line number.  The %6 format is specified
+                * by POSIX 1003.2, and is almost certainly large enough.
+                * Check, though, just in case.
+                */
+               if (LF_ISSET(E_C_HASH)) {
+                       if (from <= 999999) {
+                               SPRINTF(buf, SIZE(buf), L("%6ld  "), from);
+                               p = buf;
+                       } else
+                               p = L("TOOBIG  ");
+                       if (ex_prchars(sp, p, &col, 8, 0, 0))
+                               return (1);
+               }
+
+               /*
+                * Display the line.  The format for E_C_PRINT isn't very good,
+                * especially in handling end-of-line tabs, but they're almost
+                * backward compatible.
+                */
+               if (db_get(sp, from, DBG_FATAL, &q, &len))
+                       return (1);
+               p = q;
+
+               if (len == 0 && !LF_ISSET(E_C_LIST))
+                       (void)ex_puts(sp, "\n");
+               else if (ex_ldisplay(sp, p, len, col, flags))
+                       return (1);
+
+               if (INTERRUPTED(sp))
+                       break;
+       }
+       return (0);
+}
+
+/*
+ * ex_ldisplay --
+ *     Display a line without any preceding number.
+ *
+ * PUBLIC: int ex_ldisplay __P((SCR *, const CHAR_T *, size_t, size_t, u_int));
+ */
+int
+ex_ldisplay(SCR *sp, const CHAR_T *p, size_t len, size_t col, u_int flags)
+{
+       if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
+               return (1);
+       if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
+               p = L("$");
+               if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
+                       return (1);
+       }
+       if (!INTERRUPTED(sp))
+               (void)ex_puts(sp, "\n");
+       return (0);
+}
+
+/*
+ * ex_scprint --
+ *     Display a line for the substitute with confirmation routine.
+ *
+ * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
+ */
+int
+ex_scprint(SCR *sp, MARK *fp, MARK *tp)
+{
+       const CHAR_T *p;
+       CHAR_T *q;
+       size_t col, len;
+
+       col = 0;
+       if (O_ISSET(sp, O_NUMBER)) {
+               p = L("        ");
+               if (ex_prchars(sp, p, &col, 8, 0, 0))
+                       return (1);
+       }
+
+       if (db_get(sp, fp->lno, DBG_FATAL, &q, &len))
+               return (1);
+       p = q;
+
+       if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
+               return (1);
+       p += fp->cno;
+       if (ex_prchars(sp,
+           p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
+               return (1);
+       if (INTERRUPTED(sp))
+               return (1);
+       p = L("[ynq]");         /* XXX: should be msg_cat. */
+       if (ex_prchars(sp, p, &col, 5, 0, 0))
+               return (1);
+       (void)ex_fflush(sp);
+       return (0);
+}
+
+/*
+ * ex_prchars --
+ *     Local routine to dump characters to the screen.
+ */
+static int
+ex_prchars(SCR *sp, const CHAR_T *p, size_t *colp, size_t len, 
+           u_int flags, int repeatc)
+{
+       CHAR_T ch;
+       const char *kp;
+       GS *gp;
+       size_t col, tlen, ts;
+
+       if (O_ISSET(sp, O_LIST))
+               LF_SET(E_C_LIST);
+       gp = sp->gp;
+       ts = O_VAL(sp, O_TABSTOP);
+       for (col = *colp; len--;)
+               if ((ch = *p++) == L('\t') && !LF_ISSET(E_C_LIST))
+                       for (tlen = ts - col % ts;
+                           col < sp->cols && tlen--; ++col) {
+                               (void)ex_printf(sp,
+                                   "%c", repeatc ? repeatc : ' ');
+                               if (INTERRUPTED(sp))
+                                       goto intr;
+                       }
+               else {
+                       /* XXXX */
+                       if (INTISWIDE(ch)) {
+                           CHAR_T str[2] = {0, 0};
+                           str[0] = ch;
+                           INT2CHAR(sp, str, 2, kp, tlen);
+                       } else {
+                           kp = (char *)KEY_NAME(sp, ch);
+                           tlen = KEY_LEN(sp, ch);
+                       }
+                       if (!repeatc  && col + tlen < sp->cols) {
+                               (void)ex_puts(sp, kp);
+                               col += tlen;
+                       } else
+                               for (; tlen--; ++kp, ++col) {
+                                       if (col == sp->cols) {
+                                               col = 0;
+                                               (void)ex_puts(sp, "\n");
+                                       }
+                                       (void)ex_printf(sp,
+                                           "%c", repeatc ? repeatc : *kp);
+                                       if (INTERRUPTED(sp))
+                                               goto intr;
+                               }
+               }
+intr:  *colp = col;
+       return (0);
+}
+
+/*
+ * ex_printf --
+ *     Ex's version of printf.
+ *
+ * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
+ */
+int
+#ifdef __STDC__
+ex_printf(SCR *sp, const char *fmt, ...)
+#else
+ex_printf(sp, fmt, va_alist)
+       SCR *sp;
+       const char *fmt;
+       va_dcl
+#endif
+{
+       EX_PRIVATE *exp;
+       va_list ap;
+       size_t n;
+
+       exp = EXP(sp);
+
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
+           sizeof(exp->obp) - exp->obp_len, fmt, ap);
+       va_end(ap);
+
+       /* Flush when reach a <newline> or half the buffer. */
+       if (exp->obp[exp->obp_len - 1] == '\n' ||
+           exp->obp_len > sizeof(exp->obp) / 2)
+               (void)ex_fflush(sp);
+       return (n);
+}
+
+/*
+ * ex_puts --
+ *     Ex's version of puts.
+ *
+ * PUBLIC: int ex_puts __P((SCR *, const char *));
+ */
+int
+ex_puts(SCR *sp, const char *str)
+{
+       EX_PRIVATE *exp;
+       int doflush, n;
+
+       exp = EXP(sp);
+
+       /* Flush when reach a <newline> or the end of the buffer. */
+       for (doflush = n = 0; *str != '\0'; ++n) {
+               if (exp->obp_len > sizeof(exp->obp))
+                       (void)ex_fflush(sp);
+               if ((exp->obp[exp->obp_len++] = *str++) == '\n')
+                       doflush = 1;
+       }
+       if (doflush)
+               (void)ex_fflush(sp);
+       return (n);
+}
+
+/*
+ * ex_fflush --
+ *     Ex's version of fflush.
+ *
+ * PUBLIC: int ex_fflush __P((SCR *sp));
+ */
+int
+ex_fflush(SCR *sp)
+{
+       EX_PRIVATE *exp;
+
+       exp = EXP(sp);
+
+       if (exp->obp_len != 0) {
+               sp->wp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
+               exp->obp_len = 0;
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_put.c b/dist/nvi/ex/ex_put.c
new file mode 100644 (file)
index 0000000..2e5e6f0
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $NetBSD: ex_put.c,v 1.1.1.2 2008/05/18 14:31:17 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_put.c,v 10.8 2001/06/25 15:19:18 skimo Exp (Berkeley) Date: 2001/06/25 15:19:18";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_put -- [line] pu[t] [buffer]
+ *     Append a cut buffer into the file.
+ *
+ * PUBLIC: int ex_put __P((SCR *, EXCMD *));
+ */
+int
+ex_put(SCR *sp, EXCMD *cmdp)
+{
+       MARK m;
+
+       NEEDFILE(sp, cmdp);
+
+       m.lno = sp->lno;
+       m.cno = sp->cno;
+       if (put(sp, NULL,
+           FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
+           &cmdp->addr1, &m, 1))
+               return (1);
+       sp->lno = m.lno;
+       sp->cno = m.cno;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_quit.c b/dist/nvi/ex/ex_quit.c
new file mode 100644 (file)
index 0000000..38a87d8
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: ex_quit.c,v 1.1.1.2 2008/05/18 14:31:17 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_quit.c,v 10.8 2001/06/25 15:19:18 skimo Exp (Berkeley) Date: 2001/06/25 15:19:18";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_quit -- :quit[!]
+ *     Quit.
+ *
+ * PUBLIC: int ex_quit __P((SCR *, EXCMD *));
+ */
+int
+ex_quit(SCR *sp, EXCMD *cmdp)
+{
+       int force;
+
+       force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+
+       /* Check for file modifications, or more files to edit. */
+       if (file_m2(sp, force) || ex_ncheck(sp, force))
+               return (1);
+
+       F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_read.c b/dist/nvi/ex/ex_read.c
new file mode 100644 (file)
index 0000000..d0602ed
--- /dev/null
@@ -0,0 +1,366 @@
+/*     $NetBSD: ex_read.c,v 1.4 2009/11/14 23:40:11 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_read.c,v 10.44 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_read --  :read [file]
+ *             :read [!cmd]
+ *     Read from a file or utility.
+ *
+ * !!!
+ * Historical vi wouldn't undo a filter read, for no apparent reason.
+ *
+ * PUBLIC: int ex_read __P((SCR *, EXCMD *));
+ */
+int
+ex_read(SCR *sp, EXCMD *cmdp)
+{
+       enum { R_ARG, R_EXPANDARG, R_FILTER } which;
+       struct stat sb;
+       CHAR_T *arg = NULL;
+       const char *name;
+       size_t nlen;
+       EX_PRIVATE *exp;
+       FILE *fp;
+       FREF *frp;
+       GS *gp;
+       MARK rm;
+       db_recno_t nlines;
+       size_t arglen = 0;
+       int argc, rval;
+       char *p;
+
+       gp = sp->gp;
+
+       /*
+        * 0 args: read the current pathname.
+        * 1 args: check for "read !arg".
+        */
+       switch (cmdp->argc) {
+       case 0:
+               which = R_ARG;
+               break;
+       case 1:
+               arg = cmdp->argv[0]->bp;
+               arglen = cmdp->argv[0]->len;
+               if (*arg == '!') {
+                       ++arg;
+                       --arglen;
+                       which = R_FILTER;
+
+                       /* Secure means no shell access. */
+                       if (O_ISSET(sp, O_SECURE)) {
+                               ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
+                               return (1);
+                       }
+               } else
+                       which = R_EXPANDARG;
+               break;
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+
+       /* Load a temporary file if no file being edited. */
+       if (sp->ep == NULL) {
+               if ((frp = file_add(sp, NULL)) == NULL)
+                       return (1);
+               if (file_init(sp, frp, NULL, 0))
+                       return (1);
+       }
+
+       switch (which) {
+       case R_FILTER:
+               /*
+                * File name and bang expand the user's argument.  If
+                * we don't get an additional argument, it's illegal.
+                */
+               argc = cmdp->argc;
+               if (argv_exp1(sp, cmdp, arg, arglen, 1))
+                       return (1);
+               if (argc == cmdp->argc) {
+                       ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+                       return (1);
+               }
+               argc = cmdp->argc - 1;
+
+               /* Set the last bang command. */
+               exp = EXP(sp);
+               if (exp->lastbcomm != NULL)
+                       free(exp->lastbcomm);
+               if ((exp->lastbcomm =
+                   v_wstrdup(sp, cmdp->argv[argc]->bp,
+                               cmdp->argv[argc]->len)) == NULL) {
+                       msgq(sp, M_SYSERR, NULL);
+                       return (1);
+               }
+
+               /*
+                * Vi redisplayed the user's argument if it changed, ex
+                * always displayed a !, plus the user's argument if it
+                * changed.
+                */
+               if (F_ISSET(sp, SC_VI)) {
+                       if (F_ISSET(cmdp, E_MODIFY))
+                               (void)vs_update(sp, "!", cmdp->argv[argc]->bp);
+               } else {
+                       if (F_ISSET(cmdp, E_MODIFY)) {
+                               INT2CHAR(sp, cmdp->argv[argc]->bp,
+                                   cmdp->argv[argc]->len + 1, name, nlen);
+                               (void)ex_printf(sp,
+                                   "!%s\n", name);
+                       } else
+                               (void)ex_puts(sp, "!\n");
+                       (void)ex_fflush(sp);
+               }
+
+               /*
+                * Historically, filter reads as the first ex command didn't
+                * wait for the user. If SC_SCR_EXWROTE not already set, set
+                * the don't-wait flag.
+                */
+               if (!F_ISSET(sp, SC_SCR_EXWROTE))
+                       F_SET(sp, SC_EX_WAIT_NO);
+
+               /*
+                * Switch into ex canonical mode.  The reason to restore the
+                * original terminal modes for read filters is so that users
+                * can do things like ":r! cat /dev/tty".
+                *
+                * !!!
+                * We do not output an extra <newline>, so that we don't touch
+                * the screen on a normal read.
+                */
+               if (F_ISSET(sp, SC_VI)) {
+                       if (gp->scr_screen(sp, SC_EX)) {
+                               ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
+                               return (1);
+                       }
+                       /*
+                        * !!!
+                        * Historically, the read command doesn't switch to
+                        * the alternate X11 xterm screen, if doing a filter
+                        * read -- don't set SA_ALTERNATE.
+                        */
+                       F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
+               }
+
+               if (ex_filter(sp, cmdp, &cmdp->addr1,
+                   NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
+                       return (1);
+
+               /* The filter version of read set the autoprint flag. */
+               F_SET(cmdp, E_AUTOPRINT);
+
+               /*
+                * If in vi mode, move to the first nonblank.  Might have
+                * switched into ex mode, so saved the original SC_VI value.
+                */
+               sp->lno = rm.lno;
+               if (F_ISSET(sp, SC_VI)) {
+                       sp->cno = 0;
+                       (void)nonblank(sp, sp->lno, &sp->cno);
+               }
+               return (0);
+       case R_ARG:
+               name = sp->frp->name;
+               break;
+       case R_EXPANDARG:
+               if (argv_exp2(sp, cmdp, arg, arglen))
+                       return (1);
+               /*
+                *  0 args: impossible.
+                *  1 args: impossible (I hope).
+                *  2 args: read it.
+                * >2 args: object, too many args.
+                *
+                * The 1 args case depends on the argv_sexp() function refusing
+                * to return success without at least one non-blank character.
+                */
+               switch (cmdp->argc) {
+               case 0:
+               case 1:
+                       abort();
+                       /* NOTREACHED */
+               case 2:
+                       INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len + 1, 
+                                name, nlen);
+                       /*
+                        * !!!
+                        * Historically, the read and write commands renamed
+                        * "unnamed" files, or, if the file had a name, set
+                        * the alternate file name.
+                        */
+                       if (F_ISSET(sp->frp, FR_TMPFILE) &&
+                           !F_ISSET(sp->frp, FR_EXNAMED)) {
+                               if ((p = strdup(name)) != NULL) {
+                                       free(sp->frp->name);
+                                       sp->frp->name = p;
+                               }
+                               /*
+                                * The file has a real name, it's no longer a
+                                * temporary, clear the temporary file flags.
+                                */
+                               F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
+                               F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
+
+                               /* Notify the screen. */
+                               (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+                               name = sp->frp->name;
+                       } else {
+                               set_alt_name(sp, name);
+                               name = sp->alt_name;
+                       }
+                       break;
+               default:
+                       ex_wemsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
+                       return (1);
+               
+               }
+               break;
+       }
+
+       /*
+        * !!!
+        * Historically, vi did not permit reads from non-regular files, nor
+        * did it distinguish between "read !" and "read!", so there was no
+        * way to "force" it.  We permit reading from named pipes too, since
+        * they didn't exist when the original implementation of vi was done
+        * and they seem a reasonable addition.
+        */
+       if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
+               msgq_str(sp, M_SYSERR, name, "%s");
+               return (1);
+       }
+       if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
+               (void)fclose(fp);
+               msgq(sp, M_ERR,
+                   "145|Only regular files and named pipes may be read");
+               return (1);
+       }
+
+       /* Try and get a lock. */
+       if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
+               msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
+
+       rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
+
+       /*
+        * In vi, set the cursor to the first line read in, if anything read
+        * in, otherwise, the address.  (Historic vi set it to the line after
+        * the address regardless, but since that line may not exist we don't
+        * bother.)
+        *
+        * In ex, set the cursor to the last line read in, if anything read in,
+        * otherwise, the address.
+        */
+       if (F_ISSET(sp, SC_VI)) {
+               sp->lno = cmdp->addr1.lno;
+               if (nlines)
+                       ++sp->lno;
+       } else
+               sp->lno = cmdp->addr1.lno + nlines;
+       return (rval);
+}
+
+/*
+ * ex_readfp --
+ *     Read lines into the file.
+ *
+ * PUBLIC: int ex_readfp __P((SCR *, char *, FILE *, MARK *, db_recno_t *, int));
+ */
+int
+ex_readfp(SCR *sp, const char *name, FILE *fp, MARK *fm, db_recno_t *nlinesp, int silent)
+{
+       EX_PRIVATE *exp;
+       GS *gp;
+       db_recno_t lcnt, lno;
+       size_t len;
+       u_long ccnt;                    /* XXX: can't print off_t portably. */
+       int nf, rval;
+       const char *p;
+       size_t wlen;
+       const CHAR_T *wp;
+
+       gp = sp->gp;
+       exp = EXP(sp);
+
+       /*
+        * Add in the lines from the output.  Insertion starts at the line
+        * following the address.
+        */
+       ccnt = 0;
+       lcnt = 0;
+       p = "147|Reading...";
+       for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
+               if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
+                       if (INTERRUPTED(sp))
+                               break;
+                       if (!silent) {
+                               gp->scr_busy(sp, p,
+                                   p == NULL ? BUSY_UPDATE : BUSY_ON);
+                               p = NULL;
+                       }
+               }
+               FILE2INT5(sp, exp->ibcw, exp->ibp, len, wp, wlen);
+               if (db_append(sp, 1, lno, wp, wlen))
+                       goto err;
+               ccnt += len;
+       }
+
+       if (ferror(fp) || fclose(fp))
+               goto err;
+
+       /* Return the number of lines read in. */
+       if (nlinesp != NULL)
+               *nlinesp = lcnt;
+
+       if (!silent) {
+               char *q = msg_print(sp, name, &nf);
+               msgq(sp, M_INFO,
+                   "148|%s: %lu lines, %lu characters", q, (unsigned long)lcnt,
+                   (unsigned long)ccnt);
+               if (nf)
+                       FREE_SPACE(sp, q, 0);
+       }
+
+       rval = 0;
+       if (0) {
+err:           msgq_str(sp, M_SYSERR, name, "%s");
+               (void)fclose(fp);
+               rval = 1;
+       }
+
+       if (!silent)
+               gp->scr_busy(sp, NULL, BUSY_OFF);
+       return (rval);
+}
diff --git a/dist/nvi/ex/ex_screen.c b/dist/nvi/ex/ex_screen.c
new file mode 100644 (file)
index 0000000..8b0930f
--- /dev/null
@@ -0,0 +1,134 @@
+/*     $NetBSD: ex_screen.c,v 1.2 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_screen.c,v 10.12 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_bg --    :bg
+ *     Hide the screen.
+ *
+ * PUBLIC: int ex_bg __P((SCR *, EXCMD *));
+ */
+int
+ex_bg(SCR *sp, EXCMD *cmdp)
+{
+       return (vs_bg(sp));
+}
+
+/*
+ * ex_fg --    :fg [file]
+ *     Show the screen.
+ *
+ * PUBLIC: int ex_fg __P((SCR *, EXCMD *));
+ */
+int
+ex_fg(SCR *sp, EXCMD *cmdp)
+{
+       SCR *nsp;
+       int newscreen;
+
+       newscreen = F_ISSET(cmdp, E_NEWSCREEN);
+       if (vs_fg(sp, &nsp, cmdp->argc ? cmdp->argv[0]->bp : NULL, newscreen))
+               return (1);
+
+       /* Set up the switch. */
+       if (newscreen) {
+               sp->nextdisp = nsp;
+               F_SET(sp, SC_SSWITCH);
+       }
+       return (0);
+}
+
+/*
+ * ex_resize --        :resize [+-]rows
+ *     Change the screen size.
+ *
+ * PUBLIC: int ex_resize __P((SCR *, EXCMD *));
+ */
+int
+ex_resize(SCR *sp, EXCMD *cmdp)
+{
+       adj_t adj;
+
+       switch (FL_ISSET(cmdp->iflags,
+           E_C_COUNT | E_C_COUNT_NEG | E_C_COUNT_POS)) {
+       case E_C_COUNT:
+               adj = A_SET;
+               break;
+       case E_C_COUNT | E_C_COUNT_NEG:
+               adj = A_DECREASE;
+               break;
+       case E_C_COUNT | E_C_COUNT_POS:
+               adj = A_INCREASE;
+               break;
+       default:
+               ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+               return (1);
+       }
+       return (vs_resize(sp, cmdp->count, adj));
+}
+
+/*
+ * ex_sdisplay --
+ *     Display the list of screens.
+ *
+ * PUBLIC: int ex_sdisplay __P((SCR *));
+ */
+int
+ex_sdisplay(SCR *sp)
+{
+       GS *gp;
+       SCR *tsp;
+       int cnt, sep;
+       size_t col, len;
+
+       gp = sp->gp;
+       if ((tsp = gp->hq.cqh_first) == (void *)&gp->hq) {
+               msgq(sp, M_INFO, "149|No background screens to display");
+               return (0);
+       }
+
+       col = len = sep = 0;
+       for (cnt = 1; tsp != (void *)&gp->hq && !INTERRUPTED(sp);
+           tsp = tsp->q.cqe_next) {
+               col += len = strlen(tsp->frp->name) + sep;
+               if (col >= sp->cols - 1) {
+                       col = len;
+                       sep = 0;
+                       (void)ex_puts(sp, "\n");
+               } else if (cnt != 1) {
+                       sep = 1;
+                       (void)ex_puts(sp, " ");
+               }
+               (void)ex_puts(sp, tsp->frp->name);
+               ++cnt;
+       }
+       if (!INTERRUPTED(sp))
+               (void)ex_puts(sp, "\n");
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_script.c b/dist/nvi/ex/ex_script.c
new file mode 100644 (file)
index 0000000..fe15281
--- /dev/null
@@ -0,0 +1,835 @@
+/*     $NetBSD: ex_script.c,v 1.5 2011/11/23 19:18:53 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Brian Hirt.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_script.c,v 10.38 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/stat.h>
+#if defined(HAVE_SYS5_PTY) && !defined(__NetBSD__)
+#include <sys/stropts.h>
+#endif
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>             /* XXX: OSF/1 bug: include before <grp.h> */
+#include <grp.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "script.h"
+#include "pathnames.h"
+
+static void    sscr_check __P((SCR *));
+static int     sscr_getprompt __P((SCR *));
+static int     sscr_init __P((SCR *));
+static int     sscr_insert __P((SCR *));
+static int     sscr_matchprompt __P((SCR *, CHAR_T *, size_t, size_t *));
+static int     sscr_pty __P((int *, int *, char *, struct termios *, void *));
+static int     sscr_setprompt __P((SCR *, CHAR_T *, size_t));
+
+/*
+ * ex_script -- : sc[ript][!] [file]
+ *     Switch to script mode.
+ *
+ * PUBLIC: int ex_script __P((SCR *, EXCMD *));
+ */
+int
+ex_script(SCR *sp, EXCMD *cmdp)
+{
+       /* Vi only command. */
+       if (!F_ISSET(sp, SC_VI)) {
+               msgq(sp, M_ERR,
+                   "150|The script command is only available in vi mode");
+               return (1);
+       }
+
+       /* Switch to the new file. */
+       if (cmdp->argc != 0 && ex_edit(sp, cmdp))
+               return (1);
+
+       /* Create the shell, figure out the prompt. */
+       if (sscr_init(sp))
+               return (1);
+
+       return (0);
+}
+
+/*
+ * sscr_init --
+ *     Create a pty setup for a shell.
+ */
+static int
+sscr_init(SCR *sp)
+{
+       SCRIPT *sc;
+       const char *sh, *sh_path;
+
+       /* We're going to need a shell. */
+       if (opts_empty(sp, O_SHELL, 0))
+               return (1);
+
+       MALLOC_RET(sp, sc, SCRIPT *, sizeof(SCRIPT));
+       sp->script = sc;
+       sc->sh_prompt = NULL;
+       sc->sh_prompt_len = 0;
+
+       /*
+        * There are two different processes running through this code.
+        * They are the shell and the parent.
+        */
+       sc->sh_master = sc->sh_slave = -1;
+
+       if (tcgetattr(STDIN_FILENO, &sc->sh_term) == -1) {
+               msgq(sp, M_SYSERR, "tcgetattr");
+               goto err;
+       }
+
+       /*
+        * Turn off output postprocessing and echo.
+        */
+       sc->sh_term.c_oflag &= ~OPOST;
+       sc->sh_term.c_cflag &= ~(ECHO|ECHOE|ECHONL|ECHOK);
+
+#ifdef TIOCGWINSZ
+       if (ioctl(STDIN_FILENO, TIOCGWINSZ, &sc->sh_win) == -1) {
+               msgq(sp, M_SYSERR, "tcgetattr");
+               goto err;
+       }
+
+       if (sscr_pty(&sc->sh_master,
+           &sc->sh_slave, sc->sh_name, &sc->sh_term, &sc->sh_win) == -1) {
+               msgq(sp, M_SYSERR, "pty");
+               goto err;
+       }
+#else
+       if (sscr_pty(&sc->sh_master,
+           &sc->sh_slave, sc->sh_name, &sc->sh_term, NULL) == -1) {
+               msgq(sp, M_SYSERR, "pty");
+               goto err;
+       }
+#endif
+
+       /*
+        * __TK__ huh?
+        * Don't use vfork() here, because the signal semantics differ from
+        * implementation to implementation.
+        */
+       switch (sc->sh_pid = fork()) {
+       case -1:                        /* Error. */
+               msgq(sp, M_SYSERR, "fork");
+err:           if (sc->sh_master != -1)
+                       (void)close(sc->sh_master);
+               if (sc->sh_slave != -1)
+                       (void)close(sc->sh_slave);
+               return (1);
+       case 0:                         /* Utility. */
+               /*
+                * XXX
+                * So that shells that do command line editing turn it off.
+                */
+               (void)setenv("TERM", "emacs", 1);
+               (void)setenv("TERMCAP", "emacs:", 1);
+               (void)setenv("EMACS", "t", 1);
+
+               (void)setsid();
+#ifdef TIOCSCTTY
+               /*
+                * 4.4BSD allocates a controlling terminal using the TIOCSCTTY
+                * ioctl, not by opening a terminal device file.  POSIX 1003.1
+                * doesn't define a portable way to do this.  If TIOCSCTTY is
+                * not available, hope that the open does it.
+                */
+               (void)ioctl(sc->sh_slave, TIOCSCTTY, 0);
+#endif
+               (void)close(sc->sh_master);
+               (void)dup2(sc->sh_slave, STDIN_FILENO);
+               (void)dup2(sc->sh_slave, STDOUT_FILENO);
+               (void)dup2(sc->sh_slave, STDERR_FILENO);
+               (void)close(sc->sh_slave);
+
+               /* Assumes that all shells have -i. */
+               sh_path = O_STR(sp, O_SHELL);
+               if ((sh = strrchr(sh_path, '/')) == NULL)
+                       sh = sh_path;
+               else
+                       ++sh;
+               execl(sh_path, sh, "-i", NULL);
+               msgq_str(sp, M_SYSERR, sh_path, "execl: %s");
+               _exit(127);
+       default:                        /* Parent. */
+               break;
+       }
+
+       if (sscr_getprompt(sp))
+               return (1);
+
+       F_SET(sp, SC_SCRIPT);
+       F_SET(sp->gp, G_SCRWIN);
+       return (0);
+}
+
+/*
+ * sscr_getprompt --
+ *     Eat lines printed by the shell until a line with no trailing
+ *     carriage return comes; set the prompt from that line.
+ */
+static int
+sscr_getprompt(SCR *sp)
+{
+       struct timeval tv;
+       CHAR_T *endp, *p, *t, buf[1024];
+       SCRIPT *sc;
+       fd_set fdset;
+       db_recno_t lline;
+       size_t llen, len;
+       e_key_t value;
+       int nr;
+
+       FD_ZERO(&fdset);
+       endp = buf;
+       len = sizeof(buf);
+
+       /* Wait up to a second for characters to read. */
+       tv.tv_sec = 5;
+       tv.tv_usec = 0;
+       sc = sp->script;
+       FD_SET(sc->sh_master, &fdset);
+       switch (select(sc->sh_master + 1, &fdset, NULL, NULL, &tv)) {
+       case -1:                /* Error or interrupt. */
+               msgq(sp, M_SYSERR, "select");
+               goto prompterr;
+       case  0:                /* Timeout */
+               msgq(sp, M_ERR, "Error: timed out");
+               goto prompterr;
+       case  1:                /* Characters to read. */
+               break;
+       }
+
+       /* Read the characters. */
+more:  len = sizeof(buf) - (endp - buf);
+       switch (nr = read(sc->sh_master, endp, len)) {
+       case  0:                        /* EOF. */
+               msgq(sp, M_ERR, "Error: shell: EOF");
+               goto prompterr;
+       case -1:                        /* Error or interrupt. */
+               msgq(sp, M_SYSERR, "shell");
+               goto prompterr;
+       default:
+               endp += nr;
+               break;
+       }
+
+       /* If any complete lines, push them into the file. */
+       for (p = t = buf; p < endp; ++p) {
+               value = KEY_VAL(sp, *p);
+               if (value == K_CR || value == K_NL) {
+                       if (db_last(sp, &lline) ||
+                           db_append(sp, 0, lline, t, p - t))
+                               goto prompterr;
+                       t = p + 1;
+               }
+       }
+       if (p > buf) {
+               MEMMOVE(buf, t, endp - t);
+               endp = buf + (endp - t);
+       }
+       if (endp == buf)
+               goto more;
+
+       /* Wait up 1/10 of a second to make sure that we got it all. */
+       tv.tv_sec = 0;
+       tv.tv_usec = 100000;
+       switch (select(sc->sh_master + 1, &fdset, NULL, NULL, &tv)) {
+       case -1:                /* Error or interrupt. */
+               msgq(sp, M_SYSERR, "select");
+               goto prompterr;
+       case  0:                /* Timeout */
+               break;
+       case  1:                /* Characters to read. */
+               goto more;
+       }
+
+       /* Timed out, so theoretically we have a prompt. */
+       llen = endp - buf;
+       endp = buf;
+
+       /* Append the line into the file. */
+       if (db_last(sp, &lline) || db_append(sp, 0, lline, buf, llen)) {
+prompterr:     sscr_end(sp);
+               return (1);
+       }
+
+       return (sscr_setprompt(sp, buf, llen));
+}
+
+/*
+ * sscr_exec --
+ *     Take a line and hand it off to the shell.
+ *
+ * PUBLIC: int sscr_exec __P((SCR *, db_recno_t));
+ */
+int
+sscr_exec(SCR *sp, db_recno_t lno)
+{
+       SCRIPT *sc;
+       db_recno_t last_lno;
+       size_t blen, len, last_len, tlen;
+       int isempty, matchprompt, rval;
+       ssize_t nw;
+       CHAR_T *bp = NULL;
+       CHAR_T *p;
+
+       /* If there's a prompt on the last line, append the command. */
+       if (db_last(sp, &last_lno))
+               return (1);
+       if (db_get(sp, last_lno, DBG_FATAL, &p, &last_len))
+               return (1);
+       if (sscr_matchprompt(sp, p, last_len, &tlen) && tlen == 0) {
+               matchprompt = 1;
+               GET_SPACE_RETW(sp, bp, blen, last_len + 128);
+               MEMMOVEW(bp, p, last_len);
+       } else
+               matchprompt = 0;
+
+       /* Get something to execute. */
+       if (db_eget(sp, lno, &p, &len, &isempty)) {
+               if (isempty)
+                       goto empty;
+               goto err1;
+       }
+
+       /* Empty lines aren't interesting. */
+       if (len == 0)
+               goto empty;
+
+       /* Delete any prompt. */
+       if (sscr_matchprompt(sp, p, len, &tlen)) {
+               if (tlen == len) {
+empty:                 msgq(sp, M_BERR, "151|No command to execute");
+                       goto err1;
+               }
+               p += (len - tlen);
+               len = tlen;
+       }
+
+       /* Push the line to the shell. */
+       sc = sp->script;
+       if ((size_t)(nw = write(sc->sh_master, p, len)) != len)
+               goto err2;
+       rval = 0;
+       if (write(sc->sh_master, "\n", 1) != 1) {
+err2:          if (nw == 0)
+                       errno = EIO;
+               msgq(sp, M_SYSERR, "shell");
+               goto err1;
+       }
+
+       if (matchprompt) {
+               ADD_SPACE_RETW(sp, bp, blen, last_len + len);
+               MEMMOVEW(bp + last_len, p, len);
+               if (db_set(sp, last_lno, bp, last_len + len))
+err1:                  rval = 1;
+       }
+       if (matchprompt)
+               FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
+
+/*
+ * sscr_check_input -
+ *     Check whether any input from shell or passed set.
+ *
+ * PUBLIC: int sscr_check_input __P((SCR *sp, fd_set *rdfd, int maxfd));
+ */
+int
+sscr_check_input(SCR *sp, fd_set *fdset, int maxfd)
+{
+       fd_set rdfd;
+       SCR *tsp;
+       WIN *wp;
+
+       wp = sp->wp;
+
+loop:  memcpy(&rdfd, fdset, sizeof(fd_set));
+
+       for (tsp = wp->scrq.cqh_first; 
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
+               if (F_ISSET(sp, SC_SCRIPT)) {
+                       FD_SET(sp->script->sh_master, &rdfd);
+                       if (sp->script->sh_master > maxfd)
+                               maxfd = sp->script->sh_master;
+               }
+       switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
+       case 0:
+               abort();
+       case -1:
+               return 1;
+       default:
+               break;
+       }
+       for (tsp = wp->scrq.cqh_first; 
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
+               if (F_ISSET(sp, SC_SCRIPT) &&
+                   FD_ISSET(sp->script->sh_master, &rdfd)) {
+                       if (sscr_input(sp))
+                               return 1;
+                       goto loop;
+               }
+       return 0;
+}
+
+/*
+ * sscr_input --
+ *     Read any waiting shell input.
+ *
+ * PUBLIC: int sscr_input __P((SCR *));
+ */
+int
+sscr_input(SCR *sp)
+{
+       GS *gp;
+       WIN *wp;
+       struct timeval poll;
+       fd_set rdfd;
+       int maxfd;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+loop:  maxfd = 0;
+       FD_ZERO(&rdfd);
+       poll.tv_sec = 0;
+       poll.tv_usec = 0;
+
+       /* Set up the input mask. */
+       for (sp = wp->scrq.cqh_first; sp != (void *)&wp->scrq; 
+           sp = sp->q.cqe_next)
+               if (F_ISSET(sp, SC_SCRIPT)) {
+                       FD_SET(sp->script->sh_master, &rdfd);
+                       if (sp->script->sh_master > maxfd)
+                               maxfd = sp->script->sh_master;
+               }
+
+       /* Check for input. */
+       switch (select(maxfd + 1, &rdfd, NULL, NULL, &poll)) {
+       case -1:
+               msgq(sp, M_SYSERR, "select");
+               return (1);
+       case 0:
+               return (0);
+       default:
+               break;
+       }
+
+       /* Read the input. */
+       for (sp = wp->scrq.cqh_first; sp != (void *)&wp->scrq; 
+           sp = sp->q.cqe_next)
+               if (F_ISSET(sp, SC_SCRIPT) &&
+                   FD_ISSET(sp->script->sh_master, &rdfd) && 
+                   sscr_insert(sp))
+                       return (1);
+       goto loop;
+}
+
+/*
+ * sscr_insert --
+ *     Take a line from the shell and insert it into the file.
+ */
+static int
+sscr_insert(SCR *sp)
+{
+       struct timeval tv;
+       CHAR_T *endp, *p, *t;
+       SCRIPT *sc;
+       fd_set rdfd;
+       db_recno_t lno;
+       size_t blen, len = 0, tlen;
+       e_key_t value;
+       int nr, rval;
+       CHAR_T *bp;
+
+       /* Find out where the end of the file is. */
+       if (db_last(sp, &lno))
+               return (1);
+
+#define        MINREAD 1024
+       GET_SPACE_RETW(sp, bp, blen, MINREAD);
+       endp = bp;
+
+       /* Read the characters. */
+       rval = 1;
+       sc = sp->script;
+more:  switch (nr = read(sc->sh_master, endp, MINREAD)) {
+       case  0:                        /* EOF; shell just exited. */
+               sscr_end(sp);
+               rval = 0;
+               goto ret;
+       case -1:                        /* Error or interrupt. */
+               msgq(sp, M_SYSERR, "shell");
+               goto ret;
+       default:
+               endp += nr;
+               break;
+       }
+
+       /* Append the lines into the file. */
+       for (p = t = bp; p < endp; ++p) {
+               value = KEY_VAL(sp, *p);
+               if (value == K_CR || value == K_NL) {
+                       len = p - t;
+                       if (db_append(sp, 1, lno++, t, len))
+                               goto ret;
+                       t = p + 1;
+               }
+       }
+       if (p > t) {
+               len = p - t;
+               /*
+                * If the last thing from the shell isn't another prompt, wait
+                * up to 1/10 of a second for more stuff to show up, so that
+                * we don't break the output into two separate lines.  Don't
+                * want to hang indefinitely because some program is hanging,
+                * confused the shell, or whatever.
+                */
+               if (!sscr_matchprompt(sp, t, len, &tlen) || tlen != 0) {
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 100000;
+                       FD_ZERO(&rdfd);
+                       FD_SET(sc->sh_master, &rdfd);
+                       if (select(sc->sh_master + 1,
+                           &rdfd, NULL, NULL, &tv) == 1) {
+                               MEMMOVE(bp, t, len);
+                               endp = bp + len;
+                               goto more;
+                       }
+               }
+               if (sscr_setprompt(sp, t, len))
+                       return (1);
+               if (db_append(sp, 1, lno++, t, len))
+                       goto ret;
+       }
+
+       /* The cursor moves to EOF. */
+       sp->lno = lno;
+       sp->cno = len ? len - 1 : 0;
+       rval = vs_refresh(sp, 1);
+
+ret:   FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
+
+/*
+ * sscr_setprompt --
+ *
+ * Set the prompt to the last line we got from the shell.
+ *
+ */
+static int
+sscr_setprompt(SCR *sp, CHAR_T *buf, size_t len)
+{
+       SCRIPT *sc;
+       const char *np;
+       size_t nlen;
+
+       sc = sp->script;
+       if (sc->sh_prompt)
+               free(sc->sh_prompt);
+       MALLOC(sp, sc->sh_prompt, char *, len + 1);
+       if (sc->sh_prompt == NULL) {
+               sscr_end(sp);
+               return (1);
+       }
+       INT2CHAR(sp, buf, len, np, nlen);
+       memmove(sc->sh_prompt, np, nlen);
+       sc->sh_prompt_len = len;
+       sc->sh_prompt[len] = '\0';
+       return (0);
+}
+
+/*
+ * sscr_matchprompt --
+ *     Check to see if a line matches the prompt.  Nul's indicate
+ *     parts that can change, in both content and size.
+ */
+static int
+sscr_matchprompt(SCR *sp, CHAR_T *lp, size_t line_len, size_t *lenp)
+{
+       SCRIPT *sc;
+       size_t prompt_len;
+       char *pp;
+
+       sc = sp->script;
+       if (line_len < (prompt_len = sc->sh_prompt_len))
+               return (0);
+
+       for (pp = sc->sh_prompt;
+           prompt_len && line_len; --prompt_len, --line_len) {
+               if (*pp == '\0') {
+                       for (; prompt_len && *pp == '\0'; --prompt_len, ++pp);
+                       if (!prompt_len)
+                               return (0);
+                       for (; line_len && *lp != *pp; --line_len, ++lp);
+                       if (!line_len)
+                               return (0);
+               }
+               if (*pp++ != *lp++)
+                       break;
+       }
+
+       if (prompt_len)
+               return (0);
+       if (lenp != NULL)
+               *lenp = line_len;
+       return (1);
+}
+
+/*
+ * sscr_end --
+ *     End the pipe to a shell.
+ *
+ * PUBLIC: int sscr_end __P((SCR *));
+ */
+int
+sscr_end(SCR *sp)
+{
+       SCRIPT *sc;
+
+       if ((sc = sp->script) == NULL)
+               return (0);
+
+       /* Turn off the script flags. */
+       F_CLR(sp, SC_SCRIPT);
+       sscr_check(sp);
+
+       /* Close down the parent's file descriptors. */
+       if (sc->sh_master != -1)
+           (void)close(sc->sh_master);
+       if (sc->sh_slave != -1)
+           (void)close(sc->sh_slave);
+
+       /* This should have killed the child. */
+       (void)proc_wait(sp, (long)sc->sh_pid, "script-shell", 0, 0);
+
+       /* Free memory. */
+       free(sc->sh_prompt);
+       free(sc);
+       sp->script = NULL;
+
+       return (0);
+}
+
+/*
+ * sscr_check --
+ *     Set/clear the global scripting bit.
+ */
+static void
+sscr_check(SCR *sp)
+{
+       GS *gp;
+       WIN *wp;
+
+       gp = sp->gp;
+       wp = sp->wp;
+       for (sp = wp->scrq.cqh_first; sp != (void *)&wp->scrq; 
+           sp = sp->q.cqe_next)
+               if (F_ISSET(sp, SC_SCRIPT)) {
+                       F_SET(gp, G_SCRWIN);
+                       return;
+               }
+       F_CLR(gp, G_SCRWIN);
+}
+
+#ifdef HAVE_SYS5_PTY
+static int ptys_open __P((int, char *));
+static int ptym_open __P((char *));
+
+static int
+sscr_pty(int *amaster, int *aslave, char *name, struct termios *termp, void *winp)
+{
+       int master, slave;
+
+       /* open master terminal */
+       if ((master = ptym_open(name)) < 0)  {
+               errno = ENOENT; /* out of ptys */
+               return (-1);
+       }
+
+       /* open slave terminal */
+       if ((slave = ptys_open(master, name)) >= 0) {
+               *amaster = master;
+               *aslave = slave;
+       } else {
+               errno = ENOENT; /* out of ptys */
+               return (-1);
+       }
+
+       if (termp)
+               (void) tcsetattr(slave, TCSAFLUSH, termp);
+#ifdef TIOCSWINSZ
+       if (winp != NULL)
+               (void) ioctl(slave, TIOCSWINSZ, (struct winsize *)winp);
+#endif
+       return (0);
+}
+
+/*
+ * ptym_open --
+ *     This function opens a master pty and returns the file descriptor
+ *     to it.  pts_name is also returned which is the name of the slave.
+ */
+static int
+ptym_open(char *pts_name)
+{
+       int fdm;
+       char *ptr;
+
+       strcpy(pts_name, _PATH_SYSV_PTY);
+       if ((fdm = open(pts_name, O_RDWR)) < 0 )
+               return (-1);
+
+       if (grantpt(fdm) < 0) {
+               close(fdm);
+               return (-2);
+       }
+
+       if (unlockpt(fdm) < 0) {
+               close(fdm);
+               return (-3);
+       }
+
+       if (unlockpt(fdm) < 0) {
+               close(fdm);
+               return (-3);
+       }
+
+       /* get slave's name */
+       if ((ptr = ptsname(fdm)) == NULL) {
+               close(fdm);
+               return (-3);
+       }
+       strcpy(pts_name, ptr);
+       return (fdm);
+}
+
+/*
+ * ptys_open --
+ *     This function opens the slave pty.
+ */
+static int
+ptys_open(int fdm, char *pts_name)
+{
+       int fds;
+
+       if ((fds = open(pts_name, O_RDWR)) < 0) {
+               close(fdm);
+               return (-5);
+       }
+
+#ifdef I_PUSH
+       if (ioctl(fds, I_PUSH, "ptem") < 0) {
+               close(fds);
+               close(fdm);
+               return (-6);
+       }
+
+       if (ioctl(fds, I_PUSH, "ldterm") < 0) {
+               close(fds);
+               close(fdm);
+               return (-7);
+       }
+
+       if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
+               close(fds);
+               close(fdm);
+               return (-8);
+       }
+#endif /* I_PUSH */
+
+       return (fds);
+}
+
+#else /* !HAVE_SYS5_PTY */
+
+static int
+sscr_pty(amaster, aslave, name, termp, winp)
+       int *amaster, *aslave;
+       char *name;
+       struct termios *termp;
+       void *winp;
+{
+       static char line[] = "/dev/ptyXX";
+       register char *cp1, *cp2;
+       register int master, slave, ttygid;
+       struct group *gr;
+
+       if ((gr = getgrnam("tty")) != NULL)
+               ttygid = gr->gr_gid;
+       else
+               ttygid = -1;
+
+       for (cp1 = "pqrs"; *cp1; cp1++) {
+               line[8] = *cp1;
+               for (cp2 = "0123456789abcdef"; *cp2; cp2++) {
+                       line[5] = 'p';
+                       line[9] = *cp2;
+                       if ((master = open(line, O_RDWR, 0)) == -1) {
+                               if (errno == ENOENT)
+                                       return (-1);    /* out of ptys */
+                       } else {
+                               line[5] = 't';
+                               (void) chown(line, getuid(), ttygid);
+                               (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
+#ifdef HAVE_REVOKE
+                               (void) revoke(line);
+#endif
+                               if ((slave = open(line, O_RDWR, 0)) != -1) {
+                                       *amaster = master;
+                                       *aslave = slave;
+                                       if (name)
+                                               strcpy(name, line);
+                                       if (termp)
+                                               (void) tcsetattr(slave, 
+                                                       TCSAFLUSH, termp);
+#ifdef TIOCSWINSZ
+                                       if (winp)
+                                               (void) ioctl(slave, TIOCSWINSZ, 
+                                                       (char *)winp);
+#endif
+                                       return (0);
+                               }
+                               (void) close(master);
+                       }
+               }
+       }
+       errno = ENOENT; /* out of ptys */
+       return (-1);
+}
+#endif /* HAVE_SYS5_PTY */
diff --git a/dist/nvi/ex/ex_set.c b/dist/nvi/ex/ex_set.c
new file mode 100644 (file)
index 0000000..7dfa4b3
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: ex_set.c,v 1.1.1.2 2008/05/18 14:31:17 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_set.c,v 10.8 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_set -- :set
+ *     Ex set option.
+ *
+ * PUBLIC: int ex_set __P((SCR *, EXCMD *));
+ */
+int
+ex_set(SCR *sp, EXCMD *cmdp)
+{
+       switch(cmdp->argc) {
+       case 0:
+               opts_dump(sp, CHANGED_DISPLAY);
+               break;
+       default:
+               if (opts_set(sp, cmdp->argv, cmdp->cmd->usage))
+                       return (1);
+               break;
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_shell.c b/dist/nvi/ex/ex_shell.c
new file mode 100644 (file)
index 0000000..0d4065c
--- /dev/null
@@ -0,0 +1,371 @@
+/*     $NetBSD: ex_shell.c,v 1.5 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_shell.c,v 10.42 2003/11/05 17:11:54 skimo Exp (Berkeley) Date: 2003/11/05 17:11:54";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/wait.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+static const char *sigmsg __P((int));
+
+/*
+ * ex_shell -- :sh[ell]
+ *     Invoke the program named in the SHELL environment variable
+ *     with the argument -i.
+ *
+ * PUBLIC: int ex_shell __P((SCR *, EXCMD *));
+ */
+int
+ex_shell(SCR *sp, EXCMD *cmdp)
+{
+       int rval;
+       char buf[MAXPATHLEN];
+
+       /* We'll need a shell. */
+       if (opts_empty(sp, O_SHELL, 0))
+               return (1);
+
+       /*
+        * XXX
+        * Assumes all shells use -i.
+        */
+       (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
+
+       /* Restore the window name. */
+       (void)sp->gp->scr_rename(sp, NULL, 0);
+
+       /* If we're still in a vi screen, move out explicitly. */
+       rval = ex_exec_proc(sp, cmdp, buf, NULL, !F_ISSET(sp, SC_SCR_EXWROTE));
+
+       /* Set the window name. */
+       (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+       /*
+        * !!!
+        * Historically, vi didn't require a continue message after the
+        * return of the shell.  Match it.
+        */
+       F_SET(sp, SC_EX_WAIT_NO);
+
+       return (rval);
+}
+
+/*
+ * ex_exec_proc --
+ *     Run a separate process.
+ *
+ * PUBLIC: int ex_exec_proc __P((SCR *, EXCMD *, const char *, const char *, int));
+ */
+int
+ex_exec_proc(SCR *sp, EXCMD *cmdp, const char *cmd, const char *msg, int need_newline)
+{
+       GS *gp;
+       const char *name;
+       pid_t pid;
+
+       gp = sp->gp;
+
+       /* We'll need a shell. */
+       if (opts_empty(sp, O_SHELL, 0))
+               return (1);
+
+       /* Enter ex mode. */
+       if (F_ISSET(sp, SC_VI)) {
+               if (gp->scr_screen(sp, SC_EX)) {
+                       ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON);
+                       return (1);
+               }
+               (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
+               F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
+       }
+
+       /* Put out additional newline, message. */
+       if (need_newline)
+               (void)ex_puts(sp, "\n");
+       if (msg != NULL) {
+               (void)ex_puts(sp, msg);
+               (void)ex_puts(sp, "\n");
+       }
+       (void)ex_fflush(sp);
+
+       switch (pid = vfork()) {
+       case -1:                        /* Error. */
+               msgq(sp, M_SYSERR, "vfork");
+               return (1);
+       case 0:                         /* Utility. */
+               if (gp->scr_child)
+                       gp->scr_child(sp);
+               if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
+                       name = O_STR(sp, O_SHELL);
+               else
+                       ++name;
+               execl(O_STR(sp, O_SHELL), name, "-c", cmd, (char *)NULL);
+               msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
+               _exit(127);
+               /* NOTREACHED */
+       default:                        /* Parent. */
+               return (proc_wait(sp, (long)pid, cmd, 0, 0));
+       }
+       /* NOTREACHED */
+}
+
+/*
+ * proc_wait --
+ *     Wait for one of the processes.
+ *
+ * !!!
+ * The pid_t type varies in size from a short to a long depending on the
+ * system.  It has to be cast into something or the standard promotion
+ * rules get you.  I'm using a long based on the belief that nobody is
+ * going to make it unsigned and it's unlikely to be a quad.
+ *
+ * PUBLIC: int proc_wait __P((SCR *, long, const char *, int, int));
+ */
+int
+proc_wait(SCR *sp, long int pid, const char *cmd, int silent, int okpipe)
+{
+       size_t len;
+       int nf, pstat;
+       char *p;
+
+       /* Wait for the utility, ignoring interruptions. */
+       for (;;) {
+               errno = 0;
+               if (waitpid((pid_t)pid, &pstat, 0) != -1)
+                       break;
+               if (errno != EINTR) {
+                       msgq(sp, M_SYSERR, "waitpid");
+                       return (1);
+               }
+       }
+
+       /*
+        * Display the utility's exit status.  Ignore SIGPIPE from the
+        * parent-writer, as that only means that the utility chose to
+        * exit before reading all of its input.
+        */
+       if (WIFSIGNALED(pstat) && (!okpipe || WTERMSIG(pstat) != SIGPIPE)) {
+               for (; isblank((unsigned char)*cmd); ++cmd);
+               p = msg_print(sp, cmd, &nf);
+               len = strlen(p);
+               msgq(sp, M_ERR, "%.*s%s: received signal: %s%s",
+                   (int)MIN(len, 20), p, len > 20 ? " ..." : "",
+                   sigmsg(WTERMSIG(pstat)),
+                   WCOREDUMP(pstat) ? "; core dumped" : "");
+               if (nf)
+                       FREE_SPACE(sp, p, 0);
+               return (1);
+       }
+
+       if (WIFEXITED(pstat) && WEXITSTATUS(pstat)) {
+               /*
+                * Remain silent for "normal" errors when doing shell file
+                * name expansions, they almost certainly indicate nothing
+                * more than a failure to match.
+                *
+                * Remain silent for vi read filter errors.  It's historic
+                * practice.
+                */
+               if (!silent) {
+                       for (; isblank((unsigned char)*cmd); ++cmd);
+                       p = msg_print(sp, cmd, &nf);
+                       len = strlen(p);
+                       msgq(sp, M_ERR, "%.*s%s: exited with status %d",
+                           (int)MIN(len, 20), p, len > 20 ? " ..." : "",
+                           WEXITSTATUS(pstat));
+                       if (nf)
+                               FREE_SPACE(sp, p, 0);
+               }
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * XXX
+ * The sys_siglist[] table in the C library has this information, but there's
+ * no portable way to get to it.  (Believe me, I tried.)
+ */
+typedef struct _sigs {
+       int      number;                /* signal number */
+       const char *message;            /* related message */
+} SIGS;
+
+SIGS const sigs[] = {
+#ifdef SIGABRT
+       { SIGABRT,      "Abort trap" },
+#endif
+#ifdef SIGALRM
+       { SIGALRM,      "Alarm clock" },
+#endif
+#ifdef SIGBUS
+       { SIGBUS,               "Bus error" },
+#endif
+#ifdef SIGCLD
+       { SIGCLD,               "Child exited or stopped" },
+#endif
+#ifdef SIGCHLD
+       { SIGCHLD,      "Child exited" },
+#endif
+#ifdef SIGCONT
+       { SIGCONT,      "Continued" },
+#endif
+#ifdef SIGDANGER
+       { SIGDANGER,    "System crash imminent" },
+#endif
+#ifdef SIGEMT
+       { SIGEMT,               "EMT trap" },
+#endif
+#ifdef SIGFPE
+       { SIGFPE,               "Floating point exception" },
+#endif
+#ifdef SIGGRANT
+       { SIGGRANT,     "HFT monitor mode granted" },
+#endif
+#ifdef SIGHUP
+       { SIGHUP,               "Hangup" },
+#endif
+#ifdef SIGILL
+       { SIGILL,               "Illegal instruction" },
+#endif
+#ifdef SIGINFO
+       { SIGINFO,      "Information request" },
+#endif
+#ifdef SIGINT
+       { SIGINT,               "Interrupt" },
+#endif
+#ifdef SIGIO
+       { SIGIO,                "I/O possible" },
+#endif
+#ifdef SIGIOT
+       { SIGIOT,               "IOT trap" },
+#endif
+#ifdef SIGKILL
+       { SIGKILL,      "Killed" },
+#endif
+#ifdef SIGLOST
+       { SIGLOST,      "Record lock" },
+#endif
+#ifdef SIGMIGRATE
+       { SIGMIGRATE,   "Migrate process to another CPU" },
+#endif
+#ifdef SIGMSG
+       { SIGMSG,               "HFT input data pending" },
+#endif
+#ifdef SIGPIPE
+       { SIGPIPE,      "Broken pipe" },
+#endif
+#ifdef SIGPOLL
+       { SIGPOLL,      "I/O possible" },
+#endif
+#ifdef SIGPRE
+       { SIGPRE,               "Programming error" },
+#endif
+#ifdef SIGPROF
+       { SIGPROF,      "Profiling timer expired" },
+#endif
+#ifdef SIGPWR
+       { SIGPWR,               "Power failure imminent" },
+#endif
+#ifdef SIGRETRACT
+       { SIGRETRACT,   "HFT monitor mode retracted" },
+#endif
+#ifdef SIGQUIT
+       { SIGQUIT,      "Quit" },
+#endif
+#ifdef SIGSAK
+       { SIGSAK,               "Secure Attention Key" },
+#endif
+#ifdef SIGSEGV
+       { SIGSEGV,      "Segmentation fault" },
+#endif
+#ifdef SIGSOUND
+       { SIGSOUND,     "HFT sound sequence completed" },
+#endif
+#ifdef SIGSTOP
+       { SIGSTOP,      "Suspended (signal)" },
+#endif
+#ifdef SIGSYS
+       { SIGSYS,               "Bad system call" },
+#endif
+#ifdef SIGTERM
+       { SIGTERM,      "Terminated" },
+#endif
+#ifdef SIGTRAP
+       { SIGTRAP,      "Trace/BPT trap" },
+#endif
+#ifdef SIGTSTP
+       { SIGTSTP,      "Suspended" },
+#endif
+#ifdef SIGTTIN
+       { SIGTTIN,      "Stopped (tty input)" },
+#endif
+#ifdef SIGTTOU
+       { SIGTTOU,      "Stopped (tty output)" },
+#endif
+#ifdef SIGURG
+       { SIGURG,               "Urgent I/O condition" },
+#endif
+#ifdef SIGUSR1
+       { SIGUSR1,      "User defined signal 1" },
+#endif
+#ifdef SIGUSR2
+       { SIGUSR2,      "User defined signal 2" },
+#endif
+#ifdef SIGVTALRM
+       { SIGVTALRM,    "Virtual timer expired" },
+#endif
+#ifdef SIGWINCH
+       { SIGWINCH,     "Window size changes" },
+#endif
+#ifdef SIGXCPU
+       { SIGXCPU,      "Cputime limit exceeded" },
+#endif
+#ifdef SIGXFSZ
+       { SIGXFSZ,      "Filesize limit exceeded" },
+#endif
+};
+
+/*
+ * sigmsg --
+ *     Return a pointer to a message describing a signal.
+ */
+static const char *
+sigmsg(int signo)
+{
+       static char buf[40];
+       const SIGS *sigp;
+       size_t n;
+
+       for (n = 0,
+           sigp = &sigs[0]; n < sizeof(sigs) / sizeof(sigs[0]); ++n, ++sigp)
+               if (sigp->number == signo)
+                       return (sigp->message);
+       (void)snprintf(buf, sizeof(buf), "Unknown signal: %d", signo);
+       return (buf);
+}
diff --git a/dist/nvi/ex/ex_shift.c b/dist/nvi/ex/ex_shift.c
new file mode 100644 (file)
index 0000000..4b19adb
--- /dev/null
@@ -0,0 +1,190 @@
+/*     $NetBSD: ex_shift.c,v 1.3 2009/08/07 16:19:54 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_shift.c,v 10.17 2001/06/25 15:19:20 skimo Exp (Berkeley) Date: 2001/06/25 15:19:20";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+enum which {LEFT, RIGHT};
+static int shift __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_shiftl -- :<[<...]
+ *
+ *
+ * PUBLIC: int ex_shiftl __P((SCR *, EXCMD *));
+ */
+int
+ex_shiftl(SCR *sp, EXCMD *cmdp)
+{
+       return (shift(sp, cmdp, LEFT));
+}
+
+/*
+ * ex_shiftr -- :>[>...]
+ *
+ * PUBLIC: int ex_shiftr __P((SCR *, EXCMD *));
+ */
+int
+ex_shiftr(SCR *sp, EXCMD *cmdp)
+{
+       return (shift(sp, cmdp, RIGHT));
+}
+
+/*
+ * shift --
+ *     Ex shift support.
+ */
+static int
+shift(SCR *sp, EXCMD *cmdp, enum which rl)
+{
+       db_recno_t from, to;
+       size_t blen, len, newcol, newidx, oldcol, oldidx, sw;
+       int curset;
+       CHAR_T *p;
+       CHAR_T *bp, *tbp;
+
+       NEEDFILE(sp, cmdp);
+
+       if (O_VAL(sp, O_SHIFTWIDTH) == 0) {
+               msgq(sp, M_INFO, "152|shiftwidth option set to 0");
+               return (0);
+       }
+
+       /* Copy the lines being shifted into the unnamed buffer. */
+       if (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
+               return (1);
+
+       /*
+        * The historic version of vi permitted the user to string any number
+        * of '>' or '<' characters together, resulting in an indent of the
+        * appropriate levels.  There's a special hack in ex_cmd() so that
+        * cmdp->argv[0] points to the string of '>' or '<' characters.
+        *
+        * Q: What's the difference between the people adding features
+        *    to vi and the Girl Scouts?
+        * A: The Girl Scouts have mint cookies and adult supervision.
+        */
+       for (p = cmdp->argv[0]->bp, sw = 0; *p == '>' || *p == '<'; ++p)
+               sw += O_VAL(sp, O_SHIFTWIDTH);
+
+       GET_SPACE_RETW(sp, bp, blen, 256);
+
+       curset = 0;
+       for (from = cmdp->addr1.lno, to = cmdp->addr2.lno; from <= to; ++from) {
+               if (db_get(sp, from, DBG_FATAL, &p, &len))
+                       goto err;
+               if (!len) {
+                       if (sp->lno == from)
+                               curset = 1;
+                       continue;
+               }
+
+               /*
+                * Calculate the old indent amount and the number of
+                * characters it used.
+                */
+               for (oldidx = 0, oldcol = 0; oldidx < len; ++oldidx)
+                       if (p[oldidx] == ' ')
+                               ++oldcol;
+                       else if (p[oldidx] == '\t')
+                               oldcol += O_VAL(sp, O_TABSTOP) -
+                                   oldcol % O_VAL(sp, O_TABSTOP);
+                       else
+                               break;
+
+               /* Calculate the new indent amount. */
+               if (rl == RIGHT)
+                       newcol = oldcol + sw;
+               else {
+                       newcol = oldcol < sw ? 0 : oldcol - sw;
+                       if (newcol == oldcol) {
+                               if (sp->lno == from)
+                                       curset = 1;
+                               continue;
+                       }
+               }
+
+               /* Get a buffer that will hold the new line. */
+               ADD_SPACE_RETW(sp, bp, blen, newcol + len);
+
+               /*
+                * Build a new indent string and count the number of
+                * characters it uses.
+                */
+               tbp = bp;
+               newidx = 0;
+               if (!O_ISSET(sp, O_EXPANDTAB)) {
+                       for (; newcol >= O_VAL(sp, O_TABSTOP); ++newidx) {
+                               *tbp++ = '\t';
+                               newcol -= O_VAL(sp, O_TABSTOP);
+                       }
+               }
+               for (; newcol > 0; --newcol, ++newidx)
+                       *tbp++ = ' ';
+
+               /* Add the original line. */
+               MEMCPYW(tbp, p + oldidx, len - oldidx);
+
+               /* Set the replacement line. */
+               if (db_set(sp, from, bp, (tbp + (len - oldidx)) - bp)) {
+err:                   FREE_SPACEW(sp, bp, blen);
+                       return (1);
+               }
+
+               /*
+                * !!!
+                * The shift command in historic vi had the usual bizarre
+                * collection of cursor semantics.  If called from vi, the
+                * cursor was repositioned to the first non-blank character
+                * of the lowest numbered line shifted.  If called from ex,
+                * the cursor was repositioned to the first non-blank of the
+                * highest numbered line shifted.  Here, if the cursor isn't
+                * part of the set of lines that are moved, move it to the
+                * first non-blank of the last line shifted.  (This makes
+                * ":3>>" in vi work reasonably.)  If the cursor is part of
+                * the shifted lines, it doesn't get moved at all.  This
+                * permits shifting of marked areas, i.e. ">'a." shifts the
+                * marked area twice, something that couldn't be done with
+                * historic vi.
+                */
+               if (sp->lno == from) {
+                       curset = 1;
+                       if (newidx > oldidx)
+                               sp->cno += newidx - oldidx;
+                       else if (sp->cno >= oldidx - newidx)
+                               sp->cno -= oldidx - newidx;
+               }
+       }
+       if (!curset) {
+               sp->lno = to;
+               sp->cno = 0;
+               (void)nonblank(sp, to, &sp->cno);
+       }
+
+       FREE_SPACEW(sp, bp, blen);
+
+       sp->rptlines[L_SHIFT] += cmdp->addr2.lno - cmdp->addr1.lno + 1;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_source.c b/dist/nvi/ex/ex_source.c
new file mode 100644 (file)
index 0000000..f1005a4
--- /dev/null
@@ -0,0 +1,95 @@
+/*     $NetBSD: ex_source.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_source.c,v 10.16 2001/08/18 21:49:58 skimo Exp (Berkeley) Date: 2001/08/18 21:49:58";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_source -- :source file
+ *     Execute ex commands from a file.
+ *
+ * PUBLIC: int ex_source __P((SCR *, EXCMD *));
+ */
+int
+ex_source(SCR *sp, EXCMD *cmdp)
+{
+       struct stat sb;
+       int fd, len;
+       char *bp;
+       const char *name;
+       size_t nlen;
+       const CHAR_T *wp;
+       CHAR_T *dp;
+       size_t wlen;
+
+       INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, name, nlen);
+       if ((fd = open(name, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
+               goto err;
+
+       /*
+        * XXX
+        * I'd like to test to see if the file is too large to malloc.  Since
+        * we don't know what size or type off_t's or size_t's are, what the
+        * largest unsigned integral type is, or what random insanity the local
+        * C compiler will perpetrate, doing the comparison in a portable way
+        * is flatly impossible.  So, put an fairly unreasonable limit on it,
+        * I don't want to be dropping core here.
+        */
+#define        MEGABYTE        1048576
+       if (sb.st_size > MEGABYTE) {
+               errno = ENOMEM;
+               goto err;
+       }
+
+       MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
+       if (bp == NULL) {
+               (void)close(fd);
+               return (1);
+       }
+       bp[sb.st_size] = '\0';
+
+       /* Read the file into memory. */
+       len = read(fd, bp, (int)sb.st_size);
+       (void)close(fd);
+       if (len == -1 || len != sb.st_size) {
+               if (len != sb.st_size)
+                       errno = EIO;
+               free(bp);
+err:           msgq_str(sp, M_SYSERR, name, "%s");
+               return (1);
+       }
+
+       if (CHAR2INT(sp, bp, (size_t)sb.st_size + 1, wp, wlen))
+               msgq(sp, M_ERR, "323|Invalid input. Truncated.");
+       dp = v_wstrdup(sp, wp, wlen - 1);
+       free(bp);
+       /* Put it on the ex queue. */
+       INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, name, nlen);
+       return (ex_run_str(sp, name, dp, wlen - 1, 1, 1));
+}
diff --git a/dist/nvi/ex/ex_stop.c b/dist/nvi/ex/ex_stop.c
new file mode 100644 (file)
index 0000000..cde21fe
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $NetBSD: ex_stop.c,v 1.1.1.2 2008/05/18 14:31:18 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_stop.c,v 10.11 2001/06/25 15:19:20 skimo Exp (Berkeley) Date: 2001/06/25 15:19:20";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_stop -- :stop[!]
+ *           :suspend[!]
+ *     Suspend execution.
+ *
+ * PUBLIC: int ex_stop __P((SCR *, EXCMD *));
+ */
+int
+ex_stop(SCR *sp, EXCMD *cmdp)
+{
+       int allowed;
+
+       /* For some strange reason, the force flag turns off autowrite. */
+       if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && file_aw(sp, FS_ALL))
+               return (1);
+
+       if (sp->gp->scr_suspend(sp, &allowed))
+               return (1);
+       if (!allowed)
+               ex_emsg(sp, NULL, EXM_NOSUSPEND);
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_subst.c b/dist/nvi/ex/ex_subst.c
new file mode 100644 (file)
index 0000000..67c5c1f
--- /dev/null
@@ -0,0 +1,1451 @@
+/*     $NetBSD: ex_subst.c,v 1.4 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_subst.c,v 10.50 2002/02/09 21:18:23 skimo Exp (Berkeley) Date: 2002/02/09 21:18:23";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+#define        SUB_FIRST       0x01            /* The 'r' flag isn't reasonable. */
+#define        SUB_MUSTSETR    0x02            /* The 'r' flag is required. */
+
+static int re_conv __P((SCR *, CHAR_T **, size_t *, int *));
+static int re_cscope_conv __P((SCR *, CHAR_T **, size_t *, int *));
+static int re_sub __P((SCR *,
+               CHAR_T *, CHAR_T **, size_t *, size_t *, regmatch_t [10]));
+static int re_tag_conv __P((SCR *, CHAR_T **, size_t *, int *));
+static int s __P((SCR *, EXCMD *, CHAR_T *, regex_t *, u_int));
+
+/*
+ * ex_s --
+ *     [line [,line]] s[ubstitute] [[/;]pat[/;]/repl[/;] [cgr] [count] [#lp]]
+ *
+ *     Substitute on lines matching a pattern.
+ *
+ * PUBLIC: int ex_s __P((SCR *, EXCMD *));
+ */
+int
+ex_s(SCR *sp, EXCMD *cmdp)
+{
+       regex_t *re;
+       size_t blen, len;
+       u_int flags;
+       ARG_CHAR_T delim;
+       CHAR_T *bp, *p, *ptrn, *rep, *t;
+
+       /*
+        * Skip leading white space.
+        *
+        * !!!
+        * Historic vi allowed any non-alphanumeric to serve as the
+        * substitution command delimiter.
+        *
+        * !!!
+        * If the arguments are empty, it's the same as &, i.e. we
+        * repeat the last substitution.
+        */
+       if (cmdp->argc == 0)
+               goto subagain;
+       for (p = cmdp->argv[0]->bp,
+           len = cmdp->argv[0]->len; len > 0; --len, ++p) {
+               if (!ISBLANK((UCHAR_T)*p))
+                       break;
+       }
+       if (len == 0)
+subagain:      return (ex_subagain(sp, cmdp));
+
+       delim = (UCHAR_T)*p++;
+       if (ISALNUM(delim) || delim == '\\')
+               return (s(sp, cmdp, p, &sp->subre_c, SUB_MUSTSETR));
+
+       /*
+        * !!!
+        * The full-blown substitute command reset the remembered
+        * state of the 'c' and 'g' suffices.
+        */
+       sp->c_suffix = sp->g_suffix = 0;
+
+       /*
+        * Get the pattern string, toss escaping characters.
+        *
+        * !!!
+        * Historic vi accepted any of the following forms:
+        *
+        *      :s/abc/def/             change "abc" to "def"
+        *      :s/abc/def              change "abc" to "def"
+        *      :s/abc/                 delete "abc"
+        *      :s/abc                  delete "abc"
+        *
+        * QUOTING NOTE:
+        *
+        * Only toss an escaping character if it escapes a delimiter.
+        * This means that "s/A/\\\\f" replaces "A" with "\\f".  It
+        * would be nice to be more regular, i.e. for each layer of
+        * escaping a single escaping character is removed, but that's
+        * not how the historic vi worked.
+        */
+       for (ptrn = t = p;;) {
+               if (p[0] == '\0' || p[0] == delim) {
+                       if (p[0] == delim)
+                               ++p;
+                       /*
+                        * !!!
+                        * Nul terminate the pattern string -- it's passed
+                        * to regcomp which doesn't understand anything else.
+                        */
+                       *t = '\0';
+                       break;
+               }
+               if (p[0] == '\\') {
+                       if (p[1] == delim)
+                               ++p;
+                       else if (p[1] == '\\')
+                               *t++ = *p++;
+               }
+               *t++ = *p++;
+       }
+
+       /*
+        * If the pattern string is empty, use the last RE (not just the
+        * last substitution RE).
+        */
+       if (*ptrn == '\0') {
+               if (sp->re == NULL) {
+                       ex_emsg(sp, NULL, EXM_NOPREVRE);
+                       return (1);
+               }
+
+               /* Re-compile the RE if necessary. */
+               if (!F_ISSET(sp, SC_RE_SEARCH) &&
+                   re_compile(sp, sp->re, sp->re_len,
+                   NULL, NULL, &sp->re_c, SEARCH_CSEARCH | SEARCH_MSG))
+                       return (1);
+               flags = 0;
+       } else {
+               /*
+                * !!!
+                * Compile the RE.  Historic practice is that substitutes set
+                * the search direction as well as both substitute and search
+                * RE's.  We compile the RE twice, as we don't want to bother
+                * ref counting the pattern string and (opaque) structure.
+                */
+               if (re_compile(sp, ptrn, t - ptrn, &sp->re,
+                   &sp->re_len, &sp->re_c, SEARCH_CSEARCH | SEARCH_MSG))
+                       return (1);
+               if (re_compile(sp, ptrn, t - ptrn, &sp->subre,
+                   &sp->subre_len, &sp->subre_c, SEARCH_CSUBST | SEARCH_MSG))
+                       return (1);
+               
+               flags = SUB_FIRST;
+               sp->searchdir = FORWARD;
+       }
+       re = &sp->re_c;
+
+       /*
+        * Get the replacement string.
+        *
+        * The special character & (\& if O_MAGIC not set) matches the
+        * entire RE.  No handling of & is required here, it's done by
+        * re_sub().
+        *
+        * The special character ~ (\~ if O_MAGIC not set) inserts the
+        * previous replacement string into this replacement string.
+        * Count ~'s to figure out how much space we need.  We could
+        * special case nonexistent last patterns or whether or not
+        * O_MAGIC is set, but it's probably not worth the effort.
+        *
+        * QUOTING NOTE:
+        *
+        * Only toss an escaping character if it escapes a delimiter or
+        * if O_MAGIC is set and it escapes a tilde.
+        *
+        * !!!
+        * If the entire replacement pattern is "%", then use the last
+        * replacement pattern.  This semantic was added to vi in System
+        * V and then percolated elsewhere, presumably around the time
+        * that it was added to their version of ed(1).
+        */
+       if (p[0] == L('\0') || p[0] == delim) {
+               if (p[0] == delim)
+                       ++p;
+               if (sp->repl != NULL)
+                       free(sp->repl);
+               sp->repl = NULL;
+               sp->repl_len = 0;
+       } else if (p[0] == L('%') && (p[1] == L('\0') || p[1] == delim))
+               p += p[1] == delim ? 2 : 1;
+       else {
+               for (rep = p, len = 0;
+                   p[0] != L('\0') && p[0] != delim; ++p, ++len)
+                       if (p[0] == L('~'))
+                               len += sp->repl_len;
+               GET_SPACE_RETW(sp, bp, blen, len);
+               for (t = bp, len = 0, p = rep;;) {
+                       if (p[0] == L('\0') || p[0] == delim) {
+                               if (p[0] == delim)
+                                       ++p;
+                               break;
+                       }
+                       if (p[0] == L('\\')) {
+                               if (p[1] == delim)
+                                       ++p;
+                               else if (p[1] == L('\\')) {
+                                       *t++ = *p++;
+                                       ++len;
+                               } else if (p[1] == L('~')) {
+                                       ++p;
+                                       if (!O_ISSET(sp, O_MAGIC))
+                                               goto tilde;
+                               }
+                       } else if (p[0] == L('~') && O_ISSET(sp, O_MAGIC)) {
+tilde:                         ++p;
+                               MEMCPYW(t, sp->repl, sp->repl_len);
+                               t += sp->repl_len;
+                               len += sp->repl_len;
+                               continue;
+                       }
+                       *t++ = *p++;
+                       ++len;
+               }
+               if ((sp->repl_len = len) != 0) {
+                       if (sp->repl != NULL)
+                               free(sp->repl);
+                       if ((sp->repl = malloc(len * sizeof(CHAR_T))) == NULL) {
+                               msgq(sp, M_SYSERR, NULL);
+                               FREE_SPACEW(sp, bp, blen);
+                               return (1);
+                       }
+                       MEMCPYW(sp->repl, bp, len);
+               }
+               FREE_SPACEW(sp, bp, blen);
+       }
+       return (s(sp, cmdp, p, re, flags));
+}
+
+/*
+ * ex_subagain --
+ *     [line [,line]] & [cgr] [count] [#lp]]
+ *
+ *     Substitute using the last substitute RE and replacement pattern.
+ *
+ * PUBLIC: int ex_subagain __P((SCR *, EXCMD *));
+ */
+int
+ex_subagain(SCR *sp, EXCMD *cmdp)
+{
+       if (sp->subre == NULL) {
+               ex_emsg(sp, NULL, EXM_NOPREVRE);
+               return (1);
+       }
+       if (!F_ISSET(sp, SC_RE_SUBST) &&
+           re_compile(sp, sp->subre, sp->subre_len,
+           NULL, NULL, &sp->subre_c, SEARCH_CSUBST | SEARCH_MSG))
+               return (1);
+       return (s(sp,
+           cmdp, cmdp->argc ? cmdp->argv[0]->bp : NULL, &sp->subre_c, 0));
+}
+
+/*
+ * ex_subtilde --
+ *     [line [,line]] ~ [cgr] [count] [#lp]]
+ *
+ *     Substitute using the last RE and last substitute replacement pattern.
+ *
+ * PUBLIC: int ex_subtilde __P((SCR *, EXCMD *));
+ */
+int
+ex_subtilde(SCR *sp, EXCMD *cmdp)
+{
+       if (sp->re == NULL) {
+               ex_emsg(sp, NULL, EXM_NOPREVRE);
+               return (1);
+       }
+       if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp, sp->re,
+           sp->re_len, NULL, NULL, &sp->re_c, SEARCH_CSEARCH | SEARCH_MSG))
+               return (1);
+       return (s(sp,
+           cmdp, cmdp->argc ? cmdp->argv[0]->bp : NULL, &sp->re_c, 0));
+}
+
+/*
+ * s --
+ * Do the substitution.  This stuff is *really* tricky.  There are lots of
+ * special cases, and general nastiness.  Don't mess with it unless you're
+ * pretty confident.
+ * 
+ * The nasty part of the substitution is what happens when the replacement
+ * string contains newlines.  It's a bit tricky -- consider the information
+ * that has to be retained for "s/f\(o\)o/^M\1^M\1/".  The solution here is
+ * to build a set of newline offsets which we use to break the line up later,
+ * when the replacement is done.  Don't change it unless you're *damned*
+ * confident.
+ */
+#define        NEEDNEWLINE(sp) {                                               \
+       if (sp->newl_len == sp->newl_cnt) {                             \
+               sp->newl_len += 25;                                     \
+               REALLOC(sp, sp->newl, size_t *,                         \
+                   sp->newl_len * sizeof(size_t));                     \
+               if (sp->newl == NULL) {                                 \
+                       sp->newl_len = 0;                               \
+                       return (1);                                     \
+               }                                                       \
+       }                                                               \
+}
+
+#define        BUILD(sp, l, len) {                                             \
+       if (lbclen + (len) > lblen) {                                   \
+               lblen += MAX(lbclen + (len), 256);                      \
+               REALLOC(sp, lb, CHAR_T *, lblen * sizeof(CHAR_T));      \
+               if (lb == NULL) {                                       \
+                       lbclen = 0;                                     \
+                       return (1);                                     \
+               }                                                       \
+       }                                                               \
+       MEMCPYW(lb + lbclen, l, len);                                   \
+       lbclen += len;                                                  \
+}
+
+#define        NEEDSP(sp, len, pnt) {                                          \
+       if (lbclen + (len) > lblen) {                                   \
+               lblen += MAX(lbclen + (len), 256);                      \
+               REALLOC(sp, lb, CHAR_T *, lblen * sizeof(CHAR_T));      \
+               if (lb == NULL) {                                       \
+                       lbclen = 0;                                     \
+                       return (1);                                     \
+               }                                                       \
+               pnt = lb + lbclen;                                      \
+       }                                                               \
+}
+
+static int
+s(SCR *sp, EXCMD *cmdp, CHAR_T *st, regex_t *re, u_int flags)
+{
+       EVENT ev;
+       MARK from, to;
+       TEXTH tiq;
+       db_recno_t elno, lno, slno;
+       u_long ul;
+       regmatch_t match[10];
+       size_t blen, cnt, last, lbclen, lblen, len, llen;
+       size_t offset, saved_offset, scno;
+       int cflag, lflag, nflag, pflag, rflag;
+       int didsub, do_eol_match, eflags, empty_ok, eval;
+       int linechanged, matched, quit, rval;
+       CHAR_T *lb, *bp;
+       enum nresult nret;
+
+       NEEDFILE(sp, cmdp);
+
+       slno = sp->lno;
+       scno = sp->cno;
+
+       /*
+        * !!!
+        * Historically, the 'g' and 'c' suffices were always toggled as flags,
+        * so ":s/A/B/" was the same as ":s/A/B/ccgg".  If O_EDCOMPATIBLE was
+        * not set, they were initialized to 0 for all substitute commands.  If
+        * O_EDCOMPATIBLE was set, they were initialized to 0 only if the user
+        * specified substitute/replacement patterns (see ex_s()).
+        */
+       if (!O_ISSET(sp, O_EDCOMPATIBLE))
+               sp->c_suffix = sp->g_suffix = 0;
+
+       /*
+        * Historic vi permitted the '#', 'l' and 'p' options in vi mode, but
+        * it only displayed the last change.  I'd disallow them, but they are
+        * useful in combination with the [v]global commands.  In the current
+        * model the problem is combining them with the 'c' flag -- the screen
+        * would have to flip back and forth between the confirm screen and the
+        * ex print screen, which would be pretty awful.  We do display all
+        * changes, though, for what that's worth.
+        *
+        * !!!
+        * Historic vi was fairly strict about the order of "options", the
+        * count, and "flags".  I'm somewhat fuzzy on the difference between
+        * options and flags, anyway, so this is a simpler approach, and we
+        * just take it them in whatever order the user gives them.  (The ex
+        * usage statement doesn't reflect this.)
+        */
+       cflag = lflag = nflag = pflag = rflag = 0;
+       if (st == NULL)
+               goto noargs;
+       for (lno = OOBLNO; *st != '\0'; ++st)
+               switch (*st) {
+               case ' ':
+               case '\t':
+                       continue;
+               case '+':
+                       ++cmdp->flagoff;
+                       break;
+               case '-':
+                       --cmdp->flagoff;
+                       break;
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       if (lno != OOBLNO)
+                               goto usage;
+                       errno = 0;
+                       nret = nget_uslong(sp, &ul, st, &st, 10);
+                       lno = ul;
+                       if (*st == '\0')                /* Loop increment correction. */
+                               --st;
+                       if (nret != NUM_OK) {
+                               if (nret == NUM_OVER)
+                                       msgq(sp, M_ERR, "153|Count overflow");
+                               else if (nret == NUM_UNDER)
+                                       msgq(sp, M_ERR, "154|Count underflow");
+                               else
+                                       msgq(sp, M_SYSERR, NULL);
+                               return (1);
+                       }
+                       /*
+                        * In historic vi, the count was inclusive from the
+                        * second address.
+                        */
+                       cmdp->addr1.lno = cmdp->addr2.lno;
+                       cmdp->addr2.lno += lno - 1;
+                       if (!db_exist(sp, cmdp->addr2.lno) &&
+                           db_last(sp, &cmdp->addr2.lno))
+                               return (1);
+                       break;
+               case '#':
+                       nflag = 1;
+                       break;
+               case 'c':
+                       sp->c_suffix = !sp->c_suffix;
+
+                       /* Ex text structure initialization. */
+                       if (F_ISSET(sp, SC_EX)) {
+                               memset(&tiq, 0, sizeof(TEXTH));
+                               CIRCLEQ_INIT(&tiq);
+                       }
+                       break;
+               case 'g':
+                       sp->g_suffix = !sp->g_suffix;
+                       break;
+               case 'l':
+                       lflag = 1;
+                       break;
+               case 'p':
+                       pflag = 1;
+                       break;
+               case 'r':
+                       if (LF_ISSET(SUB_FIRST)) {
+                               msgq(sp, M_ERR,
+                   "155|Regular expression specified; r flag meaningless");
+                               return (1);
+                       }
+                       if (!F_ISSET(sp, SC_RE_SEARCH)) {
+                               ex_emsg(sp, NULL, EXM_NOPREVRE);
+                               return (1);
+                       }
+                       rflag = 1;
+                       re = &sp->re_c;
+                       break;
+               default:
+                       goto usage;
+               }
+
+       if (*st != '\0' || (!rflag && LF_ISSET(SUB_MUSTSETR))) {
+usage:         ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+               return (1);
+       }
+
+noargs:        if (F_ISSET(sp, SC_VI) && sp->c_suffix && (lflag || nflag || pflag)) {
+               msgq(sp, M_ERR,
+"156|The #, l and p flags may not be combined with the c flag in vi mode");
+               return (1);
+       }
+
+       /*
+        * bp:          if interactive, line cache
+        * blen:        if interactive, line cache length
+        * lb:          build buffer pointer.
+        * lbclen:      current length of built buffer.
+        * lblen;       length of build buffer.
+        */
+       bp = lb = NULL;
+       blen = lbclen = lblen = 0;
+
+       /* For each line... */
+       lno = cmdp->addr1.lno == 0 ? 1 : cmdp->addr1.lno;
+       for (matched = quit = 0,
+           elno = cmdp->addr2.lno; !quit && lno <= elno; ++lno) {
+
+               /* Someone's unhappy, time to stop. */
+               if (INTERRUPTED(sp))
+                       break;
+
+               /* Get the line. */
+               if (db_get(sp, lno, DBG_FATAL, &st, &llen))
+                       goto err;
+
+               /*
+                * Make a local copy if doing confirmation -- when calling
+                * the confirm routine we're likely to lose the cached copy.
+                */
+               if (sp->c_suffix) {
+                       if (bp == NULL) {
+                               GET_SPACE_RETW(sp, bp, blen, llen);
+                       } else
+                               ADD_SPACE_RETW(sp, bp, blen, llen);
+                       MEMCPYW(bp, st, llen);
+                       st = bp;
+               }
+
+               /* Start searching from the beginning. */
+               offset = 0;
+               len = llen;
+
+               /* Reset the build buffer offset. */
+               lbclen = 0;
+
+               /* Reset empty match flag. */
+               empty_ok = 1;
+
+               /*
+                * We don't want to have to do a setline if the line didn't
+                * change -- keep track of whether or not this line changed.
+                * If doing confirmations, don't want to keep setting the
+                * line if change is refused -- keep track of substitutions.
+                */
+               didsub = linechanged = 0;
+
+               /* New line, do an EOL match. */
+               do_eol_match = 1;
+
+               /* It's not nul terminated, but we pretend it is. */
+               eflags = REG_STARTEND;
+
+               /*
+                * The search area is from st + offset to the EOL.
+                *
+                * Generally, match[0].rm_so is the offset of the start
+                * of the match from the start of the search, and offset
+                * is the offset of the start of the last search.
+                */
+nextmatch:     match[0].rm_so = 0;
+               match[0].rm_eo = len;
+
+               /* Get the next match. */
+               eval = regexec(re, st + offset, 10, match, eflags);
+
+               /*
+                * There wasn't a match or if there was an error, deal with
+                * it.  If there was a previous match in this line, resolve
+                * the changes into the database.  Otherwise, just move on.
+                */
+               if (eval == REG_NOMATCH)
+                       goto endmatch;
+               if (eval != 0) {
+                       re_error(sp, eval, re);
+                       goto err;
+               }
+               matched = 1;
+
+               /* Only the first search can match an anchored expression. */
+               eflags |= REG_NOTBOL;
+
+               /*
+                * !!!
+                * It's possible to match 0-length strings -- for example, the
+                * command s;a*;X;, when matched against the string "aabb" will
+                * result in "XbXbX", i.e. the matches are "aa", the space
+                * between the b's and the space between the b's and the end of
+                * the string.  There is a similar space between the beginning
+                * of the string and the a's.  The rule that we use (because vi
+                * historically used it) is that any 0-length match, occurring
+                * immediately after a match, is ignored.  Otherwise, the above
+                * example would have resulted in "XXbXbX".  Another example is
+                * incorrectly using " *" to replace groups of spaces with one
+                * space.
+                *
+                * The way we do this is that if we just had a successful match,
+                * the starting offset does not skip characters, and the match
+                * is empty, ignore the match and move forward.  If there's no
+                * more characters in the string, we were attempting to match
+                * after the last character, so quit.
+                */
+               if (!empty_ok && match[0].rm_so == 0 && match[0].rm_eo == 0) {
+                       empty_ok = 1;
+                       if (len == 0)
+                               goto endmatch;
+                       BUILD(sp, st + offset, 1)
+                       ++offset;
+                       --len;
+                       goto nextmatch;
+               }
+
+               /* Confirm change. */
+               if (sp->c_suffix) {
+                       /*
+                        * Set the cursor position for confirmation.  Note,
+                        * if we matched on a '$', the cursor may be past
+                        * the end of line.
+                        */
+                       from.lno = to.lno = lno;
+                       from.cno = match[0].rm_so + offset;
+                       to.cno = match[0].rm_eo + offset;
+                       /*
+                        * Both ex and vi have to correct for a change before
+                        * the first character in the line.
+                        */
+                       if (llen == 0)
+                               from.cno = to.cno = 0;
+                       if (F_ISSET(sp, SC_VI)) {
+                               /*
+                                * Only vi has to correct for a change after
+                                * the last character in the line.
+                                *
+                                * XXX
+                                * It would be nice to change the vi code so
+                                * that we could display a cursor past EOL.
+                                */
+                               if (to.cno >= llen)
+                                       to.cno = llen - 1;
+                               if (from.cno >= llen)
+                                       from.cno = llen - 1;
+
+                               sp->lno = from.lno;
+                               sp->cno = from.cno;
+                               if (vs_refresh(sp, 1))
+                                       goto err;
+
+                               vs_update(sp, msg_cat(sp,
+                                   "169|Confirm change? [n]", NULL), NULL);
+
+                               if (v_event_get(sp, &ev, 0, 0))
+                                       goto err;
+                               switch (ev.e_event) {
+                               case E_CHARACTER:
+                                       break;
+                               case E_EOF:
+                               case E_ERR:
+                               case E_INTERRUPT:
+                                       goto lquit;
+                               default:
+                                       v_event_err(sp, &ev);
+                                       goto lquit;
+                               }
+                       } else {
+                               if (ex_print(sp, cmdp, &from, &to, 0) ||
+                                   ex_scprint(sp, &from, &to))
+                                       goto lquit;
+                               if (ex_txt(sp, &tiq, 0, TXT_CR))
+                                       goto err;
+                               ev.e_c = tiq.cqh_first->lb[0];
+                       }
+
+                       switch (ev.e_c) {
+                       case CH_YES:
+                               break;
+                       default:
+                       case CH_NO:
+                               didsub = 0;
+                               BUILD(sp, st + offset, match[0].rm_eo);
+                               goto skip;
+                       case CH_QUIT:
+                               /* Set the quit/interrupted flags. */
+lquit:                         quit = 1;
+                               F_SET(sp->gp, G_INTERRUPTED);
+
+                               /*
+                                * Resolve any changes, then return to (and
+                                * exit from) the main loop.
+                                */
+                               goto endmatch;
+                       }
+               }
+
+               /*
+                * Set the cursor to the last position changed, converting
+                * from 1-based to 0-based.
+                */
+               sp->lno = lno;
+               sp->cno = match[0].rm_so;
+
+               /* Copy the bytes before the match into the build buffer. */
+               BUILD(sp, st + offset, match[0].rm_so);
+
+               /* Substitute the matching bytes. */
+               didsub = 1;
+               if (re_sub(sp, st + offset, &lb, &lbclen, &lblen, match))
+                       goto err;
+
+               /* Set the change flag so we know this line was modified. */
+               linechanged = 1;
+
+               /* Move past the matched bytes. */
+skip:          offset += match[0].rm_eo;
+               len -= match[0].rm_eo;
+
+               /* A match cannot be followed by an empty pattern. */
+               empty_ok = 0;
+
+               /*
+                * If doing a global change with confirmation, we have to
+                * update the screen.  The basic idea is to store the line
+                * so the screen update routines can find it, and restart.
+                */
+               if (didsub && sp->c_suffix && sp->g_suffix) {
+                       /*
+                        * The new search offset will be the end of the
+                        * modified line.
+                        */
+                       saved_offset = lbclen;
+
+                       /* Copy the rest of the line. */
+                       if (len)
+                               BUILD(sp, st + offset, len)
+
+                       /* Set the new offset. */
+                       offset = saved_offset;
+
+                       /* Store inserted lines, adjusting the build buffer. */
+                       last = 0;
+                       if (sp->newl_cnt) {
+                               for (cnt = 0;
+                                   cnt < sp->newl_cnt; ++cnt, ++lno, ++elno) {
+                                       if (db_insert(sp, lno,
+                                           lb + last, sp->newl[cnt] - last))
+                                               goto err;
+                                       last = sp->newl[cnt] + 1;
+                                       ++sp->rptlines[L_ADDED];
+                               }
+                               lbclen -= last;
+                               offset -= last;
+                               sp->newl_cnt = 0;
+                       }
+
+                       /* Store and retrieve the line. */
+                       if (db_set(sp, lno, lb + last, lbclen))
+                               goto err;
+                       if (db_get(sp, lno, DBG_FATAL, &st, &llen))
+                               goto err;
+                       ADD_SPACE_RETW(sp, bp, blen, llen)
+                       MEMCPYW(bp, st, llen);
+                       st = bp;
+                       len = llen - offset;
+
+                       /* Restart the build. */
+                       lbclen = 0;
+                       BUILD(sp, st, offset);
+
+                       /*
+                        * If we haven't already done the after-the-string
+                        * match, do one.  Set REG_NOTEOL so the '$' pattern
+                        * only matches once.
+                        */
+                       if (!do_eol_match)
+                               goto endmatch;
+                       if (offset == len) {
+                               do_eol_match = 0;
+                               eflags |= REG_NOTEOL;
+                       }
+                       goto nextmatch;
+               }
+
+               /*
+                * If it's a global:
+                *
+                * If at the end of the string, do a test for the after
+                * the string match.  Set REG_NOTEOL so the '$' pattern
+                * only matches once.
+                */
+               if (sp->g_suffix && do_eol_match) {
+                       if (len == 0) {
+                               do_eol_match = 0;
+                               eflags |= REG_NOTEOL;
+                       }
+                       goto nextmatch;
+               }
+
+endmatch:      if (!linechanged)
+                       continue;
+
+               /* Copy any remaining bytes into the build buffer. */
+               if (len)
+                       BUILD(sp, st + offset, len)
+
+               /* Store inserted lines, adjusting the build buffer. */
+               last = 0;
+               if (sp->newl_cnt) {
+                       for (cnt = 0;
+                           cnt < sp->newl_cnt; ++cnt, ++lno, ++elno) {
+                               if (db_insert(sp,
+                                   lno, lb + last, sp->newl[cnt] - last))
+                                       goto err;
+                               last = sp->newl[cnt] + 1;
+                               ++sp->rptlines[L_ADDED];
+                       }
+                       lbclen -= last;
+                       sp->newl_cnt = 0;
+               }
+
+               /* Store the changed line. */
+               if (db_set(sp, lno, lb + last, lbclen))
+                       goto err;
+
+               /* Update changed line counter. */
+               if (sp->rptlchange != lno) {
+                       sp->rptlchange = lno;
+                       ++sp->rptlines[L_CHANGED];
+               }
+
+               /*
+                * !!!
+                * Display as necessary.  Historic practice is to only
+                * display the last line of a line split into multiple
+                * lines.
+                */
+               if (lflag || nflag || pflag) {
+                       from.lno = to.lno = lno;
+                       from.cno = to.cno = 0;
+                       if (lflag)
+                               (void)ex_print(sp, cmdp, &from, &to, E_C_LIST);
+                       if (nflag)
+                               (void)ex_print(sp, cmdp, &from, &to, E_C_HASH);
+                       if (pflag)
+                               (void)ex_print(sp, cmdp, &from, &to, E_C_PRINT);
+               }
+       }
+
+       /*
+        * !!!
+        * Historically, vi attempted to leave the cursor at the same place if
+        * the substitution was done at the current cursor position.  Otherwise
+        * it moved it to the first non-blank of the last line changed.  There
+        * were some problems: for example, :s/$/foo/ with the cursor on the
+        * last character of the line left the cursor on the last character, or
+        * the & command with multiple occurrences of the matching string in the
+        * line usually left the cursor in a fairly random position.
+        *
+        * We try to do the same thing, with the exception that if the user is
+        * doing substitution with confirmation, we move to the last line about
+        * which the user was consulted, as opposed to the last line that they
+        * actually changed.  This prevents a screen flash if the user doesn't
+        * change many of the possible lines.
+        */
+       if (!sp->c_suffix && (sp->lno != slno || sp->cno != scno)) {
+               sp->cno = 0;
+               (void)nonblank(sp, sp->lno, &sp->cno);
+       }
+
+       /*
+        * If not in a global command, and nothing matched, say so.
+        * Else, if none of the lines displayed, put something up.
+        */
+       rval = 0;
+       if (!matched) {
+               if (!F_ISSET(sp, SC_EX_GLOBAL)) {
+                       msgq(sp, M_ERR, "157|No match found");
+                       goto err;
+               }
+       } else if (!lflag && !nflag && !pflag)
+               F_SET(cmdp, E_AUTOPRINT);
+
+       if (0) {
+err:           rval = 1;
+       }
+
+       if (bp != NULL)
+               FREE_SPACEW(sp, bp, blen);
+       if (lb != NULL)
+               free(lb);
+       return (rval);
+}
+
+/*
+ * re_compile --
+ *     Compile the RE.
+ *
+ * PUBLIC: int re_compile __P((SCR *,
+ * PUBLIC:     CHAR_T *, size_t, CHAR_T **, size_t *, regex_t *, u_int));
+ */
+int
+re_compile(SCR *sp, CHAR_T *ptrn, size_t plen, CHAR_T **ptrnp, size_t *lenp, regex_t *rep, u_int flags)
+{
+       size_t len;
+       int reflags, replaced, rval;
+       CHAR_T *p;
+
+       /* Set RE flags. */
+       reflags = 0;
+       if (LF_ISSET(SEARCH_EXTEND))
+               reflags |= REG_EXTENDED;
+       if (LF_ISSET(SEARCH_IC))
+               reflags |= REG_ICASE;
+       if (LF_ISSET(SEARCH_LITERAL))
+               reflags |= REG_NOSPEC;
+       if (!LF_ISSET(SEARCH_NOOPT | SEARCH_CSCOPE | SEARCH_TAG)) {
+               if (O_ISSET(sp, O_EXTENDED))
+                       reflags |= REG_EXTENDED;
+               if (O_ISSET(sp, O_IGNORECASE))
+                       reflags |= REG_ICASE;
+               if (O_ISSET(sp, O_ICLOWER))
+                       goto iclower;
+       }
+       if (LF_ISSET(SEARCH_ICL)) {
+iclower:       for (p = ptrn, len = plen; len > 0; ++p, --len)
+                       if (ISUPPER((UCHAR_T)*p))
+                               break;
+               if (len == 0)
+                       reflags |= REG_ICASE;
+       }
+
+       /* If we're replacing a saved value, clear the old one. */
+       if (LF_ISSET(SEARCH_CSEARCH) && F_ISSET(sp, SC_RE_SEARCH)) {
+               regfree(&sp->re_c);
+               F_CLR(sp, SC_RE_SEARCH);
+       }
+       if (LF_ISSET(SEARCH_CSUBST) && F_ISSET(sp, SC_RE_SUBST)) {
+               regfree(&sp->subre_c);
+               F_CLR(sp, SC_RE_SUBST);
+       }
+
+       /*
+        * If we're saving the string, it's a pattern we haven't seen before,
+        * so convert the vi-style RE's to POSIX 1003.2 RE's.  Save a copy for
+        * later recompilation.   Free any previously saved value.
+        */
+       if (ptrnp != NULL) {
+               replaced = 0;
+               if (LF_ISSET(SEARCH_CSCOPE)) {
+                       if (re_cscope_conv(sp, &ptrn, &plen, &replaced))
+                               return (1);
+                       /*
+                        * XXX
+                        * Currently, the match-any-<blank> expression used in
+                        * re_cscope_conv() requires extended RE's.  This may
+                        * not be right or safe.
+                        */
+                       reflags |= REG_EXTENDED;
+               } else if (LF_ISSET(SEARCH_TAG)) {
+                       if (re_tag_conv(sp, &ptrn, &plen, &replaced))
+                               return (1);
+               } else if (!LF_ISSET(SEARCH_LITERAL))
+                       if (re_conv(sp, &ptrn, &plen, &replaced))
+                               return (1);
+
+               /* Discard previous pattern. */
+               if (*ptrnp != NULL) {
+                       free(*ptrnp);
+                       *ptrnp = NULL;
+               }
+               if (lenp != NULL)
+                       *lenp = plen;
+
+               /*
+                * Copy the string into allocated memory.
+                *
+                * XXX
+                * Regcomp isn't 8-bit clean, so the pattern is nul-terminated
+                * for now.  There's just no other solution.  
+                */
+               MALLOC(sp, *ptrnp, CHAR_T *, (plen + 1) * sizeof(CHAR_T));
+               if (*ptrnp != NULL) {
+                       MEMCPYW(*ptrnp, ptrn, plen);
+                       (*ptrnp)[plen] = '\0';
+               }
+
+               /* Free up conversion-routine-allocated memory. */
+               if (replaced)
+                       FREE_SPACEW(sp, ptrn, 0);
+
+               if (*ptrnp == NULL)
+                       return (1);
+
+               ptrn = *ptrnp;
+       }
+
+       /*
+        * XXX
+        * Regcomp isn't 8-bit clean, so we just lost if the pattern
+        * contained a nul.  Bummer!
+        */
+       if ((rval = regcomp(rep, ptrn, /* plen, */ reflags)) != 0) {
+               if (LF_ISSET(SEARCH_MSG))
+                       re_error(sp, rval, rep); 
+               return (1);
+       }
+
+       if (LF_ISSET(SEARCH_CSEARCH))
+               F_SET(sp, SC_RE_SEARCH);
+       if (LF_ISSET(SEARCH_CSUBST))
+               F_SET(sp, SC_RE_SUBST);
+
+       return (0);
+}
+
+/*
+ * re_conv --
+ *     Convert vi's regular expressions into something that the
+ *     the POSIX 1003.2 RE functions can handle.
+ *
+ * There are three conversions we make to make vi's RE's (specifically
+ * the global, search, and substitute patterns) work with POSIX RE's.
+ *
+ * 1: If O_MAGIC is not set, strip backslashes from the magic character
+ *    set (.[*~) that have them, and add them to the ones that don't.
+ * 2: If O_MAGIC is not set, the string "\~" is replaced with the text
+ *    from the last substitute command's replacement string.  If O_MAGIC
+ *    is set, it's the string "~".
+ * 3: The pattern \<ptrn\> does "word" searches, convert it to use the
+ *    new RE escapes.
+ *
+ * !!!/XXX
+ * This doesn't exactly match the historic behavior of vi because we do
+ * the ~ substitution before calling the RE engine, so magic characters
+ * in the replacement string will be expanded by the RE engine, and they
+ * weren't historically.  It's a bug.
+ */
+static int
+re_conv(SCR *sp, CHAR_T **ptrnp, size_t *plenp, int *replacedp)
+{
+       size_t blen, len, needlen;
+       int magic;
+       CHAR_T *bp, *p, *t;
+
+       /*
+        * First pass through, we figure out how much space we'll need.
+        * We do it in two passes, on the grounds that most of the time
+        * the user is doing a search and won't have magic characters.
+        * That way we can skip most of the memory allocation and copies.
+        */
+       magic = 0;
+       for (p = *ptrnp, len = *plenp, needlen = 0; len > 0; ++p, --len)
+               switch (*p) {
+               case '\\':
+                       if (len > 1) {
+                               --len;
+                               switch (*++p) {
+                               case '<':
+                                       magic = 1;
+                                       needlen += RE_WSTART_LEN + 1;
+                                       break;
+                               case '>':
+                                       magic = 1;
+                                       needlen += RE_WSTOP_LEN + 1;
+                                       break;
+                               case '~':
+                                       if (!O_ISSET(sp, O_MAGIC)) {
+                                               magic = 1;
+                                               needlen += sp->repl_len;
+                                       }
+                                       break;
+                               case '.':
+                               case '[':
+                               case '*':
+                                       if (!O_ISSET(sp, O_MAGIC)) {
+                                               magic = 1;
+                                               needlen += 1;
+                                       }
+                                       break;
+                               default:
+                                       needlen += 2;
+                               }
+                       } else
+                               needlen += 1;
+                       break;
+               case '~':
+                       if (O_ISSET(sp, O_MAGIC)) {
+                               magic = 1;
+                               needlen += sp->repl_len;
+                       }
+                       break;
+               case '.':
+               case '[':
+               case '*':
+                       if (!O_ISSET(sp, O_MAGIC)) {
+                               magic = 1;
+                               needlen += 2;
+                       }
+                       break;
+               default:
+                       needlen += 1;
+                       break;
+               }
+
+       if (!magic) {
+               *replacedp = 0;
+               return (0);
+       }
+
+       /* Get enough memory to hold the final pattern. */
+       *replacedp = 1;
+       GET_SPACE_RETW(sp, bp, blen, needlen);
+
+       for (p = *ptrnp, len = *plenp, t = bp; len > 0; ++p, --len)
+               switch (*p) {
+               case '\\':
+                       if (len > 1) {
+                               --len;
+                               switch (*++p) {
+                               case '<':
+                                       MEMCPY(t,
+                                           RE_WSTART, RE_WSTART_LEN);
+                                       t += RE_WSTART_LEN;
+                                       break;
+                               case '>':
+                                       MEMCPY(t,
+                                           RE_WSTOP, RE_WSTOP_LEN);
+                                       t += RE_WSTOP_LEN;
+                                       break;
+                               case '~':
+                                       if (O_ISSET(sp, O_MAGIC))
+                                               *t++ = '~';
+                                       else {
+                                               MEMCPYW(t,
+                                                   sp->repl, sp->repl_len);
+                                               t += sp->repl_len;
+                                       }
+                                       break;
+                               case '.':
+                               case '[':
+                               case '*':
+                                       if (O_ISSET(sp, O_MAGIC))
+                                               *t++ = '\\';
+                                       *t++ = *p;
+                                       break;
+                               default:
+                                       *t++ = '\\';
+                                       *t++ = *p;
+                               }
+                       } else
+                               *t++ = '\\';
+                       break;
+               case '~':
+                       if (O_ISSET(sp, O_MAGIC)) {
+                               MEMCPYW(t, sp->repl, sp->repl_len);
+                               t += sp->repl_len;
+                       } else
+                               *t++ = '~';
+                       break;
+               case '.':
+               case '[':
+               case '*':
+                       if (!O_ISSET(sp, O_MAGIC))
+                               *t++ = '\\';
+                       *t++ = *p;
+                       break;
+               default:
+                       *t++ = *p;
+                       break;
+               }
+
+       *ptrnp = bp;
+       *plenp = t - bp;
+       return (0);
+}
+
+/*
+ * re_tag_conv --
+ *     Convert a tags search path into something that the POSIX
+ *     1003.2 RE functions can handle.
+ */
+static int
+re_tag_conv(SCR *sp, CHAR_T **ptrnp, size_t *plenp, int *replacedp)
+{
+       size_t blen, len;
+       int lastdollar;
+       CHAR_T *bp, *p, *t;
+
+       len = *plenp;
+
+       /* Max memory usage is 2 times the length of the string. */
+       *replacedp = 1;
+       GET_SPACE_RETW(sp, bp, blen, len * 2);
+
+       p = *ptrnp;
+       t = bp;
+
+       /* If the last character is a '/' or '?', we just strip it. */
+       if (len > 0 && (p[len - 1] == '/' || p[len - 1] == '?'))
+               --len;
+
+       /* If the next-to-last or last character is a '$', it's magic. */
+       if (len > 0 && p[len - 1] == '$') {
+               --len;
+               lastdollar = 1;
+       } else
+               lastdollar = 0;
+
+       /* If the first character is a '/' or '?', we just strip it. */
+       if (len > 0 && (p[0] == '/' || p[0] == '?')) {
+               ++p;
+               --len;
+       }
+
+       /* If the first or second character is a '^', it's magic. */
+       if (p[0] == '^') {
+               *t++ = *p++;
+               --len;
+       }
+
+       /*
+        * Escape every other magic character we can find, meanwhile stripping
+        * the backslashes ctags inserts when escaping the search delimiter
+        * characters.
+        */
+       for (; len > 0; --len) {
+               if (p[0] == '\\' && (p[1] == '/' || p[1] == '?')) {
+                       ++p;
+                       --len;
+               } else if (strchr("^.[]$*", p[0]))
+                       *t++ = '\\';
+               *t++ = *p++;
+       }
+       if (lastdollar)
+               *t++ = '$';
+
+       *ptrnp = bp;
+       *plenp = t - bp;
+       return (0);
+}
+
+/*
+ * re_cscope_conv --
+ *      Convert a cscope search path into something that the POSIX
+ *      1003.2 RE functions can handle.
+ */
+static int
+re_cscope_conv(SCR *sp, CHAR_T **ptrnp, size_t *plenp, int *replacedp)
+{
+       size_t blen, len, nspaces;
+       CHAR_T *bp, *t;
+       CHAR_T *p;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /*
+        * Each space in the source line printed by cscope represents an
+        * arbitrary sequence of spaces, tabs, and comments.
+        */
+#define        CSCOPE_RE_SPACE         "([ \t]|/\\*([^*]|\\*/)*\\*/)*"
+#define CSCOPE_LEN     sizeof(CSCOPE_RE_SPACE) - 1
+       CHAR2INT(sp, CSCOPE_RE_SPACE, CSCOPE_LEN, wp, wlen);
+       for (nspaces = 0, p = *ptrnp, len = *plenp; len > 0; ++p, --len)
+               if (*p == ' ')
+                       ++nspaces;
+
+       /*
+        * Allocate plenty of space:
+        *      the string, plus potential escaping characters;
+        *      nspaces + 2 copies of CSCOPE_RE_SPACE;
+        *      ^, $, nul terminator characters.
+        */
+       *replacedp = 1;
+       len = (p - *ptrnp) * 2 + (nspaces + 2) * sizeof(CSCOPE_RE_SPACE) + 3;
+       GET_SPACE_RETW(sp, bp, blen, len);
+
+       p = *ptrnp;
+       t = bp;
+
+       *t++ = '^';
+       MEMCPYW(t, wp, wlen);
+       t += wlen;
+
+       for (len = *plenp; len > 0; ++p, --len)
+               if (*p == ' ') {
+                       MEMCPYW(t, wp, wlen);
+                       t += wlen;
+               } else {
+                       if (strchr("\\^.[]$*+?()|{}", *p))
+                               *t++ = '\\';
+                       *t++ = *p;
+               }
+
+       MEMCPYW(t, wp, wlen);
+       t += wlen;
+       *t++ = '$';
+
+       *ptrnp = bp;
+       *plenp = t - bp;
+       return (0);
+}
+
+/*
+ * re_error --
+ *     Report a regular expression error.
+ *
+ * PUBLIC: void re_error __P((SCR *, int, regex_t *));
+ */
+void
+re_error(SCR *sp, int errcode, regex_t *preg)
+{
+       size_t sz;
+       char *oe;
+
+       sz = regerror(errcode, preg, NULL, 0);
+       if ((oe = malloc(sz)) == NULL)
+               msgq(sp, M_SYSERR, NULL);
+       else {
+               (void)regerror(errcode, preg, oe, sz);
+               msgq(sp, M_ERR, "RE error: %s", oe);
+               free(oe);
+       }
+}
+
+/*
+ * re_sub --
+ *     Do the substitution for a regular expression.
+ */
+static int
+re_sub(SCR *sp, CHAR_T *ip, CHAR_T **lbp, size_t *lbclenp, size_t *lblenp, regmatch_t *match)
+               
+                                       /* Input line. */
+                    
+                                
+                            
+{
+       enum { C_NOT_SET, C_LOWER, C_ONE_LOWER, C_ONE_UPPER, C_UPPER } conv;
+       size_t lbclen, lblen;           /* Local copies. */
+       size_t mlen;                    /* Match length. */
+       size_t rpl;                     /* Remaining replacement length. */
+       CHAR_T *rp;                     /* Replacement pointer. */
+       int ch;
+       int no;                         /* Match replacement offset. */
+       CHAR_T *p, *t;                  /* Buffer pointers. */
+       CHAR_T *lb;                     /* Local copies. */
+
+       lb = *lbp;                      /* Get local copies. */
+       lbclen = *lbclenp;
+       lblen = *lblenp;
+
+       /*
+        * QUOTING NOTE:
+        *
+        * There are some special sequences that vi provides in the
+        * replacement patterns.
+        *       & string the RE matched (\& if nomagic set)
+        *      \# n-th regular subexpression
+        *      \E end \U, \L conversion
+        *      \e end \U, \L conversion
+        *      \l convert the next character to lower-case
+        *      \L convert to lower-case, until \E, \e, or end of replacement
+        *      \u convert the next character to upper-case
+        *      \U convert to upper-case, until \E, \e, or end of replacement
+        *
+        * Otherwise, since this is the lowest level of replacement, discard
+        * all escaping characters.  This (hopefully) matches historic practice.
+        */
+#define        OUTCH(ch, nltrans) {                                            \
+       ARG_CHAR_T __ch = (ch);                                         \
+       e_key_t __value = KEY_VAL(sp, __ch);                            \
+       if (nltrans && (__value == K_CR || __value == K_NL)) {          \
+               NEEDNEWLINE(sp);                                        \
+               sp->newl[sp->newl_cnt++] = lbclen;                      \
+       } else if (conv != C_NOT_SET) {                                 \
+               switch (conv) {                                         \
+               case C_ONE_LOWER:                                       \
+                       conv = C_NOT_SET;                               \
+                       /* FALLTHROUGH */                               \
+               case C_LOWER:                                           \
+                       if (ISUPPER(__ch))                              \
+                               __ch = TOLOWER(__ch);                   \
+                       break;                                          \
+               case C_ONE_UPPER:                                       \
+                       conv = C_NOT_SET;                               \
+                       /* FALLTHROUGH */                               \
+               case C_UPPER:                                           \
+                       if (ISLOWER(__ch))                              \
+                               __ch = TOUPPER(__ch);                   \
+                       break;                                          \
+               default:                                                \
+                       abort();                                        \
+               }                                                       \
+       }                                                               \
+       NEEDSP(sp, 1, p);                                               \
+       *p++ = __ch;                                                    \
+       ++lbclen;                                                       \
+}
+       conv = C_NOT_SET;
+       for (rp = sp->repl, rpl = sp->repl_len, p = lb + lbclen; rpl--;) {
+               switch (ch = *rp++) {
+               case '&':
+                       if (O_ISSET(sp, O_MAGIC)) {
+                               no = 0;
+                               goto subzero;
+                       }
+                       break;
+               case '\\':
+                       if (rpl == 0)
+                               break;
+                       --rpl;
+                       switch (ch = *rp) {
+                       case '&':
+                               ++rp;
+                               if (!O_ISSET(sp, O_MAGIC)) {
+                                       no = 0;
+                                       goto subzero;
+                               }
+                               break;
+                       case '0': case '1': case '2': case '3': case '4':
+                       case '5': case '6': case '7': case '8': case '9':
+                               no = *rp++ - '0';
+subzero:                       if (match[no].rm_so == -1 ||
+                                   match[no].rm_eo == -1)
+                                       break;
+                               mlen = match[no].rm_eo - match[no].rm_so;
+                               for (t = ip + match[no].rm_so; mlen--; ++t)
+                                       OUTCH((UCHAR_T)*t, 0);
+                               continue;
+                       case 'e':
+                       case 'E':
+                               ++rp;
+                               conv = C_NOT_SET;
+                               continue;
+                       case 'l':
+                               ++rp;
+                               conv = C_ONE_LOWER;
+                               continue;
+                       case 'L':
+                               ++rp;
+                               conv = C_LOWER;
+                               continue;
+                       case 'u':
+                               ++rp;
+                               conv = C_ONE_UPPER;
+                               continue;
+                       case 'U':
+                               ++rp;
+                               conv = C_UPPER;
+                               continue;
+                       default:
+                               ++rp;
+                               break;
+                       }
+               }
+               OUTCH(ch, 1);
+       }
+
+       *lbp = lb;                      /* Update caller's information. */
+       *lbclenp = lbclen;
+       *lblenp = lblen;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_tag.c b/dist/nvi/ex/ex_tag.c
new file mode 100644 (file)
index 0000000..2a38b7e
--- /dev/null
@@ -0,0 +1,1491 @@
+/*     $NetBSD: ex_tag.c,v 1.11 2012/02/25 00:13:00 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems, Inc.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_tag.c,v 10.50 2004/03/16 14:09:11 skimo Exp (Berkeley) Date: 2004/03/16 14:09:11";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>         /* XXX: param.h may not have included types.h */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "tag.h"
+
+static char    *binary_search __P((char *, char *, char *));
+static int      compare __P((char *, char *, char *));
+static void     ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
+static int      ctag_search __P((SCR *, CHAR_T *, size_t, char *));
+#ifdef GTAGS
+static int      getentry __P((char *, char **, char **, char **));
+static TAGQ    *gtag_slist __P((SCR *, CHAR_T *, int));
+#endif
+static int      ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
+static TAGQ    *ctag_slist __P((SCR *, CHAR_T *));
+static char    *linear_search __P((char *, char *, char *, unsigned long));
+static int      tag_copy __P((SCR *, TAG *, TAG **));
+static int      tag_pop __P((SCR *, TAGQ *, int));
+static int      tagf_copy __P((SCR *, TAGF *, TAGF **));
+static int      tagf_free __P((SCR *, TAGF *));
+static int      tagq_copy __P((SCR *, TAGQ *, TAGQ **));
+
+/*
+ * ex_tag_first --
+ *     The tag code can be entered from main, e.g., "vi -t tag".
+ *
+ * PUBLIC: int ex_tag_first __P((SCR *, CHAR_T *));
+ */
+int
+ex_tag_first(SCR *sp, const CHAR_T *tagarg)
+{
+       EXCMD cmd;
+
+       /* Build an argument for the ex :tag command. */
+       ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
+       argv_exp0(sp, &cmd, tagarg, STRLEN(tagarg));
+
+       /*
+        * XXX
+        * Historic vi went ahead and created a temporary file when it failed
+        * to find the tag.  We match historic practice, but don't distinguish
+        * between real error and failure to find the tag.
+        */
+       if (ex_tag_push(sp, &cmd))
+               return (0);
+
+       /* Display tags in the center of the screen. */
+       F_CLR(sp, SC_SCR_TOP);
+       F_SET(sp, SC_SCR_CENTER);
+
+       return (0);
+}
+
+#ifdef GTAGS
+/*
+ * ex_rtag_push -- ^]
+ *              :rtag[!] [string]
+ *
+ * Enter a new TAGQ context based on a ctag string.
+ *
+ * PUBLIC: int ex_rtag_push __P((SCR *, EXCMD *));
+ */
+int
+ex_rtag_push(SCR *sp, EXCMD *cmdp)
+{
+       F_SET(cmdp, E_REFERENCE);
+       return ex_tag_push(sp, cmdp);
+}
+#endif
+
+/*
+ * ex_tag_push -- ^]
+ *               :tag[!] [string]
+ *
+ * Enter a new TAGQ context based on a ctag string.
+ *
+ * PUBLIC: int ex_tag_push __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_push(SCR *sp, EXCMD *cmdp)
+{
+       EX_PRIVATE *exp;
+       TAGQ *tqp;
+       unsigned long tl;
+
+       exp = EXP(sp);
+       switch (cmdp->argc) {
+       case 1:
+               if (exp->tag_last != NULL)
+                       free(exp->tag_last);
+
+               if ((exp->tag_last = v_wstrdup(sp, cmdp->argv[0]->bp,
+                   cmdp->argv[0]->len)) == NULL) {
+                       msgq(sp, M_SYSERR, NULL);
+                       return (1);
+               }
+
+               /* Taglength may limit the number of characters. */
+               if ((tl =
+                   O_VAL(sp, O_TAGLENGTH)) != 0 && STRLEN(exp->tag_last) > tl)
+                       exp->tag_last[tl] = '\0';
+               break;
+       case 0:
+               if (exp->tag_last == NULL) {
+                       msgq(sp, M_ERR, "158|No previous tag entered");
+                       return (1);
+               }
+               break;
+       default:
+               abort();
+       }
+
+       /* Get the tag information. */
+#ifdef GTAGS
+       if (O_ISSET(sp, O_GTAGSMODE)) {
+               if ((tqp = gtag_slist(sp, exp->tag_last,
+                   F_ISSET(cmdp, E_REFERENCE))) == NULL)
+                       return (1);
+       } else
+#endif
+       if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL)
+               return (1);
+
+       if (tagq_push(sp, tqp, F_ISSET(cmdp, E_NEWSCREEN), 
+                              FL_ISSET(cmdp->iflags, E_C_FORCE)))
+               return 1;
+
+       return 0;
+}
+
+/* 
+ * ex_tag_next --
+ *     Switch context to the next TAG.
+ *
+ * PUBLIC: int ex_tag_next __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_next(SCR *sp, EXCMD *cmdp)
+{
+       EX_PRIVATE *exp;
+       TAG *tp;
+       TAGQ *tqp;
+       const char *np;
+       size_t nlen;
+
+       exp = EXP(sp);
+       if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
+               tag_msg(sp, TAG_EMPTY, NULL);
+               return (1);
+       }
+       if ((tp = tqp->current->q.cqe_next) == (void *)&tqp->tagq) {
+               msgq(sp, M_ERR, "282|Already at the last tag of this group");
+               return (1);
+       }
+       if (ex_tag_nswitch(sp, tp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+               return (1);
+       tqp->current = tp;
+
+       if (F_ISSET(tqp, TAG_CSCOPE))
+               (void)cscope_search(sp, tqp, tp);
+       else
+               (void)ctag_search(sp, tp->search, tp->slen, tqp->tag);
+       if (tqp->current->msg) {
+           INT2CHAR(sp, tqp->current->msg, tqp->current->mlen + 1,
+                    np, nlen);
+           msgq(sp, M_INFO, "%s", np);
+       }
+       return (0);
+}
+
+/* 
+ * ex_tag_prev --
+ *     Switch context to the next TAG.
+ *
+ * PUBLIC: int ex_tag_prev __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_prev(SCR *sp, EXCMD *cmdp)
+{
+       EX_PRIVATE *exp;
+       TAG *tp;
+       TAGQ *tqp;
+       const char *np;
+       size_t nlen;
+
+       exp = EXP(sp);
+       if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
+               tag_msg(sp, TAG_EMPTY, NULL);
+               return (0);
+       }
+       if ((tp = tqp->current->q.cqe_prev) == (void *)&tqp->tagq) {
+               msgq(sp, M_ERR, "255|Already at the first tag of this group");
+               return (1);
+       }
+       if (ex_tag_nswitch(sp, tp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+               return (1);
+       tqp->current = tp;
+
+       if (F_ISSET(tqp, TAG_CSCOPE))
+               (void)cscope_search(sp, tqp, tp);
+       else
+               (void)ctag_search(sp, tp->search, tp->slen, tqp->tag);
+       if (tqp->current->msg) {
+           INT2CHAR(sp, tqp->current->msg, tqp->current->mlen + 1,
+                    np, nlen);
+           msgq(sp, M_INFO, "%s", np);
+       }
+       return (0);
+}
+
+/*
+ * ex_tag_nswitch --
+ *     Switch context to the specified TAG.
+ *
+ * PUBLIC: int ex_tag_nswitch __P((SCR *, TAG *, int));
+ */
+int
+ex_tag_nswitch(SCR *sp, TAG *tp, int force)
+{
+       /* Get a file structure. */
+       if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL)
+               return (1);
+
+       /* If not changing files, return, we're done. */
+       if (tp->frp == sp->frp)
+               return (0);
+
+       /* Check for permission to leave. */
+       if (file_m1(sp, force, FS_ALL | FS_POSSIBLE))
+               return (1);
+
+       /* Initialize the new file. */
+       if (file_init(sp, tp->frp, NULL, FS_SETALT))
+               return (1);
+
+       /* Display tags in the center of the screen. */
+       F_CLR(sp, SC_SCR_TOP);
+       F_SET(sp, SC_SCR_CENTER);
+
+       /* Switch. */
+       F_SET(sp, SC_FSWITCH);
+       return (0);
+}
+
+/*
+ * ex_tag_Nswitch --
+ *     Switch context to the specified TAG in a new screen.
+ *
+ * PUBLIC: int ex_tag_Nswitch __P((SCR *, TAG *, int));
+ */
+int
+ex_tag_Nswitch(SCR *sp, TAG *tp, int force)
+{
+       SCR *new;
+
+       /* Get a file structure. */
+       if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL)
+               return (1);
+
+       /* Get a new screen. */
+       if (screen_init(sp->gp, sp, &new))
+               return (1);
+       if (vs_split(sp, new, 0)) {
+               (void)file_end(new, new->ep, 1);
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* Get a backing file. */
+       if (tp->frp == sp->frp) {
+               /* Copy file state. */
+               new->ep = sp->ep;
+               ++new->ep->refcnt;
+               CIRCLEQ_INSERT_HEAD(&new->ep->scrq, new, eq);
+
+               new->frp = tp->frp;
+               new->frp->flags = sp->frp->flags;
+       } else if (file_init(new, tp->frp, NULL, force)) {
+               (void)vs_discard(new, NULL);
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* Create the argument list. */
+       new->cargv = new->argv = ex_buildargv(sp, NULL, tp->frp->name);
+
+       /* Display tags in the center of the screen. */
+       F_CLR(new, SC_SCR_TOP);
+       F_SET(new, SC_SCR_CENTER);
+
+       /* Switch. */
+       sp->nextdisp = new;
+       F_SET(sp, SC_SSWITCH);
+
+       return (0);
+}
+
+/*
+ * ex_tag_pop -- ^T
+ *              :tagp[op][!] [number | file]
+ *
+ *     Pop to a previous TAGQ context.
+ *
+ * PUBLIC: int ex_tag_pop __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_pop(SCR *sp, EXCMD *cmdp)
+{
+       EX_PRIVATE *exp;
+       TAGQ *tqp, *dtqp = NULL;
+       size_t arglen;
+       long off;
+       const char *arg;
+       char *p, *t;
+       size_t nlen;
+
+       /* Check for an empty stack. */
+       exp = EXP(sp);
+       if (exp->tq.cqh_first == (void *)&exp->tq) {
+               tag_msg(sp, TAG_EMPTY, NULL);
+               return (1);
+       }
+
+       /* Find the last TAG structure that we're going to DISCARD! */
+       switch (cmdp->argc) {
+       case 0:                         /* Pop one tag. */
+               dtqp = exp->tq.cqh_first;
+               break;
+       case 1:                         /* Name or number. */
+               INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len+1, 
+                        arg, nlen);
+               off = strtol(arg, &p, 10);
+               if (*p != '\0')
+                       goto filearg;
+
+               /* Number: pop that many queue entries. */
+               if (off < 1)
+                       return (0);
+               for (tqp = exp->tq.cqh_first;
+                   tqp != (void *)&exp->tq && --off > 1;
+                   tqp = tqp->q.cqe_next);
+               if (tqp == (void *)&exp->tq) {
+                       msgq(sp, M_ERR,
+       "159|Less than %s entries on the tags stack; use :display t[ags]",
+                           arg);
+                       return (1);
+               }
+               dtqp = tqp;
+               break;
+
+               /* File argument: pop to that queue entry. */
+filearg:       arglen = strlen(arg);
+               for (tqp = exp->tq.cqh_first;
+                   tqp != (void *)&exp->tq;
+                   dtqp = tqp, tqp = tqp->q.cqe_next) {
+                       /* Don't pop to the current file. */
+                       if (tqp == exp->tq.cqh_first)
+                               continue;
+                       p = tqp->current->frp->name;
+                       if ((t = strrchr(p, '/')) == NULL)
+                               t = p;
+                       else
+                               ++t;
+                       if (!strncmp(arg, t, arglen))
+                               break;
+               }
+               if (tqp == (void *)&exp->tq) {
+                       msgq_str(sp, M_ERR, arg,
+       "160|No file %s on the tags stack to return to; use :display t[ags]");
+                       return (1);
+               }
+               if (tqp == exp->tq.cqh_first)
+                       return (0);
+               break;
+       default:
+               abort();
+       }
+
+       return (tag_pop(sp, dtqp, FL_ISSET(cmdp->iflags, E_C_FORCE)));
+}
+
+/*
+ * ex_tag_top -- :tagt[op][!]
+ *     Clear the tag stack.
+ *
+ * PUBLIC: int ex_tag_top __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_top(SCR *sp, EXCMD *cmdp)
+{
+       EX_PRIVATE *exp;
+
+       exp = EXP(sp);
+
+       /* Check for an empty stack. */
+       if (exp->tq.cqh_first == (void *)&exp->tq) {
+               tag_msg(sp, TAG_EMPTY, NULL);
+               return (1);
+       }
+
+       /* Return to the oldest information. */
+       return (tag_pop(sp,
+           exp->tq.cqh_last->q.cqe_prev, FL_ISSET(cmdp->iflags, E_C_FORCE)));
+}
+
+/*
+ * tag_pop --
+ *     Pop up to and including the specified TAGQ context.
+ */
+static int
+tag_pop(SCR *sp, TAGQ *dtqp, int force)
+{
+       EX_PRIVATE *exp;
+       TAG *tp;
+       TAGQ *tqp;
+
+       exp = EXP(sp);
+
+       /*
+        * Update the cursor from the saved TAG information of the TAG
+        * structure we're moving to.
+        */
+       tp = dtqp->q.cqe_next->current;
+       if (tp->frp == sp->frp) {
+               sp->lno = tp->lno;
+               sp->cno = tp->cno;
+       } else {
+               if (file_m1(sp, force, FS_ALL | FS_POSSIBLE))
+                       return (1);
+
+               tp->frp->lno = tp->lno;
+               tp->frp->cno = tp->cno;
+               F_SET(sp->frp, FR_CURSORSET);
+               if (file_init(sp, tp->frp, NULL, FS_SETALT))
+                       return (1);
+
+               F_SET(sp, SC_FSWITCH);
+       }
+
+       /* Pop entries off the queue up to and including dtqp. */
+       do {
+               tqp = exp->tq.cqh_first;
+               if (tagq_free(sp, tqp))
+                       return (0);
+       } while (tqp != dtqp);
+
+       /*
+        * If only a single tag left, we've returned to the first tag point,
+        * and the stack is now empty.
+        */
+       if (exp->tq.cqh_first->q.cqe_next == (void *)&exp->tq)
+               tagq_free(sp, exp->tq.cqh_first);
+
+       return (0);
+}
+
+/*
+ * ex_tag_display --
+ *     Display the list of tags.
+ *
+ * PUBLIC: int ex_tag_display __P((SCR *));
+ */
+int
+ex_tag_display(SCR *sp)
+{
+       EX_PRIVATE *exp;
+       TAG *tp;
+       TAGQ *tqp;
+       int cnt;
+       size_t len;
+       char *p;
+
+       exp = EXP(sp);
+       if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
+               tag_msg(sp, TAG_EMPTY, NULL);
+               return (0);
+       }
+
+       /*
+        * We give the file name 20 columns and the search string the rest.
+        * If there's not enough room, we don't do anything special, it's
+        * not worth the effort, it just makes the display more confusing.
+        *
+        * We also assume that characters in file names map 1-1 to printing
+        * characters.  This might not be true, but I don't think it's worth
+        * fixing.  (The obvious fix is to pass the filenames through the
+        * msg_print function.)
+        */
+#define        L_NAME  30              /* Name. */
+#define        L_SLOP   4              /* Leading number plus trailing *. */
+#define        L_SPACE  5              /* Spaces after name, before tag. */
+#define        L_TAG   20              /* Tag. */
+       if (sp->cols <= L_NAME + L_SLOP) {
+               msgq(sp, M_ERR, "292|Display too small.");
+               return (0);
+       }
+
+       /*
+        * Display the list of tags for each queue entry.  The first entry
+        * is numbered, and the current tag entry has an asterisk appended.
+        */
+       for (cnt = 1, tqp = exp->tq.cqh_first; !INTERRUPTED(sp) &&
+           tqp != (void *)&exp->tq; ++cnt, tqp = tqp->q.cqe_next)
+               for (tp = tqp->tagq.cqh_first;
+                   tp != (void *)&tqp->tagq; tp = tp->q.cqe_next) {
+                       if (tp == tqp->tagq.cqh_first)
+                               (void)ex_printf(sp, "%2d ", cnt);
+                       else
+                               (void)ex_printf(sp, "   ");
+                       p = tp->frp == NULL ? tp->fname : tp->frp->name;
+                       if ((len = strlen(p)) > L_NAME) {
+                               len = len - (L_NAME - 4);
+                               (void)ex_printf(sp, "   ... %*.*s",
+                                   L_NAME - 4, L_NAME - 4, p + len);
+                       } else
+                               (void)ex_printf(sp,
+                                   "   %*.*s", L_NAME, L_NAME, p);
+                       if (tqp->current == tp)
+                               (void)ex_printf(sp, "*");
+
+                       if (tp == tqp->tagq.cqh_first && tqp->tag != NULL &&
+                           (sp->cols - L_NAME) >= L_TAG + L_SPACE) {
+                               len = strlen(tqp->tag);
+                               if (len > sp->cols - (L_NAME + L_SPACE))
+                                       len = sp->cols - (L_NAME + L_SPACE);
+                               (void)ex_printf(sp, "%s%.*s",
+                                   tqp->current == tp ? "    " : "     ",
+                                   (int)len, tqp->tag);
+                       }
+                       (void)ex_printf(sp, "\n");
+               }
+       return (0);
+}
+
+/*
+ * ex_tag_copy --
+ *     Copy a screen's tag structures.
+ *
+ * PUBLIC: int ex_tag_copy __P((SCR *, SCR *));
+ */
+int
+ex_tag_copy(SCR *orig, SCR *sp)
+{
+       EX_PRIVATE *oexp, *nexp;
+       TAGQ *aqp, *tqp;
+       TAG *ap, *tp;
+       TAGF *atfp, *tfp;
+
+       oexp = EXP(orig);
+       nexp = EXP(sp);
+
+       /* Copy tag queue and tags stack. */
+       for (aqp = oexp->tq.cqh_first;
+           aqp != (void *)&oexp->tq; aqp = aqp->q.cqe_next) {
+               if (tagq_copy(sp, aqp, &tqp))
+                       return (1);
+               for (ap = aqp->tagq.cqh_first;
+                   ap != (void *)&aqp->tagq; ap = ap->q.cqe_next) {
+                       if (tag_copy(sp, ap, &tp))
+                               return (1);
+                       /* Set the current pointer. */
+                       if (aqp->current == ap)
+                               tqp->current = tp;
+                       CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+               }
+               CIRCLEQ_INSERT_TAIL(&nexp->tq, tqp, q);
+       }
+
+       /* Copy list of tag files. */
+       for (atfp = oexp->tagfq.tqh_first;
+           atfp != NULL; atfp = atfp->q.tqe_next) {
+               if (tagf_copy(sp, atfp, &tfp))
+                       return (1);
+               TAILQ_INSERT_TAIL(&nexp->tagfq, tfp, q);
+       }
+
+       /* Copy the last tag. */
+       if (oexp->tag_last != NULL &&
+           (nexp->tag_last = v_wstrdup(sp, oexp->tag_last, 
+                                       STRLEN(oexp->tag_last))) == NULL) {
+               msgq(sp, M_SYSERR, NULL);
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * tagf_copy --
+ *     Copy a TAGF structure and return it in new memory.
+ */
+static int
+tagf_copy(SCR *sp, TAGF *otfp, TAGF **tfpp)
+{
+       TAGF *tfp;
+
+       MALLOC_RET(sp, tfp, TAGF *, sizeof(TAGF));
+       *tfp = *otfp;
+
+       /* XXX: Allocate as part of the TAGF structure!!! */
+       if ((tfp->name = strdup(otfp->name)) == NULL)
+               return (1);
+
+       *tfpp = tfp;
+       return (0);
+}
+
+/*
+ * tagq_copy --
+ *     Copy a TAGQ structure and return it in new memory.
+ */
+static int
+tagq_copy(SCR *sp, TAGQ *otqp, TAGQ **tqpp)
+{
+       TAGQ *tqp;
+       size_t len;
+
+       len = sizeof(TAGQ);
+       if (otqp->tag != NULL)
+               len += otqp->tlen + 1;
+       MALLOC_RET(sp, tqp, TAGQ *, len);
+       memcpy(tqp, otqp, len);
+
+       CIRCLEQ_INIT(&tqp->tagq);
+       tqp->current = NULL;
+       if (otqp->tag != NULL)
+               tqp->tag = tqp->buf;
+
+       *tqpp = tqp;
+       return (0);
+}
+
+/*
+ * tag_copy --
+ *     Copy a TAG structure and return it in new memory.
+ */
+static int
+tag_copy(SCR *sp, TAG *otp, TAG **tpp)
+{
+       TAG *tp;
+       size_t len;
+
+       len = sizeof(TAG);
+       if (otp->fname != NULL)
+               len += otp->fnlen + 1;
+       if (otp->search != NULL)
+               len += otp->slen + 1;
+       if (otp->msg != NULL)
+               len += otp->mlen + 1;
+       MALLOC_RET(sp, tp, TAG *, len);
+       memcpy(tp, otp, len);
+
+       if (otp->fname != NULL)
+               tp->fname = (char *)tp->buf;
+       if (otp->search != NULL)
+               tp->search = tp->buf + (otp->search - otp->buf);
+       if (otp->msg != NULL)
+               tp->msg = tp->buf + (otp->msg - otp->buf);
+
+       *tpp = tp;
+       return (0);
+}
+
+/*
+ * tagf_free --
+ *     Free a TAGF structure.
+ */
+static int
+tagf_free(SCR *sp, TAGF *tfp)
+{
+       EX_PRIVATE *exp;
+
+       exp = EXP(sp);
+       TAILQ_REMOVE(&exp->tagfq, tfp, q);
+       free(tfp->name);
+       free(tfp);
+       return (0);
+}
+
+/*
+ * tagq_free --
+ *     Free a TAGQ structure (and associated TAG structures).
+ *
+ * PUBLIC: int tagq_free __P((SCR *, TAGQ *));
+ */
+int
+tagq_free(SCR *sp, TAGQ *tqp)
+{
+       EX_PRIVATE *exp;
+       TAG *tp;
+
+       exp = EXP(sp);
+       while ((tp = tqp->tagq.cqh_first) != (void *)&tqp->tagq) {
+               CIRCLEQ_REMOVE(&tqp->tagq, tp, q);
+               free(tp);
+       }
+       /*
+        * !!!
+        * If allocated and then the user failed to switch files, the TAGQ
+        * structure was never attached to any list.
+        */
+       if (tqp->q.cqe_next != NULL)
+               CIRCLEQ_REMOVE(&exp->tq, tqp, q);
+       free(tqp);
+       return (0);
+}
+
+/*
+ * PUBLIC: int tagq_push __P((SCR*, TAGQ*, int, int ));
+ */
+int
+tagq_push(SCR *sp, TAGQ *tqp, int new_screen, int force)
+{
+       EX_PRIVATE *exp;
+       FREF *frp;
+       TAG *rtp;
+       TAGQ *rtqp;
+       db_recno_t lno;
+       size_t cno;
+       int istmp;
+       const char *np;
+       size_t nlen;
+
+       exp = EXP(sp);
+
+       /*
+        * Allocate all necessary memory before swapping screens.  Initialize
+        * flags so we know what to free.
+        */
+       rtp = NULL;
+       rtqp = NULL;
+       if (exp->tq.cqh_first == (void *)&exp->tq) {
+               /* Initialize the `local context' tag queue structure. */
+               CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
+               CIRCLEQ_INIT(&rtqp->tagq);
+
+               /* Initialize and link in its tag structure. */
+               CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
+               CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
+               rtqp->current = rtp;
+       }
+
+       /*
+        * Stick the current context information in a convenient place, we're
+        * about to lose it.  Note, if we're called on editor startup, there
+        * will be no FREF structure.
+        */
+       frp = sp->frp;
+       lno = sp->lno;
+       cno = sp->cno;
+       istmp = frp == NULL || (F_ISSET(frp, FR_TMPFILE) && !new_screen);
+
+       /* Try to switch to the tag. */
+       if (new_screen) {
+               if (ex_tag_Nswitch(sp, tqp->tagq.cqh_first, force))
+                       goto err;
+
+               /* Everything else gets done in the new screen. */
+               sp = sp->nextdisp;
+               exp = EXP(sp);
+       } else
+               if (ex_tag_nswitch(sp, tqp->tagq.cqh_first, force))
+                       goto err;
+
+       /*
+        * If this is the first tag, put a `current location' queue entry
+        * in place, so we can pop all the way back to the current mark.
+        * Note, it doesn't point to much of anything, it's a placeholder.
+        */
+       if (exp->tq.cqh_first == (void *)&exp->tq) {
+               CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
+       } else
+               rtqp = exp->tq.cqh_first;
+
+       /* Link the new TAGQ structure into place. */
+       CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
+
+       (void)ctag_search(sp,
+           tqp->current->search, tqp->current->slen, tqp->tag);
+       if (tqp->current->msg) {
+           INT2CHAR(sp, tqp->current->msg, tqp->current->mlen + 1,
+                    np, nlen);
+           msgq(sp, M_INFO, "%s", np);
+       }
+
+       /*
+        * Move the current context from the temporary save area into the
+        * right structure.
+        *
+        * If we were in a temporary file, we don't have a context to which
+        * we can return, so just make it be the same as what we're moving
+        * to.  It will be a little odd that ^T doesn't change anything, but
+        * I don't think it's a big deal.
+        */
+       if (istmp) {
+               rtqp->current->frp = sp->frp;
+               rtqp->current->lno = sp->lno;
+               rtqp->current->cno = sp->cno;
+       } else {
+               rtqp->current->frp = frp;
+               rtqp->current->lno = lno;
+               rtqp->current->cno = cno;
+       }
+       return (0);
+
+err:
+alloc_err:
+       if (rtqp != NULL)
+               free(rtqp);
+       if (rtp != NULL)
+               free(rtp);
+       tagq_free(sp, tqp);
+       return (1);
+}
+
+/*
+ * tag_msg
+ *     A few common messages.
+ *
+ * PUBLIC: void tag_msg __P((SCR *, tagmsg_t, char *));
+ */
+void
+tag_msg(SCR *sp, tagmsg_t msg, char *tag)
+{
+       switch (msg) {
+       case TAG_BADLNO:
+               msgq_str(sp, M_ERR, tag,
+           "164|%s: the tag's line number is past the end of the file");
+               break;
+       case TAG_EMPTY:
+               msgq(sp, M_INFO, "165|The tags stack is empty");
+               break;
+       case TAG_SEARCH:
+               msgq_str(sp, M_ERR, tag, "166|%s: search pattern not found");
+               break;
+       default:
+               abort();
+       }
+}
+
+/*
+ * ex_tagf_alloc --
+ *     Create a new list of ctag files.
+ *
+ * PUBLIC: int ex_tagf_alloc __P((SCR *, const char *));
+ */
+int
+ex_tagf_alloc(SCR *sp, const char *str)
+{
+       EX_PRIVATE *exp;
+       TAGF *tfp;
+       size_t len;
+       const char *p, *t;
+
+       /* Free current queue. */
+       exp = EXP(sp);
+       while ((tfp = exp->tagfq.tqh_first) != NULL)
+               tagf_free(sp, tfp);
+
+       /* Create new queue. */
+       for (p = t = str;; ++p) {
+               if (*p == '\0' || isblank((unsigned char)*p)) {
+                       if ((len = p - t) > 1) {
+                               MALLOC_RET(sp, tfp, TAGF *, sizeof(TAGF));
+                               MALLOC(sp, tfp->name, char *, len + 1);
+                               if (tfp->name == NULL) {
+                                       free(tfp);
+                                       return (1);
+                               }
+                               memcpy(tfp->name, t, len);
+                               tfp->name[len] = '\0';
+                               tfp->flags = 0;
+                               TAILQ_INSERT_TAIL(&exp->tagfq, tfp, q);
+                       }
+                       t = p + 1;
+               }
+               if (*p == '\0')
+                        break;
+       }
+       return (0);
+}
+                                               /* Free previous queue. */
+/*
+ * ex_tag_free --
+ *     Free the ex tag information.
+ *
+ * PUBLIC: int ex_tag_free __P((SCR *));
+ */
+int
+ex_tag_free(SCR *sp)
+{
+       EX_PRIVATE *exp;
+       TAGF *tfp;
+       TAGQ *tqp;
+
+       /* Free up tag information. */
+       exp = EXP(sp);
+       while ((tqp = exp->tq.cqh_first) != (void *)&exp->tq)
+               tagq_free(sp, tqp);
+       while ((tfp = exp->tagfq.tqh_first) != NULL)
+               tagf_free(sp, tfp);
+       if (exp->tag_last != NULL)
+               free(exp->tag_last);
+       return (0);
+}
+
+/*
+ * ctag_search --
+ *     Search a file for a tag.
+ */
+static int
+ctag_search(SCR *sp, CHAR_T *search, size_t slen, char *tag)
+{
+       MARK m;
+       char *p;
+       const char *np;
+       size_t nlen;
+
+       /*
+        * !!!
+        * The historic tags file format (from a long, long time ago...)
+        * used a line number, not a search string.  I got complaints, so
+        * people are still using the format.  POSIX 1003.2 permits it.
+        */
+       if (ISDIGIT((UCHAR_T)search[0])) {
+               INT2CHAR(sp, search, slen+1, np, nlen);
+               m.lno = atoi(np);
+               if (!db_exist(sp, m.lno)) {
+                       tag_msg(sp, TAG_BADLNO, tag);
+                       return (1);
+               }
+       } else {
+               /*
+                * Search for the tag; cheap fallback for C functions
+                * if the name is the same but the arguments have changed.
+                */
+               m.lno = 1;
+               m.cno = 0;
+               if (f_search(sp, &m, &m,
+                   search, slen, NULL, 
+                   SEARCH_FIRST | SEARCH_TAG | SEARCH_PARSE)) {
+                       INT2CHAR(sp, search, slen, np, nlen);
+                       if ((p = strrchr(np, '(')) != NULL) {
+                               slen = p - np;
+                               if (f_search(sp, &m, &m, search, slen,
+                                   NULL, SEARCH_FIRST | SEARCH_TAG))
+                                       goto notfound;
+                       } else {
+notfound:                      tag_msg(sp, TAG_SEARCH, tag);
+                               return (1);
+                       }
+               }
+               /*
+                * !!!
+                * Historically, tags set the search direction if it wasn't
+                * already set.
+                */
+               if (sp->searchdir == NOTSET)
+                       sp->searchdir = FORWARD;
+       }
+
+       /*
+        * !!!
+        * Tags move to the first non-blank, NOT the search pattern start.
+        */
+       sp->lno = m.lno;
+       sp->cno = 0;
+       (void)nonblank(sp, sp->lno, &sp->cno);
+       return (0);
+}
+
+#ifdef GTAGS
+/*
+ * getentry --
+ *     get tag information from current line.
+ *
+ * gtags temporary file format.
+ * <tag>   <lineno>  <file>         <image>
+ *
+ * sample.
+ * +------------------------------------------------
+ * |main     30      main.c         main(argc, argv)
+ * |func     21      subr.c         func(arg)
+ */
+static int
+getentry(char *buf, char **tag, char **file, char **line)
+{
+       char *p = buf;
+
+       for (*tag = p; *p && !isspace((unsigned char)*p); p++)  /* tag name */
+               ;
+       if (*p == 0)
+               goto err;
+       *p++ = 0;
+       for (; *p && isspace((unsigned char)*p); p++)   /* (skip blanks) */
+               ;
+       if (*p == 0)
+               goto err;
+       *line = p;                                      /* line no */
+       for (*line = p; *p && !isspace((unsigned char)*p); p++)
+               ;
+       if (*p == 0)
+               goto err;
+       *p++ = 0;
+       for (; *p && isspace((unsigned char)*p); p++)   /* (skip blanks) */
+               ;
+       if (*p == 0)
+               goto err;
+       *file = p;                                      /* file name */
+       for (*file = p; *p && !isspace((unsigned char)*p); p++)
+               ;
+       if (*p == 0)
+               goto err;
+       *p = 0;
+
+       /* value check */
+       if (strlen(*tag) && strlen(*line) && strlen(*file) && atoi(*line) > 0)
+               return 1;       /* OK */
+err:
+       return 0;               /* ERROR */
+}
+
+/*
+ * gtag_slist --
+ *     Search the list of tags files for a tag, and return tag queue.
+ */
+static TAGQ *
+gtag_slist(SCR *sp, CHAR_T *tag, int ref)
+{
+       TAGQ *tqp;
+       size_t len, nlen, slen, wlen;
+       int echk;
+       TAG *tp;
+       const char *np;
+       char *name, *file, *search;
+       char command[BUFSIZ];
+       char buf[BUFSIZ];
+       const CHAR_T *wp;
+       FILE *fp;
+
+       /* Allocate and initialize the tag queue structure. */
+       INT2CHAR(sp, tag, STRLEN(tag) + 1, np, nlen);
+       len = nlen - 1;
+       CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
+       CIRCLEQ_INIT(&tqp->tagq);
+       tqp->tag = tqp->buf;
+       memcpy(tqp->tag, np, (tqp->tlen = len) + 1);
+
+       /*
+        * Find the tag, only display missing file messages once, and
+        * then only if we didn't find the tag.
+        */
+       snprintf(command, sizeof(command), "global -%s '%s'", ref ? "rx" : "x",
+           np);
+       if ((fp = popen(command, "r")) != NULL) {
+               while (fgets(buf, sizeof(buf), fp)) {
+                       if (buf[strlen(buf)-1] == '\n')         /* chop(buf) */
+                               buf[strlen(buf)-1] = 0;
+                       else
+                               while (fgetc(fp) != '\n')
+                                       ;
+                       if (getentry(buf, &name, &file, &search) == 0) {
+                               echk = 1;
+                               break;
+                       }
+                       slen = strlen(search);
+                       CALLOC_GOTO(sp, tp,
+                           TAG *, 1, sizeof(TAG) + strlen(file) + 1 +
+                           (slen + 1) * sizeof(CHAR_T));
+                       tp->fname = (char *)tp->buf;
+                       strcpy(tp->fname, file);
+                       tp->fnlen = strlen(file);
+                       tp->search = (CHAR_T *)(tp->fname + tp->fnlen + 1);
+                       CHAR2INT(sp, search, slen + 1, wp, wlen);
+                       MEMCPYW(tp->search, wp, (tp->slen = slen) + 1);
+                       CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+               }
+               pclose(fp);
+       }
+
+       /* Check to see if we found anything. */
+       if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
+               msgq_str(sp, M_ERR, np, "162|%s: tag not found");
+               free(tqp);
+               return (NULL);
+       }
+
+       tqp->current = tqp->tagq.cqh_first;
+       return (tqp);
+
+alloc_err:
+       return (NULL);
+}
+#endif
+
+/*
+ * ctag_slist --
+ *     Search the list of tags files for a tag, and return tag queue.
+ */
+static TAGQ *
+ctag_slist(SCR *sp, CHAR_T *tag)
+{
+       EX_PRIVATE *exp;
+       TAGF *tfp;
+       TAGQ *tqp;
+       size_t len;
+       int echk;
+       const char *np;
+       size_t nlen;
+
+       exp = EXP(sp);
+
+       /* Allocate and initialize the tag queue structure. */
+       INT2CHAR(sp, tag, STRLEN(tag) + 1, np, nlen);
+       len = nlen - 1;
+       CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
+       CIRCLEQ_INIT(&tqp->tagq);
+       tqp->tag = tqp->buf;
+       memcpy(tqp->tag, np, (tqp->tlen = len) + 1);
+
+       /*
+        * Find the tag, only display missing file messages once, and
+        * then only if we didn't find the tag.
+        */
+       for (echk = 0,
+           tfp = exp->tagfq.tqh_first; tfp != NULL; tfp = tfp->q.tqe_next)
+               if (ctag_sfile(sp, tfp, tqp, tqp->tag)) {
+                       echk = 1;
+                       F_SET(tfp, TAGF_ERR);
+               } else
+                       F_CLR(tfp, TAGF_ERR | TAGF_ERR_WARN);
+
+       /* Check to see if we found anything. */
+       if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
+               msgq_str(sp, M_ERR, tqp->tag, "162|%s: tag not found");
+               if (echk)
+                       for (tfp = exp->tagfq.tqh_first;
+                           tfp != NULL; tfp = tfp->q.tqe_next)
+                               if (F_ISSET(tfp, TAGF_ERR) &&
+                                   !F_ISSET(tfp, TAGF_ERR_WARN)) {
+                                       errno = tfp->errnum;
+                                       msgq_str(sp, M_SYSERR, tfp->name, "%s");
+                                       F_SET(tfp, TAGF_ERR_WARN);
+                               }
+               free(tqp);
+               return (NULL);
+       }
+
+       tqp->current = tqp->tagq.cqh_first;
+       return (tqp);
+
+alloc_err:
+       return (NULL);
+}
+
+/*
+ * ctag_sfile --
+ *     Search a tags file for a tag, adding any found to the tag queue.
+ */
+static int
+ctag_sfile(SCR *sp, TAGF *tfp, TAGQ *tqp, char *tname)
+{
+       struct stat sb;
+       TAG *tp;
+       size_t dlen, nlen = 0, slen;
+       int fd, i, nf1, nf2;
+       char *back, *front, *map, *p, *search, *t;
+       char *cname = NULL, *dname = NULL, *name = NULL;
+       const CHAR_T *wp;
+       size_t wlen;
+       unsigned long tl;
+
+       if ((fd = open(tfp->name, O_RDONLY, 0)) < 0) {
+               tfp->errnum = errno;
+               return (1);
+       }
+
+#if defined(__minix)
+       return (1);
+#else
+       /*
+        * XXX
+        * Some old BSD systems require MAP_FILE as an argument when mapping
+        * regular files.
+        */
+#ifndef MAP_FILE
+#define        MAP_FILE        0
+#endif
+       /*
+        * XXX
+        * We'd like to test if the file is too big to mmap.  Since we don't
+        * know what size or type off_t's or size_t's are, what the largest
+        * unsigned integral type is, or what random insanity the local C
+        * compiler will perpetrate, doing the comparison in a portable way
+        * is flatly impossible.  Hope mmap fails if the file is too large.
+        */
+       if (fstat(fd, &sb) != 0 ||
+           (map = mmap(NULL, (size_t)sb.st_size, PROT_READ | PROT_WRITE,
+           MAP_FILE | MAP_PRIVATE, fd, (off_t)0)) == (caddr_t)-1) {
+               tfp->errnum = errno;
+               (void)close(fd);
+               return (1);
+       }
+
+       tl = O_VAL(sp, O_TAGLENGTH);
+       front = map;
+       back = front + sb.st_size;
+       front = binary_search(tname, front, back);
+       front = linear_search(tname, front, back, tl);
+       if (front == NULL)
+               goto done;
+
+       /*
+        * Initialize and link in the tag structure(s).  The historic ctags
+        * file format only permitted a single tag location per tag.  The
+        * obvious extension to permit multiple tags locations per tag is to
+        * output multiple records in the standard format.  Unfortunately,
+        * this won't work correctly with historic ex/vi implementations,
+        * because their binary search assumes that there's only one record
+        * per tag, and so will use a random tag entry if there si more than
+        * one.  This code handles either format.
+        *
+        * The tags file is in the following format:
+        *
+        *      <tag> <filename> <line number> | <pattern>
+        *
+        * Figure out how long everything is so we can allocate in one swell
+        * foop, but discard anything that looks wrong.
+        */
+       for (;;) {
+               /* Nul-terminate the end of the line. */
+               for (p = front; p < back && *p != '\n'; ++p);
+               if (p == back || *p != '\n')
+                       break;
+               *p = '\0';
+
+               /* Update the pointers for the next time. */
+               t = p + 1;
+               p = front;
+               front = t;
+
+               /* Break the line into tokens. */
+               for (i = 0; i < 2 && (t = strsep(&p, "\t ")) != NULL; ++i)
+                       switch (i) {
+                       case 0:                 /* Tag. */
+                               cname = t;
+                               break;
+                       case 1:                 /* Filename. */
+                               name = t;
+                               nlen = strlen(name);
+                               break;
+                       }
+
+               /* Check for corruption. */
+               if (i != 2 || p == NULL || t == NULL)
+                       goto corrupt;
+
+               /* The rest of the string is the search pattern. */
+               search = p;
+               if ((slen = strlen(p)) == 0) {
+corrupt:               p = msg_print(sp, tname, &nf1);
+                       t = msg_print(sp, tfp->name, &nf2);
+                       msgq(sp, M_ERR, "163|%s: corrupted tag in %s", p, t);
+                       if (nf1)
+                               FREE_SPACE(sp, p, 0);
+                       if (nf2)
+                               FREE_SPACE(sp, t, 0);
+                       continue;
+               }
+
+               /* Check for passing the last entry. */
+               if (tl ? strncmp(tname, cname, tl) : strcmp(tname, cname))
+                       break;
+
+               /* Resolve the file name. */
+               ctag_file(sp, tfp, name, &dname, &dlen);
+
+               CALLOC_GOTO(sp, tp,
+                   TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + 
+                   (slen + 1) * sizeof(CHAR_T));
+               tp->fname = (char *)tp->buf;
+               if (dlen != 0) {
+                       memcpy(tp->fname, dname, dlen);
+                       tp->fname[dlen] = '/';
+                       ++dlen;
+               }
+               memcpy(tp->fname + dlen, name, nlen + 1);
+               tp->fnlen = dlen + nlen;
+               tp->search = (CHAR_T*)(tp->fname + tp->fnlen + 1);
+               CHAR2INT(sp, search, slen + 1, wp, wlen);
+               MEMCPYW(tp->search, wp, (tp->slen = slen) + 1);
+               CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+       }
+
+alloc_err:
+done:  if (munmap(map, (size_t)sb.st_size))
+               msgq(sp, M_SYSERR, "munmap");
+       if (close(fd))
+               msgq(sp, M_SYSERR, "close");
+       return (0);
+#endif /* defined(__minix) */
+}
+
+/*
+ * ctag_file --
+ *     Search for the right path to this file.
+ */
+static void
+ctag_file(SCR *sp, TAGF *tfp, char *name, char **dirp, size_t *dlenp)
+{
+       struct stat sb;
+       size_t len;
+       char *p, buf[MAXPATHLEN];
+
+       /*
+        * !!!
+        * If the tag file path is a relative path, see if it exists.  If it
+        * doesn't, look relative to the tags file path.  It's okay for a tag
+        * file to not exist, and historically, vi simply displayed a "new"
+        * file.  However, if the path exists relative to the tag file, it's
+        * pretty clear what's happening, so we may as well get it right.
+        */
+       *dlenp = 0;
+       if (name[0] != '/' &&
+           stat(name, &sb) && (p = strrchr(tfp->name, '/')) != NULL) {
+               *p = '\0';
+               len = snprintf(buf, sizeof(buf), "%s/%s", tfp->name, name);
+               if (stat(buf, &sb) == 0) {
+                       *dirp = tfp->name;
+                       *dlenp = strlen(*dirp);
+               }
+               *p = '/';
+       }
+}
+
+/*
+ * Binary search for "string" in memory between "front" and "back".
+ *
+ * This routine is expected to return a pointer to the start of a line at
+ * *or before* the first word matching "string".  Relaxing the constraint
+ * this way simplifies the algorithm.
+ *
+ * Invariants:
+ *     front points to the beginning of a line at or before the first
+ *     matching string.
+ *
+ *     back points to the beginning of a line at or after the first
+ *     matching line.
+ *
+ * Base of the Invariants.
+ *     front = NULL;
+ *     back = EOF;
+ *
+ * Advancing the Invariants:
+ *
+ *     p = first newline after halfway point from front to back.
+ *
+ *     If the string at "p" is not greater than the string to match,
+ *     p is the new front.  Otherwise it is the new back.
+ *
+ * Termination:
+ *
+ *     The definition of the routine allows it return at any point,
+ *     since front is always at or before the line to print.
+ *
+ *     In fact, it returns when the chosen "p" equals "back".  This
+ *     implies that there exists a string is least half as long as
+ *     (back - front), which in turn implies that a linear search will
+ *     be no more expensive than the cost of simply printing a string or two.
+ *
+ *     Trying to continue with binary search at this point would be
+ *     more trouble than it's worth.
+ */
+#define        EQUAL           0
+#define        GREATER         1
+#define        LESS            (-1)
+
+#define        SKIP_PAST_NEWLINE(p, back)      while (p < back && *p++ != '\n') continue;
+
+static char *
+binary_search(register char *string, register char *front, register char *back)
+{
+       register char *p;
+
+       p = front + (back - front) / 2;
+       SKIP_PAST_NEWLINE(p, back);
+
+       while (p != back) {
+               if (compare(string, p, back) == GREATER)
+                       front = p;
+               else
+                       back = p;
+               p = front + (back - front) / 2;
+               SKIP_PAST_NEWLINE(p, back);
+       }
+       return (front);
+}
+
+/*
+ * Find the first line that starts with string, linearly searching from front
+ * to back.
+ *
+ * Return NULL for no such line.
+ *
+ * This routine assumes:
+ *
+ *     o front points at the first character in a line.
+ *     o front is before or at the first line to be printed.
+ */
+static char *
+linear_search(char *string, char *front, char *back, unsigned long tl)
+{
+       char *end;
+       while (front < back) {
+               end = tl && (unsigned long)(back-front) > tl ? front+tl : back;
+               switch (compare(string, front, end)) {
+               case EQUAL:             /* Found it. */
+                       return (front);
+               case LESS:              /* No such string. */
+                       return (NULL);
+               case GREATER:           /* Keep going. */
+                       break;
+               }
+               SKIP_PAST_NEWLINE(front, back);
+       }
+       return (NULL);
+}
+
+/*
+ * Return LESS, GREATER, or EQUAL depending on how the string1 compares
+ * with string2 (s1 ??? s2).
+ *
+ *     o Matches up to len(s1) are EQUAL.
+ *     o Matches up to len(s2) are GREATER.
+ *
+ * The string "s1" is null terminated.  The string s2 is '\t', space, (or
+ * "back") terminated.
+ *
+ * !!!
+ * Reasonably modern ctags programs use tabs as separators, not spaces.
+ * However, historic programs did use spaces, and, I got complaints.
+ */
+static int
+compare(register char *s1, register char *s2, register char *back)
+{
+       for (; *s1 && s2 < back && (*s2 != '\t' && *s2 != ' '); ++s1, ++s2)
+               if (*s1 != *s2)
+                       return (*s1 < *s2 ? LESS : GREATER);
+       return (*s1 ? GREATER : s2 < back &&
+           (*s2 != '\t' && *s2 != ' ') ? LESS : EQUAL);
+}
diff --git a/dist/nvi/ex/ex_tcl.c b/dist/nvi/ex/ex_tcl.c
new file mode 100644 (file)
index 0000000..4e24c5a
--- /dev/null
@@ -0,0 +1,80 @@
+/*     $NetBSD: ex_tcl.c,v 1.2 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1995
+ *     George V. Neville-Neil.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_tcl.c,v 8.11 2001/06/25 15:19:21 skimo Exp (Berkeley) Date: 2001/06/25 15:19:21";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+#ifdef HAVE_TCL_INTERP
+#include <tcl.h>
+#endif
+
+/* 
+ * ex_tcl -- :[line [,line]] tcl [command]
+ *     Run a command through the tcl interpreter.
+ *
+ * PUBLIC: int ex_tcl __P((SCR*, EXCMD *));
+ */
+int 
+ex_tcl(SCR *sp, EXCMD *cmdp)
+{
+#ifdef HAVE_TCL_INTERP
+       CHAR_T *p;
+       GS *gp;
+       size_t len;
+       char buf[128];
+
+       /* Initialize the interpreter. */
+       gp = sp->gp;
+       if (gp->tcl_interp == NULL && tcl_init(gp))
+               return (1);
+
+       /* Skip leading white space. */
+       if (cmdp->argc != 0)
+               for (p = cmdp->argv[0]->bp,
+                   len = cmdp->argv[0]->len; len > 0; --len, ++p)
+                       if (!ISBLANK((UCHAR_T)*p))
+                               break;
+       if (cmdp->argc == 0 || len == 0) {
+               ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+               return (1);
+       }
+
+       (void)snprintf(buf, sizeof(buf),
+           "set viScreenId %d\nset viStartLine %lu\nset viStopLine %lu",
+           sp->id, cmdp->addr1.lno, cmdp->addr2.lno);
+       if (Tcl_Eval(gp->tcl_interp, buf) == TCL_OK &&
+           Tcl_Eval(gp->tcl_interp, cmdp->argv[0]->bp) == TCL_OK)
+               return (0);
+
+       msgq(sp, M_ERR, "Tcl: %s", ((Tcl_Interp *)gp->tcl_interp)->result);
+       return (1);
+#else
+       msgq(sp, M_ERR, "302|Vi was not loaded with a Tcl interpreter");
+       return (1);
+#endif /* HAVE_TCL_INTERP */
+}
diff --git a/dist/nvi/ex/ex_txt.c b/dist/nvi/ex/ex_txt.c
new file mode 100644 (file)
index 0000000..ee10ac3
--- /dev/null
@@ -0,0 +1,432 @@
+/*     $NetBSD: ex_txt.c,v 1.6 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_txt.c,v 10.23 2001/06/25 15:19:21 skimo Exp (Berkeley) Date: 2001/06/25 15:19:21";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * !!!
+ * The backslash characters was special when it preceded a newline as part of
+ * a substitution replacement pattern.  For example, the input ":a\<cr>" would
+ * failed immediately with an error, as the <cr> wasn't part of a substitution
+ * replacement pattern.  This implies a frightening integration of the editor
+ * and the parser and/or the RE engine.  There's no way I'm going to reproduce
+ * those semantics.
+ *
+ * So, if backslashes are special, this code inserts the backslash and the next
+ * character into the string, without regard for the character or the command
+ * being entered.  Since "\<cr>" was illegal historically (except for the one
+ * special case), and the command will fail eventually, no historical scripts
+ * should break (presuming they didn't depend on the failure mode itself or the
+ * characters remaining when failure occurred.
+ */
+
+static int     txt_dent __P((SCR *, TEXT *));
+static void    txt_prompt __P((SCR *, TEXT *, ARG_CHAR_T, u_int32_t));
+
+/*
+ * ex_txt --
+ *     Get lines from the terminal for ex.
+ *
+ * PUBLIC: int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t));
+ */
+int
+ex_txt(SCR *sp, TEXTH *tiqh, ARG_CHAR_T prompt, u_int32_t flags)
+{
+       EVENT ev;
+       GS *gp;
+       TEXT ait, *ntp, *tp;
+       carat_t carat_st;
+       size_t cnt;
+       int rval;
+
+       rval = 0;
+
+       /*
+        * Get a TEXT structure with some initial buffer space, reusing the
+        * last one if it's big enough.  (All TEXT bookkeeping fields default
+        * to 0 -- text_init() handles this.)
+        */
+       if (tiqh->cqh_first != (void *)tiqh) {
+               tp = tiqh->cqh_first;
+               if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < 32) {
+                       text_lfree(tiqh);
+                       goto newtp;
+               }
+               tp->len = 0;
+       } else {
+newtp:         if ((tp = text_init(sp, NULL, 0, 32)) == NULL)
+                       goto err;
+               CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
+       }
+
+       /* Set the starting line number. */
+       tp->lno = sp->lno + 1;
+
+       /*
+        * If it's a terminal, set up autoindent, put out the prompt, and
+        * set it up so we know we were suspended.  Otherwise, turn off
+        * the autoindent flag, as that requires less special casing below.
+        *
+        * XXX
+        * Historic practice is that ^Z suspended command mode (but, because
+        * it ran in cooked mode, it was unaffected by the autowrite option.)
+        * On restart, any "current" input was discarded, whether in insert
+        * mode or not, and ex was in command mode.  This code matches historic
+        * practice, but not 'cause it's easier.
+        */
+       gp = sp->gp;
+       if (F_ISSET(gp, G_SCRIPTED))
+               LF_CLR(TXT_AUTOINDENT);
+       else {
+               if (LF_ISSET(TXT_AUTOINDENT)) {
+                       LF_SET(TXT_EOFCHAR);
+                       if (v_txt_auto(sp, sp->lno, NULL, 0, tp))
+                               goto err;
+               }
+               txt_prompt(sp, tp, prompt, flags);
+       }
+
+       for (carat_st = C_NOTSET;;) {
+               if (v_event_get(sp, &ev, 0, 0))
+                       goto err;
+
+               /* Deal with all non-character events. */
+               switch (ev.e_event) {
+               case E_CHARACTER:
+                       break;
+               case E_ERR:
+                       goto err;
+               case E_REPAINT:
+               case E_WRESIZE:
+                       continue;
+               case E_EOF:
+                       rval = 1;
+                       /* FALLTHROUGH */
+               case E_INTERRUPT:
+                       /*
+                        * Handle EOF/SIGINT events by discarding partially
+                        * entered text and returning.  EOF returns failure,
+                        * E_INTERRUPT returns success.
+                        */
+                       goto notlast;
+               default:
+                       v_event_err(sp, &ev);
+                       goto notlast;
+               }
+
+               /*
+                * Deal with character events.
+                *
+                * Check to see if the character fits into the input buffer.
+                * (Use tp->len, ignore overwrite and non-printable chars.)
+                */
+               BINC_GOTOW(sp, tp->lb, tp->lb_len, tp->len + 1);
+
+               switch (ev.e_value) {
+               case K_CR:
+                       /*
+                        * !!!
+                        * Historically, <carriage-return>'s in the command
+                        * weren't special, so the ex parser would return an
+                        * unknown command error message.  However, if they
+                        * terminated the command if they were in a map.  I'm
+                        * pretty sure this still isn't right, but it handles
+                        * what I've seen so far.
+                        */
+                       if (!FL_ISSET(ev.e_flags, CH_MAPPED))
+                               goto ins_ch;
+                       /* FALLTHROUGH */
+               case K_NL:
+                       /*
+                        * '\' can escape <carriage-return>/<newline>.  We
+                        * don't discard the backslash because we need it
+                        * to get the <newline> through the ex parser.
+                        */
+                       if (LF_ISSET(TXT_BACKSLASH) &&
+                           tp->len != 0 && tp->lb[tp->len - 1] == '\\')
+                               goto ins_ch;
+
+                       /*
+                        * CR returns from the ex command line.
+                        *
+                        * XXX
+                        * Terminate with a nul, needed by filter.
+                        */
+                       if (LF_ISSET(TXT_CR)) {
+                               tp->lb[tp->len] = '\0';
+                               goto done;
+                       }
+
+                       /*
+                        * '.' may terminate text input mode; free the current
+                        * TEXT.
+                        */
+                       if (LF_ISSET(TXT_DOTTERM) && tp->len == tp->ai + 1 &&
+                           tp->lb[tp->len - 1] == '.') {
+notlast:                       CIRCLEQ_REMOVE(tiqh, tp, q);
+                               text_free(tp);
+                               goto done;
+                       }
+
+                       /* Set up bookkeeping for the new line. */
+                       if ((ntp = text_init(sp, NULL, 0, 32)) == NULL)
+                               goto err;
+                       ntp->lno = tp->lno + 1;
+
+                       /*
+                        * Reset the autoindent line value.  0^D keeps the ai
+                        * line from changing, ^D changes the level, even if
+                        * there were no characters in the old line.  Note, if
+                        * using the current tp structure, use the cursor as
+                        * the length, the autoindent characters may have been
+                        * erased.
+                        */
+                       if (LF_ISSET(TXT_AUTOINDENT)) {
+                               if (carat_st == C_NOCHANGE) {
+                                       if (v_txt_auto(sp,
+                                           OOBLNO, &ait, ait.ai, ntp))
+                                               goto err;
+                                       free(ait.lb);
+                               } else
+                                       if (v_txt_auto(sp,
+                                           OOBLNO, tp, tp->len, ntp))
+                                               goto err;
+                               carat_st = C_NOTSET;
+                       }
+                       txt_prompt(sp, ntp, prompt, flags);
+
+                       /*
+                        * Swap old and new TEXT's, and insert the new TEXT
+                        * into the queue.
+                        */
+                       tp = ntp;
+                       CIRCLEQ_INSERT_TAIL(tiqh, tp, q);
+                       break;
+               case K_CARAT:                   /* Delete autoindent chars. */
+                       if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+                               carat_st = C_CARATSET;
+                       goto ins_ch;
+               case K_ZERO:                    /* Delete autoindent chars. */
+                       if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+                               carat_st = C_ZEROSET;
+                       goto ins_ch;
+               case K_CNTRLD:                  /* Delete autoindent char. */
+                       /*
+                        * !!!
+                        * Historically, the ^D command took (but then ignored)
+                        * a count.  For simplicity, we don't return it unless
+                        * it's the first character entered.  The check for len
+                        * equal to 0 is okay, TXT_AUTOINDENT won't be set.
+                        */
+                       if (LF_ISSET(TXT_CNTRLD)) {
+                               for (cnt = 0; cnt < tp->len; ++cnt)
+                                       if (!ISBLANK((UCHAR_T)tp->lb[cnt]))
+                                               break;
+                               if (cnt == tp->len) {
+                                       tp->len = 1;
+                                       tp->lb[0] = ev.e_c;
+                                       tp->lb[1] = '\0';
+
+                                       /*
+                                        * Put out a line separator, in case
+                                        * the command fails.
+                                        */
+                                       (void)putchar('\n');
+                                       goto done;
+                               }
+                       }
+
+                       /*
+                        * POSIX 1003.1b-1993, paragraph 7.1.1.9, states that
+                        * the EOF characters are discarded if there are other
+                        * characters to process in the line, i.e. if the EOF
+                        * is not the first character in the line.  For this
+                        * reason, historic ex discarded the EOF characters,
+                        * even if occurring in the middle of the input line.
+                        * We match that historic practice.
+                        *
+                        * !!!
+                        * The test for discarding in the middle of the line is
+                        * done in the switch, because the CARAT forms are N+1,
+                        * not N.
+                        *
+                        * !!!
+                        * There's considerable magic to make the terminal code
+                        * return the EOF character at all.  See that code for
+                        * details.
+                        */
+                       if (!LF_ISSET(TXT_AUTOINDENT) || tp->len == 0)
+                               continue;
+                       switch (carat_st) {
+                       case C_CARATSET:                /* ^^D */
+                               if (tp->len > tp->ai + 1)
+                                       continue;
+
+                               /* Save the ai string for later. */
+                               ait.lb = NULL;
+                               ait.lb_len = 0;
+                               BINC_GOTOW(sp, ait.lb, ait.lb_len, tp->ai);
+                               MEMCPYW(ait.lb, tp->lb, tp->ai);
+                               ait.ai = ait.len = tp->ai;
+
+                               carat_st = C_NOCHANGE;
+                               goto leftmargin;
+                       case C_ZEROSET:                 /* 0^D */
+                               if (tp->len > tp->ai + 1)
+                                       continue;
+
+                               carat_st = C_NOTSET;
+leftmargin:                    (void)gp->scr_ex_adjust(sp, EX_TERM_CE);
+                               tp->ai = tp->len = 0;
+                               break;
+                       case C_NOTSET:                  /* ^D */
+                               if (tp->len > tp->ai)
+                                       continue;
+
+                               if (txt_dent(sp, tp))
+                                       goto err;
+                               break;
+                       default:
+                               abort();
+                       }
+
+                       /* Clear and redisplay the line. */
+                       (void)gp->scr_ex_adjust(sp, EX_TERM_CE);
+                       txt_prompt(sp, tp, prompt, flags);
+                       break;
+               default:
+                       /*
+                        * See the TXT_BEAUTIFY comment in vi/v_txt_ev.c.
+                        *
+                        * Silently eliminate any iscntrl() character that was
+                        * not already handled specially, except for <tab> and
+                        * <ff>.
+                        */
+ins_ch:                        if (LF_ISSET(TXT_BEAUTIFY) && ISCNTRL(ev.e_c) &&
+                           ev.e_value != K_FORMFEED && ev.e_value != K_TAB)
+                               break;
+
+                       tp->lb[tp->len++] = ev.e_c;
+                       break;
+               }
+       }
+       /* NOTREACHED */
+
+done:  return (rval);
+
+err:   
+alloc_err:
+       return (1);
+}
+
+/*
+ * txt_prompt --
+ *     Display the ex prompt, line number, ai characters.  Characters had
+ *     better be printable by the terminal driver, but that's its problem,
+ *     not ours.
+ */
+static void
+txt_prompt(SCR *sp, TEXT *tp, ARG_CHAR_T prompt, u_int32_t flags)
+{
+       /* Display the prompt. */
+       if (LF_ISSET(TXT_PROMPT))
+               (void)ex_printf(sp, "%c", prompt);
+
+       /* Display the line number. */
+       if (LF_ISSET(TXT_NUMBER) && O_ISSET(sp, O_NUMBER))
+               (void)ex_printf(sp, "%6lu  ", (u_long)tp->lno);
+
+       /* Print out autoindent string. */
+       if (LF_ISSET(TXT_AUTOINDENT)) {
+               const char *nstr;
+               size_t nlen;
+               INT2CHAR(sp, tp->lb, tp->ai + 1, nstr, nlen);
+               (void)ex_printf(sp, "%.*s", (int)tp->ai, nstr);
+       }
+       (void)ex_fflush(sp);
+}
+
+/*
+ * txt_dent --
+ *     Handle ^D outdents.
+ *
+ * Ex version of vi/v_ntext.c:txt_dent().  See that code for the (usual)
+ * ranting and raving.  This is a fair bit simpler as ^T isn't special.
+ */
+static int
+txt_dent(SCR *sp, TEXT *tp)
+{
+       u_long sw, ts;
+       size_t cno, off, scno, spaces, tabs;
+
+       ts = O_VAL(sp, O_TABSTOP);
+       sw = O_VAL(sp, O_SHIFTWIDTH);
+
+       /* Get the current screen column. */
+       for (off = scno = 0; off < tp->len; ++off)
+               if (tp->lb[off] == '\t')
+                       scno += COL_OFF(scno, ts);
+               else
+                       ++scno;
+
+       /* Get the previous shiftwidth column. */
+       cno = scno--;
+       scno -= scno % sw;
+
+       /*
+        * Since we don't know what comes before the character(s) being
+        * deleted, we have to resolve the autoindent characters .  The
+        * example is a <tab>, which doesn't take up a full shiftwidth
+        * number of columns because it's preceded by <space>s.  This is
+        * easy to get if the user sets shiftwidth to a value less than
+        * tabstop, and then uses ^T to indent, and ^D to outdent.
+        *
+        * Count up spaces/tabs needed to get to the target.
+        */
+       cno = 0;
+       tabs = 0;
+       if (!O_ISSET(sp, O_EXPANDTAB)) {
+               for (; cno + COL_OFF(cno, ts) <= scno; ++tabs)
+                       cno += COL_OFF(cno, ts);
+       }
+       spaces = scno - cno;
+
+       /* Make sure there's enough room. */
+       BINC_RETW(sp, tp->lb, tp->lb_len, tabs + spaces + 1);
+
+       /* Adjust the final ai character count. */
+       tp->ai = tabs + spaces;
+
+       /* Enter the replacement characters. */
+       for (tp->len = 0; tabs > 0; --tabs)
+               tp->lb[tp->len++] = '\t';
+       for (; spaces > 0; --spaces)
+               tp->lb[tp->len++] = ' ';
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_undo.c b/dist/nvi/ex/ex_undo.c
new file mode 100644 (file)
index 0000000..c000b92
--- /dev/null
@@ -0,0 +1,77 @@
+/*     $NetBSD: ex_undo.c,v 1.1.1.2 2008/05/18 14:31:20 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_undo.c,v 10.7 2001/06/25 15:19:21 skimo Exp (Berkeley) Date: 2001/06/25 15:19:21";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_undo -- u
+ *     Undo the last change.
+ *
+ * PUBLIC: int ex_undo __P((SCR *, EXCMD *));
+ */
+int
+ex_undo(SCR *sp, EXCMD *cmdp)
+{
+       EXF *ep;
+       MARK m;
+
+       /*
+        * !!!
+        * Historic undo always set the previous context mark.
+        */
+       m.lno = sp->lno;
+       m.cno = sp->cno;
+       if (mark_set(sp, ABSMARK1, &m, 1))
+               return (1);
+
+       /*
+        * !!!
+        * Multiple undo isn't available in ex, as there's no '.' command.
+        * Whether 'u' is undo or redo is toggled each time, unless there
+        * was a change since the last undo, in which case it's an undo.
+        */
+       ep = sp->ep;
+       if (!F_ISSET(ep, F_UNDO)) {
+               F_SET(ep, F_UNDO);
+               ep->lundo = FORWARD;
+       }
+       switch (ep->lundo) {
+       case BACKWARD:
+               if (log_forward(sp, &m))
+                       return (1);
+               ep->lundo = FORWARD;
+               break;
+       case FORWARD:
+               if (log_backward(sp, &m))
+                       return (1);
+               ep->lundo = BACKWARD;
+               break;
+       case NOTSET:
+               abort();
+       }
+       sp->lno = m.lno;
+       sp->cno = m.cno;
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_usage.c b/dist/nvi/ex/ex_usage.c
new file mode 100644 (file)
index 0000000..020c202
--- /dev/null
@@ -0,0 +1,198 @@
+/*     $NetBSD: ex_usage.c,v 1.6 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_usage.c,v 10.15 2001/06/25 15:19:21 skimo Exp (Berkeley) Date: 2001/06/25 15:19:21";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_help -- :help
+ *     Display help message.
+ *
+ * PUBLIC: int ex_help __P((SCR *, EXCMD *));
+ */
+int
+ex_help(SCR *sp, EXCMD *cmdp)
+{
+       (void)ex_puts(sp,
+           "To see the list of vi commands, enter \":viusage<CR>\"\n");
+       (void)ex_puts(sp,
+           "To see the list of ex commands, enter \":exusage<CR>\"\n");
+       (void)ex_puts(sp,
+           "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
+       (void)ex_puts(sp,
+           "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
+       (void)ex_puts(sp, "To exit, enter \":q!\"\n");
+       return (0);
+}
+
+/*
+ * ex_usage -- :exusage [cmd]
+ *     Display ex usage strings.
+ *
+ * PUBLIC: int ex_usage __P((SCR *, EXCMD *));
+ */
+int
+ex_usage(SCR *sp, EXCMD *cmdp)
+{
+       ARGS *ap;
+       EXCMDLIST const *cp;
+       int newscreen;
+       CHAR_T *p, nb[MAXCMDNAMELEN + 5];
+       const CHAR_T *name;
+
+       switch (cmdp->argc) {
+       case 1:
+               ap = cmdp->argv[0];
+               if (ISUPPER((UCHAR_T)ap->bp[0])) {
+                       newscreen = 1;
+                       ap->bp[0] = TOLOWER((UCHAR_T)ap->bp[0]);
+               } else
+                       newscreen = 0;
+               for (cp = cmds; cp->name != NULL &&
+                   memcmp(ap->bp, cp->name, ap->len); ++cp);
+               if (cp->name == NULL ||
+                   (newscreen && !F_ISSET(cp, E_NEWSCREEN))) {
+                       const char *nstr;
+                       size_t nlen;
+
+                       if (newscreen)
+                               ap->bp[0] = TOUPPER((UCHAR_T)ap->bp[0]);
+
+                       INT2CHAR(sp, ap->bp, ap->len + 1, nstr, nlen);
+                       (void)ex_printf(sp, "The %.*s command is unknown\n",
+                           (int)ap->len, nstr);
+               } else {
+                       (void)ex_printf(sp,
+                           "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
+                       /*
+                        * !!!
+                        * The "visual" command has two modes, one from ex,
+                        * one from the vi colon line.  Don't ask.
+                        */
+                       if (cp != &cmds[C_VISUAL_EX] &&
+                           cp != &cmds[C_VISUAL_VI])
+                               break;
+                       if (cp == &cmds[C_VISUAL_EX])
+                               cp = &cmds[C_VISUAL_VI];
+                       else
+                               cp = &cmds[C_VISUAL_EX];
+                       (void)ex_printf(sp,
+                           "Command: %s\n  Usage: %s\n", cp->help, cp->usage);
+               }
+               break;
+       case 0:
+               for (cp = cmds; cp->name != NULL && !INTERRUPTED(sp); ++cp) {
+                       /*
+                        * The ^D command has an unprintable name.
+                        *
+                        * XXX
+                        * We display both capital and lower-case versions of
+                        * the appropriate commands -- no need to add in extra
+                        * room, they're all short names.
+                        */
+                       if (cp == &cmds[C_SCROLL])
+                               name = L("^D");
+                       else if (F_ISSET(cp, E_NEWSCREEN)) {
+                               nb[0] = L('[');
+                               nb[1] = TOUPPER((UCHAR_T)cp->name[0]);
+                               nb[2] = cp->name[0];
+                               nb[3] = L(']');
+                               for (name = cp->name + 1,
+                                   p = nb + 4; (*p++ = *name++) != '\0';);
+                               name = nb;
+                       } else
+                               name = cp->name;
+                       (void)ex_printf(sp,
+                           WVS": %s\n", MAXCMDNAMELEN, name, cp->help);
+               }
+               break;
+       default:
+               abort();
+       }
+       return (0);
+}
+
+/*
+ * ex_viusage -- :viusage [key]
+ *     Display vi usage strings.
+ *
+ * PUBLIC: int ex_viusage __P((SCR *, EXCMD *));
+ */
+int
+ex_viusage(SCR *sp, EXCMD *cmdp)
+{
+       GS *gp;
+       VIKEYS const *kp;
+       int key;
+
+       gp = sp->gp;
+       switch (cmdp->argc) {
+       case 1:
+               if (cmdp->argv[0]->len != 1) {
+                       ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+                       return (1);
+               }
+               key = cmdp->argv[0]->bp[0];
+               if (key > MAXVIKEY)
+                       goto nokey;
+
+               /* Special case: '[' and ']' commands. */
+               if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
+                       goto nokey;
+
+               /* Special case: ~ command. */
+               if (key == '~' && O_ISSET(sp, O_TILDEOP))
+                       kp = &tmotion;
+               else
+                       kp = &vikeys[key];
+
+               if (kp->usage == NULL)
+nokey:                 (void)ex_printf(sp,
+                           "The %s key has no current meaning\n",
+                           KEY_NAME(sp, key));
+               else
+                       (void)ex_printf(sp,
+                           "  Key:%s%s\nUsage: %s\n",
+                           isblank((unsigned char)*kp->help) ? "" : " ", kp->help, kp->usage);
+               break;
+       case 0:
+               for (key = 0; key <= MAXVIKEY && !INTERRUPTED(sp); ++key) {
+                       /* Special case: ~ command. */
+                       if (key == '~' && O_ISSET(sp, O_TILDEOP))
+                               kp = &tmotion;
+                       else
+                               kp = &vikeys[key];
+                       if (kp->help != NULL)
+                               (void)ex_printf(sp, "%s\n", kp->help);
+               }
+               break;
+       default:
+               abort();
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_util.c b/dist/nvi/ex/ex_util.c
new file mode 100644 (file)
index 0000000..b91e5e3
--- /dev/null
@@ -0,0 +1,222 @@
+/*     $NetBSD: ex_util.c,v 1.3 2009/11/15 18:43:28 dsl Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_util.c,v 10.32 2001/06/25 15:19:21 skimo Exp (Berkeley) Date: 2001/06/25 15:19:21";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_cinit --
+ *     Create an EX command structure.
+ *
+ * PUBLIC: void ex_cinit __P((SCR *, EXCMD *, int, int, db_recno_t, db_recno_t, int));
+ */
+void
+ex_cinit(SCR *sp, EXCMD *cmdp, int cmd_id, int naddr, db_recno_t lno1, db_recno_t lno2, int force)
+{
+       memset(cmdp, 0, sizeof(EXCMD));
+       cmdp->cmd = &cmds[cmd_id];
+       cmdp->addrcnt = naddr;
+       cmdp->addr1.lno = lno1;
+       cmdp->addr2.lno = lno2;
+       cmdp->addr1.cno = cmdp->addr2.cno = 1;
+       if (force)
+               cmdp->iflags |= E_C_FORCE;
+       (void)argv_init(sp, cmdp);
+}
+
+/*
+ * ex_getline --
+ *     Return a line from the file.
+ *
+ * PUBLIC: int ex_getline __P((SCR *, FILE *, size_t *));
+ */
+int
+ex_getline(SCR *sp, FILE *fp, size_t *lenp)
+{
+       EX_PRIVATE *exp;
+       size_t off;
+       int ch;
+       char *p;
+
+       exp = EXP(sp);
+       for (errno = 0, off = 0, p = exp->ibp;;) {
+               if (off >= exp->ibp_len) {
+                       BINC_RETC(sp, exp->ibp, exp->ibp_len, off + 1);
+                       p = exp->ibp + off;
+               }
+               if ((ch = getc(fp)) == EOF && !feof(fp)) {
+                       if (errno == EINTR) {
+                               errno = 0;
+                               clearerr(fp);
+                               continue;
+                       }
+                       return (1);
+               }
+               if (ch == EOF || ch == '\n') {
+                       if (ch == EOF && !off)
+                               return (1);
+                       *lenp = off;
+                       return (0);
+               }
+               *p++ = ch;
+               ++off;
+       }
+       /* NOTREACHED */
+}
+
+/*
+ * ex_ncheck --
+ *     Check for more files to edit.
+ *
+ * PUBLIC: int ex_ncheck __P((SCR *, int));
+ */
+int
+ex_ncheck(SCR *sp, int force)
+{
+       char **ap;
+
+       /*
+        * !!!
+        * Historic practice: quit! or two quit's done in succession
+        * (where ZZ counts as a quit) didn't check for other files.
+        */
+       if (!force && sp->ccnt != sp->q_ccnt + 1 &&
+           sp->cargv != NULL && sp->cargv[1] != NULL) {
+               sp->q_ccnt = sp->ccnt;
+
+               for (ap = sp->cargv + 1; *ap != NULL; ++ap);
+               msgq(sp, M_ERR,
+                   "167|%zd more files to edit", (ap - sp->cargv) - 1);
+
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * ex_init --
+ *     Init the screen for ex.
+ *
+ * PUBLIC: int ex_init __P((SCR *));
+ */
+int
+ex_init(SCR *sp)
+{
+       GS *gp;
+
+       gp = sp->gp;
+
+       if (gp->scr_screen(sp, SC_EX))
+               return (1);
+       (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
+
+       sp->rows = O_VAL(sp, O_LINES);
+       sp->cols = O_VAL(sp, O_COLUMNS);
+
+       F_CLR(sp, SC_VI);
+       F_SET(sp, SC_EX | SC_SCR_EX);
+       return (0);
+}
+
+/*
+ * ex_emsg --
+ *     Display a few common ex and vi error messages.
+ *
+ * PUBLIC: void ex_wemsg __P((SCR *, CHAR_T *, exm_t));
+ */
+void
+ex_wemsg(SCR* sp, const CHAR_T *p, exm_t which)
+{
+       const char *np;
+       size_t nlen;
+
+       if (p) INT2CHAR(sp, p, STRLEN(p), np, nlen);
+       else np = NULL;
+       ex_emsg(sp, np, which);
+}
+
+/*
+ * ex_emsg --
+ *     Display a few common ex and vi error messages.
+ *
+ * PUBLIC: void ex_emsg __P((SCR *, char *, exm_t));
+ */
+void
+ex_emsg(SCR *sp, const char *p, exm_t which)
+{
+       switch (which) {
+       case EXM_EMPTYBUF:
+               msgq(sp, M_ERR, "168|Buffer %s is empty", p);
+               break;
+       case EXM_FILECOUNT:
+                msgq_str(sp, M_ERR, p, 
+                    "144|%s: expanded into too many file names");
+               break;
+       case EXM_LOCKED:
+               msgq(sp, M_ERR,
+                   "Command failed, buffer is locked");
+               break;
+       case EXM_NOCANON:
+               msgq(sp, M_ERR,
+                   "283|The %s command requires the ex terminal interface", p);
+               break;
+       case EXM_NOCANON_F:
+               msgq(sp, M_ERR,
+                   "272|That form of %s requires the ex terminal interface",
+                   p);
+               break;
+       case EXM_NOFILEYET:
+               if (p == NULL)
+                       msgq(sp, M_ERR,
+                           "274|Command failed, no file read in yet.");
+               else
+                       msgq(sp, M_ERR,
+       "173|The %s command requires that a file have already been read in", p);
+               break;
+       case EXM_NOPREVBUF:
+               msgq(sp, M_ERR, "171|No previous buffer to execute");
+               break;
+       case EXM_NOPREVRE:
+               msgq(sp, M_ERR, "172|No previous regular expression");
+               break;
+       case EXM_NOSUSPEND:
+               msgq(sp, M_ERR, "230|This screen may not be suspended");
+               break;
+       case EXM_SECURE:
+               msgq(sp, M_ERR,
+"290|The %s command is not supported when the secure edit option is set", p);
+               break;
+       case EXM_SECURE_F:
+               msgq(sp, M_ERR,
+"284|That form of %s is not supported when the secure edit option is set", p);
+               break;
+       case EXM_USAGE:
+               msgq(sp, M_ERR, "174|Usage: %s", p);
+               break;
+       }
+}
diff --git a/dist/nvi/ex/ex_version.c b/dist/nvi/ex/ex_version.c
new file mode 100644 (file)
index 0000000..9169614
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: ex_version.c,v 1.1.1.2 2008/05/18 14:31:20 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_version.c,v 10.32 2001/06/25 15:19:22 skimo Exp (Berkeley) Date: 2001/06/25 15:19:22";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "version.h"
+
+/*
+ * ex_version -- :version
+ *     Display the program version.
+ *
+ * PUBLIC: int ex_version __P((SCR *, EXCMD *));
+ */
+int
+ex_version(SCR *sp, EXCMD *cmdp)
+{
+       msgq(sp, M_INFO, "Version "VI_VERSION
+                        " The CSRG, University of California, Berkeley.");
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_visual.c b/dist/nvi/ex/ex_visual.c
new file mode 100644 (file)
index 0000000..a403d45
--- /dev/null
@@ -0,0 +1,166 @@
+/*     $NetBSD: ex_visual.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_visual.c,v 10.16 2001/08/29 11:04:13 skimo Exp (Berkeley) Date: 2001/08/29 11:04:13";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_visual -- :[line] vi[sual] [^-.+] [window_size] [flags]
+ *     Switch to visual mode.
+ *
+ * PUBLIC: int ex_visual __P((SCR *, EXCMD *));
+ */
+int
+ex_visual(SCR *sp, EXCMD *cmdp)
+{
+       SCR *tsp;
+       size_t len;
+       int pos;
+       char buf[256];
+       size_t wlen;
+       const CHAR_T *wp;
+
+       /* If open option off, disallow visual command. */
+       if (!O_ISSET(sp, O_OPEN)) {
+               msgq(sp, M_ERR,
+           "175|The visual command requires that the open option be set");
+               return (1);
+       }
+
+       /* Move to the address. */
+       sp->lno = cmdp->addr1.lno == 0 ? 1 : cmdp->addr1.lno;
+
+       /*
+        * Push a command based on the line position flags.  If no
+        * flag specified, the line goes at the top of the screen.
+        */
+       switch (FL_ISSET(cmdp->iflags,
+           E_C_CARAT | E_C_DASH | E_C_DOT | E_C_PLUS)) {
+       case E_C_CARAT:
+               pos = '^';
+               break;
+       case E_C_DASH:
+               pos = '-';
+               break;
+       case E_C_DOT:
+               pos = '.';
+               break;
+       case E_C_PLUS:
+               pos = '+';
+               break;
+       default:
+               sp->frp->lno = sp->lno;
+               sp->frp->cno = 0;
+               (void)nonblank(sp, sp->lno, &sp->cno);
+               F_SET(sp->frp, FR_CURSORSET);
+               goto nopush;
+       }
+
+       if (FL_ISSET(cmdp->iflags, E_C_COUNT))
+               len = snprintf(buf, sizeof(buf),
+                   "%luz%c%lu", (unsigned long)sp->lno, pos, cmdp->count);
+       else
+               len = snprintf(buf, sizeof(buf),
+                   "%luz%c", (unsigned long)sp->lno, pos);
+       CHAR2INT(sp, buf, len, wp, wlen);
+       (void)v_event_push(sp, NULL, wp, wlen, CH_NOMAP | CH_QUOTED);
+
+       /*
+        * !!!
+        * Historically, if no line address was specified, the [p#l] flags
+        * caused the cursor to be moved to the last line of the file, which
+        * was then positioned as described above.  This seems useless, so
+        * I haven't implemented it.
+        */
+       switch (FL_ISSET(cmdp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT)) {
+       case E_C_HASH:
+               O_SET(sp, O_NUMBER);
+               break;
+       case E_C_LIST:
+               O_SET(sp, O_LIST);
+               break;
+       case E_C_PRINT:
+               break;
+       }
+
+nopush:        /*
+        * !!!
+        * You can call the visual part of the editor from within an ex
+        * global command.
+        *
+        * XXX
+        * Historically, undoing a visual session was a single undo command,
+        * i.e. you could undo all of the changes you made in visual mode.
+        * We don't get this right; I'm waiting for the new logging code to
+        * be available.
+        *
+        * It's explicit, don't have to wait for the user, unless there's
+        * already a reason to wait.
+        */
+       if (!F_ISSET(sp, SC_SCR_EXWROTE))
+               F_SET(sp, SC_EX_WAIT_NO);
+
+       if (F_ISSET(sp, SC_EX_GLOBAL)) {
+               /*
+                * When the vi screen(s) exit, we don't want to lose our hold
+                * on this screen or this file, otherwise we're going to fail
+                * fairly spectacularly.
+                */
+               ++sp->refcnt;
+               ++sp->ep->refcnt;
+               /* XXXX where is this decremented ? */
+
+               /*
+                * Fake up a screen pointer -- vi doesn't get to change our
+                * underlying file, regardless.
+                */
+               tsp = sp;
+               if (vi(&tsp))
+                       return (1);
+
+               /*
+                * !!!
+                * Historically, if the user exited the vi screen(s) using an
+                * ex quit command (e.g. :wq, :q) ex/vi exited, it was only if
+                * they exited vi using the Q command that ex continued.  Some
+                * early versions of nvi continued in ex regardless, but users
+                * didn't like the semantic.
+                *
+                * Reset the screen.
+                */
+               if (ex_init(sp))
+                       return (1);
+
+               /* Move out of the vi screen. */
+               (void)ex_puts(sp, "\n");
+       } else {
+               F_CLR(sp, SC_EX | SC_SCR_EX);
+               F_SET(sp, SC_VI);
+       }
+       return (0);
+}
diff --git a/dist/nvi/ex/ex_write.c b/dist/nvi/ex/ex_write.c
new file mode 100644 (file)
index 0000000..53f7eac
--- /dev/null
@@ -0,0 +1,382 @@
+/*     $NetBSD: ex_write.c,v 1.4 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_write.c,v 10.38 2001/06/25 15:19:22 skimo Exp (Berkeley) Date: 2001/06/25 15:19:22";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+enum which {WN, WQ, WRITE, XIT};
+static int exwr __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_wn --    :wn[!] [>>] [file]
+ *     Write to a file and switch to the next one.
+ *
+ * PUBLIC: int ex_wn __P((SCR *, EXCMD *));
+ */
+int
+ex_wn(SCR *sp, EXCMD *cmdp)
+{
+       if (exwr(sp, cmdp, WN))
+               return (1);
+       if (file_m3(sp, 0))
+               return (1);
+
+       /* The file name isn't a new file to edit. */
+       cmdp->argc = 0;
+
+       return (ex_next(sp, cmdp));
+}
+
+/*
+ * ex_wq --    :wq[!] [>>] [file]
+ *     Write to a file and quit.
+ *
+ * PUBLIC: int ex_wq __P((SCR *, EXCMD *));
+ */
+int
+ex_wq(SCR *sp, EXCMD *cmdp)
+{
+       int force;
+
+       if (exwr(sp, cmdp, WQ))
+               return (1);
+       if (file_m3(sp, 0))
+               return (1);
+
+       force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+
+       if (ex_ncheck(sp, force))
+               return (1);
+
+       F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
+       return (0);
+}
+
+/*
+ * ex_write -- :write[!] [>>] [file]
+ *             :write [!] [cmd]
+ *     Write to a file.
+ *
+ * PUBLIC: int ex_write __P((SCR *, EXCMD *));
+ */
+int
+ex_write(SCR *sp, EXCMD *cmdp)
+{
+       return (exwr(sp, cmdp, WRITE));
+}
+
+
+/*
+ * ex_xit -- :x[it]! [file]
+ *     Write out any modifications and quit.
+ *
+ * PUBLIC: int ex_xit __P((SCR *, EXCMD *));
+ */
+int
+ex_xit(SCR *sp, EXCMD *cmdp)
+{
+       int force;
+
+       NEEDFILE(sp, cmdp);
+
+       if (F_ISSET(sp->ep, F_MODIFIED) && exwr(sp, cmdp, XIT))
+               return (1);
+       if (file_m3(sp, 0))
+               return (1);
+
+       force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+
+       if (ex_ncheck(sp, force))
+               return (1);
+
+       F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
+       return (0);
+}
+
+/*
+ * exwr --
+ *     The guts of the ex write commands.
+ */
+static int
+exwr(SCR *sp, EXCMD *cmdp, enum which cmd)
+{
+       MARK rm;
+       int flags;
+       char *name;
+       CHAR_T *p = NULL;
+       size_t nlen;
+       const char *n;
+       int rc;
+       EX_PRIVATE *exp;
+
+       NEEDFILE(sp, cmdp);
+
+       /* All write commands can have an associated '!'. */
+       LF_INIT(FS_POSSIBLE);
+       if (FL_ISSET(cmdp->iflags, E_C_FORCE))
+               LF_SET(FS_FORCE);
+
+       /* Skip any leading whitespace. */
+       if (cmdp->argc != 0)
+               for (p = cmdp->argv[0]->bp; *p != '\0' && ISBLANK((UCHAR_T)*p); ++p);
+
+       /* If "write !" it's a pipe to a utility. */
+       if (cmdp->argc != 0 && cmd == WRITE && *p == '!') {
+               /* Secure means no shell access. */
+               if (O_ISSET(sp, O_SECURE)) {
+                       ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
+                       return (1);
+               }
+
+               /* Expand the argument. */
+               for (++p; *p && ISBLANK((UCHAR_T)*p); ++p);
+               if (*p == '\0') {
+                       ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+                       return (1);
+               }
+               if (argv_exp1(sp, cmdp, p, STRLEN(p), 1))
+                       return (1);
+
+               /* Set the last bang command */
+               exp = EXP(sp);
+               free(exp->lastbcomm);
+               exp->lastbcomm = v_wstrdup(sp, cmdp->argv[1]->bp,
+                   cmdp->argv[1]->len);
+
+               /*
+                * Historically, vi waited after a write filter even if there
+                * wasn't any output from the command.  People complained when
+                * nvi waited only if there was output, wanting the visual cue
+                * that the program hadn't written anything.
+                */
+               F_SET(sp, SC_EX_WAIT_YES);
+
+               /*
+                * !!!
+                * Ignore the return cursor position, the cursor doesn't
+                * move.
+                */
+               if (ex_filter(sp, cmdp, &cmdp->addr1,
+                   &cmdp->addr2, &rm, cmdp->argv[1]->bp, FILTER_WRITE))
+                       return (1);
+
+               /* Ex terminates with a bang, even if the command fails. */
+               if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
+                       (void)ex_puts(sp, "!\n");
+
+               return (0);
+       }
+
+       /* Set the FS_ALL flag if we're writing the entire file. */
+       if (cmdp->addr1.lno <= 1 && !db_exist(sp, cmdp->addr2.lno + 1))
+               LF_SET(FS_ALL);
+
+       /* If "write >>" it's an append to a file. */
+       if (cmdp->argc != 0 && cmd != XIT && p[0] == '>' && p[1] == '>') {
+               LF_SET(FS_APPEND);
+
+               /* Skip ">>" and whitespace. */
+               for (p += 2; *p && ISBLANK((UCHAR_T)*p); ++p);
+       }
+
+       /* If no other arguments, just write the file back. */
+       if (cmdp->argc == 0 || *p == '\0')
+               return (file_write(sp,
+                   &cmdp->addr1, &cmdp->addr2, NULL, flags));
+
+       /* Build an argv so we get an argument count and file expansion. */
+       if (argv_exp2(sp, cmdp, p, STRLEN(p)))
+               return (1);
+
+       /*
+        *  0 args: impossible.
+        *  1 args: impossible (I hope).
+        *  2 args: read it.
+        * >2 args: object, too many args.
+        *
+        * The 1 args case depends on the argv_sexp() function refusing
+        * to return success without at least one non-blank character.
+        */
+       switch (cmdp->argc) {
+       case 0:
+       case 1:
+               abort();
+               /* NOTREACHED */
+       case 2:
+               INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len+1,
+                        n, nlen);
+               name = v_strdup(sp, n, nlen - 1);
+
+               /*
+                * !!!
+                * Historically, the read and write commands renamed
+                * "unnamed" files, or, if the file had a name, set
+                * the alternate file name.
+                */
+               if (F_ISSET(sp->frp, FR_TMPFILE) &&
+                   !F_ISSET(sp->frp, FR_EXNAMED)) {
+                       char *q;
+                       if ((q = v_strdup(sp, name, nlen - 1)) != NULL) {
+                               free(sp->frp->name);
+                               sp->frp->name = q;
+                       }
+                       /*
+                        * The file has a real name, it's no longer a
+                        * temporary, clear the temporary file flags.
+                        *
+                        * !!!
+                        * If we're writing the whole file, FR_NAMECHANGE
+                        * will be cleared by the write routine -- this is
+                        * historic practice.
+                        */
+                       F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
+                       F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
+
+                       /* Notify the screen. */
+                       (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+               } else
+                       set_alt_name(sp, name);
+               break;
+       default:
+               INT2CHAR(sp, p, STRLEN(p) + 1, n, nlen);
+               ex_emsg(sp, n, EXM_FILECOUNT);
+               return (1);
+       }
+
+       rc = file_write(sp, &cmdp->addr1, &cmdp->addr2, name, flags);
+
+       free(name);
+
+       return rc;
+}
+
+/*
+ * ex_writefp --
+ *     Write a range of lines to a FILE *.
+ *
+ * PUBLIC: int ex_writefp __P((SCR *,
+ * PUBLIC:    const char *, FILE *, MARK *, MARK *, u_long *, u_long *, int));
+ */
+int
+ex_writefp(SCR *sp, const char *name, FILE *fp, MARK *fm, MARK *tm, u_long *nlno, u_long *nch, int silent)
+{
+       struct stat sb;
+       GS *gp;
+       u_long ccnt;                    /* XXX: can't print off_t portably. */
+       db_recno_t fline, tline, lcnt;
+       size_t len;
+       int rval;
+       const char *msg;
+       CHAR_T *p;
+       const char *f;
+       size_t flen;
+
+       gp = sp->gp;
+       fline = fm->lno;
+       tline = tm->lno;
+
+       if (nlno != NULL) {
+               *nch = 0;
+               *nlno = 0;
+       }
+
+       /*
+        * The vi filter code has multiple processes running simultaneously,
+        * and one of them calls ex_writefp().  The "unsafe" function calls
+        * in this code are to db_get() and msgq().  Db_get() is safe, see
+        * the comment in ex_filter.c:ex_filter() for details.  We don't call
+        * msgq if the multiple process bit in the EXF is set.
+        *
+        * !!!
+        * Historic vi permitted files of 0 length to be written.  However,
+        * since the way vi got around dealing with "empty" files was to
+        * always have a line in the file no matter what, it wrote them as
+        * files of a single, empty line.  We write empty files.
+        *
+        * "Alex, I'll take vi trivia for $1000."
+        */
+       ccnt = 0;
+       lcnt = 0;
+       msg = "253|Writing...";
+       if (tline != 0)
+               for (; fline <= tline; ++fline, ++lcnt) {
+                       /* Caller has to provide any interrupt message. */
+                       if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
+                               if (INTERRUPTED(sp))
+                                       break;
+                               if (!silent) {
+                                       gp->scr_busy(sp, msg, msg == NULL ?
+                                           BUSY_UPDATE : BUSY_ON);
+                                       msg = NULL;
+                               }
+                       }
+                       if (db_get(sp, fline, DBG_FATAL, &p, &len))
+                               goto err;
+                       INT2FILE(sp, p, len, f, flen);
+                       if (fwrite(f, 1, flen, fp) != flen)
+                               goto err;
+                       ccnt += len;
+                       if (putc('\n', fp) != '\n')
+                               break;
+                       ++ccnt;
+               }
+
+       if (fflush(fp))
+               goto err;
+       /*
+        * XXX
+        * I don't trust NFS -- check to make sure that we're talking to
+        * a regular file and sync so that NFS is forced to flush.
+        */
+       if (!fstat(fileno(fp), &sb) &&
+           S_ISREG(sb.st_mode) && fsync(fileno(fp)))
+               goto err;
+
+       if (fclose(fp))
+               goto err;
+
+       rval = 0;
+       if (0) {
+err:           if (!F_ISSET(sp->ep, F_MULTILOCK))
+                       msgq_str(sp, M_SYSERR, name, "%s");
+               (void)fclose(fp);
+               rval = 1;
+       }
+
+       if (!silent)
+               gp->scr_busy(sp, NULL, BUSY_OFF);
+
+       /* Report the possibly partial transfer. */
+       if (nlno != NULL) {
+               *nch = ccnt;
+               *nlno = lcnt;
+       }
+       return (rval);
+}
diff --git a/dist/nvi/ex/ex_yank.c b/dist/nvi/ex/ex_yank.c
new file mode 100644 (file)
index 0000000..d172b49
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: ex_yank.c,v 1.1.1.2 2008/05/18 14:31:21 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_yank.c,v 10.8 2001/06/25 15:19:22 skimo Exp (Berkeley) Date: 2001/06/25 15:19:22";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_yank -- :[line [,line]] ya[nk] [buffer] [count]
+ *     Yank the lines into a buffer.
+ *
+ * PUBLIC: int ex_yank __P((SCR *, EXCMD *));
+ */
+int
+ex_yank(SCR *sp, EXCMD *cmdp)
+{
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * !!!
+        * Historically, yanking lines in ex didn't count toward the
+        * number-of-lines-yanked report.
+        */
+       return (cut(sp,
+           FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
+           &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE));
+}
diff --git a/dist/nvi/ex/ex_z.c b/dist/nvi/ex/ex_z.c
new file mode 100644 (file)
index 0000000..b433186
--- /dev/null
@@ -0,0 +1,150 @@
+/*     $NetBSD: ex_z.c,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ex_z.c,v 10.12 2001/06/25 15:19:22 skimo Exp (Berkeley) Date: 2001/06/25 15:19:22";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_z -- :[line] z [^-.+=] [count] [flags]
+ *     Adjust window.
+ *
+ * PUBLIC: int ex_z __P((SCR *, EXCMD *));
+ */
+int
+ex_z(SCR *sp, EXCMD *cmdp)
+{
+       MARK abm;
+       db_recno_t cnt, equals, lno;
+       int eofcheck;
+
+       NEEDFILE(sp, cmdp);
+
+       /*
+        * !!!
+        * If no count specified, use either two times the size of the
+        * scrolling region, or the size of the window option.  POSIX
+        * 1003.2 claims that the latter is correct, but historic ex/vi
+        * documentation and practice appear to use the scrolling region.
+        * I'm using the window size as it means that the entire screen
+        * is used instead of losing a line to roundoff.  Note, we drop
+        * a line from the cnt if using the window size to leave room for
+        * the next ex prompt.
+        */
+       if (FL_ISSET(cmdp->iflags, E_C_COUNT))
+               cnt = cmdp->count;
+       else
+#ifdef HISTORIC_PRACTICE
+               cnt = O_VAL(sp, O_SCROLL) * 2;
+#else
+               cnt = O_VAL(sp, O_WINDOW) - 1;
+#endif
+
+       equals = 0;
+       eofcheck = 0;
+       lno = cmdp->addr1.lno;
+
+       switch (FL_ISSET(cmdp->iflags,
+           E_C_CARAT | E_C_DASH | E_C_DOT | E_C_EQUAL | E_C_PLUS)) {
+       case E_C_CARAT:         /* Display cnt * 2 before the line. */
+               eofcheck = 1;
+               if (lno > cnt * 2)
+                       cmdp->addr1.lno = (lno - cnt * 2) + 1;
+               else
+                       cmdp->addr1.lno = 1;
+               cmdp->addr2.lno = (cmdp->addr1.lno + cnt) - 1;
+               break;
+       case E_C_DASH:          /* Line goes at the bottom of the screen. */
+               cmdp->addr1.lno = lno > cnt ? (lno - cnt) + 1 : 1;
+               cmdp->addr2.lno = lno;
+               break;
+       case E_C_DOT:           /* Line goes in the middle of the screen. */
+               /*
+                * !!!
+                * Historically, the "middleness" of the line overrode the
+                * count, so that "3z.19" or "3z.20" would display the first
+                * 12 lines of the file, i.e. (N - 1) / 2 lines before and
+                * after the specified line.
+                */
+               eofcheck = 1;
+               cnt = (cnt - 1) / 2;
+               cmdp->addr1.lno = lno > cnt ? lno - cnt : 1;
+               cmdp->addr2.lno = lno + cnt;
+
+               /*
+                * !!!
+                * Historically, z. set the absolute cursor mark.
+                */
+               abm.lno = sp->lno;
+               abm.cno = sp->cno;
+               (void)mark_set(sp, ABSMARK1, &abm, 1);
+               break;
+       case E_C_EQUAL:         /* Center with hyphens. */
+               /*
+                * !!!
+                * Strangeness.  The '=' flag is like the '.' flag (see the
+                * above comment, it applies here as well) but with a special
+                * little hack.  Print out lines of hyphens before and after
+                * the specified line.  Additionally, the cursor remains set
+                * on that line.
+                */
+               eofcheck = 1;
+               cnt = (cnt - 1) / 2;
+               cmdp->addr1.lno = lno > cnt ? lno - cnt : 1;
+               cmdp->addr2.lno = lno - 1;
+               if (ex_pr(sp, cmdp))
+                       return (1);
+               (void)ex_puts(sp, "----------------------------------------\n");
+               cmdp->addr2.lno = cmdp->addr1.lno = equals = lno;
+               if (ex_pr(sp, cmdp))
+                       return (1);
+               (void)ex_puts(sp, "----------------------------------------\n");
+               cmdp->addr1.lno = lno + 1;
+               cmdp->addr2.lno = (lno + cnt) - 1;
+               break;
+       default:
+               /* If no line specified, move to the next one. */
+               if (F_ISSET(cmdp, E_ADDR_DEF))
+                       ++lno;
+               /* FALLTHROUGH */
+       case E_C_PLUS:          /* Line goes at the top of the screen. */
+               eofcheck = 1;
+               cmdp->addr1.lno = lno;
+               cmdp->addr2.lno = (lno + cnt) - 1;
+               break;
+       }
+
+       if (eofcheck) {
+               if (db_last(sp, &lno))
+                       return (1);
+               if (cmdp->addr2.lno > lno)
+                       cmdp->addr2.lno = lno;
+       }
+
+       if (ex_pr(sp, cmdp))
+               return (1);
+       if (equals)
+               sp->lno = equals;
+       return (0);
+}
diff --git a/dist/nvi/ex/extern.h b/dist/nvi/ex/extern.h
new file mode 100644 (file)
index 0000000..4703ec7
--- /dev/null
@@ -0,0 +1,133 @@
+/*     $NetBSD: extern.h,v 1.4 2009/11/14 23:40:11 christos Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int ex __P((SCR **));
+int ex_cmd __P((SCR *));
+int ex_range __P((SCR *, EXCMD *, int *));
+int ex_is_abbrev __P((SCR *, CHAR_T *, size_t));
+int ex_is_unmap __P((SCR *, CHAR_T *, size_t));
+void ex_badaddr
+   __P((SCR *, EXCMDLIST const *, enum badaddr, enum nresult));
+int ex_abbr __P((SCR *, EXCMD *));
+int ex_unabbr __P((SCR *, EXCMD *));
+int ex_append __P((SCR *, EXCMD *));
+int ex_change __P((SCR *, EXCMD *));
+int ex_insert __P((SCR *, EXCMD *));
+int ex_next __P((SCR *, EXCMD *));
+int ex_prev __P((SCR *, EXCMD *));
+int ex_rew __P((SCR *, EXCMD *));
+int ex_args __P((SCR *, EXCMD *));
+char **ex_buildargv __P((SCR *, EXCMD *, char *));
+int argv_init __P((SCR *, EXCMD *));
+int argv_exp0 __P((SCR *, EXCMD *, const CHAR_T *, size_t));
+int argv_exp1 __P((SCR *, EXCMD *, const CHAR_T *, size_t, int));
+int argv_exp2 __P((SCR *, EXCMD *, const CHAR_T *, size_t));
+int argv_exp3 __P((SCR *, EXCMD *, const CHAR_T *, size_t));
+int argv_free __P((SCR *));
+int ex_at __P((SCR *, EXCMD *));
+int ex_bang __P((SCR *, EXCMD *));
+int ex_cd __P((SCR *, EXCMD *));
+int ex_cscope __P((SCR *, EXCMD *));
+int cscope_display __P((SCR *));
+int cscope_search __P((SCR *, TAGQ *, TAG *));
+int ex_delete __P((SCR *, EXCMD *));
+int ex_display __P((SCR *, EXCMD *));
+int ex_edit __P((SCR *, EXCMD *));
+int ex_equal __P((SCR *, EXCMD *));
+int ex_file __P((SCR *, EXCMD *));
+int ex_filter __P((SCR *, 
+   EXCMD *, MARK *, MARK *, MARK *, CHAR_T *, enum filtertype));
+int ex_global __P((SCR *, EXCMD *));
+int ex_v __P((SCR *, EXCMD *));
+int ex_g_insdel __P((SCR *, lnop_t, db_recno_t));
+int ex_screen_copy __P((SCR *, SCR *));
+int ex_screen_end __P((SCR *));
+int ex_optchange __P((SCR *, int, const char *, u_long *));
+int ex_exrc __P((SCR *));
+int ex_run_str __P((SCR *, const char *, const CHAR_T *, size_t, int, int));
+int ex_join __P((SCR *, EXCMD *));
+int ex_map __P((SCR *, EXCMD *));
+int ex_unmap __P((SCR *, EXCMD *));
+int ex_mark __P((SCR *, EXCMD *));
+int ex_mkexrc __P((SCR *, EXCMD *));
+int ex_copy __P((SCR *, EXCMD *));
+int ex_move __P((SCR *, EXCMD *));
+int ex_open __P((SCR *, EXCMD *));
+int ex_perl __P((SCR*, EXCMD *));
+int ex_preserve __P((SCR *, EXCMD *));
+int ex_recover __P((SCR *, EXCMD *));
+int ex_list __P((SCR *, EXCMD *));
+int ex_number __P((SCR *, EXCMD *));
+int ex_pr __P((SCR *, EXCMD *));
+int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
+int ex_ldisplay __P((SCR *, const CHAR_T *, size_t, size_t, u_int));
+int ex_scprint __P((SCR *, MARK *, MARK *));
+int ex_printf __P((SCR *, const char *, ...))
+    __attribute__((__format__(__printf__, 2, 3)));
+int ex_puts __P((SCR *, const char *));
+int ex_fflush __P((SCR *sp));
+int ex_put __P((SCR *, EXCMD *));
+int ex_quit __P((SCR *, EXCMD *));
+int ex_read __P((SCR *, EXCMD *));
+int ex_readfp __P((SCR *, const char *, FILE *, MARK *, db_recno_t *, int));
+int ex_bg __P((SCR *, EXCMD *));
+int ex_fg __P((SCR *, EXCMD *));
+int ex_resize __P((SCR *, EXCMD *));
+int ex_sdisplay __P((SCR *));
+int ex_script __P((SCR *, EXCMD *));
+int sscr_exec __P((SCR *, db_recno_t));
+int sscr_check_input __P((SCR *sp, fd_set *rdfd, int maxfd));
+int sscr_input __P((SCR *));
+int sscr_end __P((SCR *));
+int ex_set __P((SCR *, EXCMD *));
+int ex_shell __P((SCR *, EXCMD *));
+int ex_exec_proc __P((SCR *, EXCMD *, const char *, const char *, int));
+int proc_wait __P((SCR *, long, const char *, int, int));
+int ex_shiftl __P((SCR *, EXCMD *));
+int ex_shiftr __P((SCR *, EXCMD *));
+int ex_source __P((SCR *, EXCMD *));
+int ex_stop __P((SCR *, EXCMD *));
+int ex_s __P((SCR *, EXCMD *));
+int ex_subagain __P((SCR *, EXCMD *));
+int ex_subtilde __P((SCR *, EXCMD *));
+int re_compile __P((SCR *,
+    CHAR_T *, size_t, CHAR_T **, size_t *, regex_t *, u_int));
+void re_error __P((SCR *, int, regex_t *));
+int ex_tag_first __P((SCR *, const CHAR_T *));
+int ex_rtag_push __P((SCR *, EXCMD *));
+int ex_tag_push __P((SCR *, EXCMD *));
+int ex_tag_next __P((SCR *, EXCMD *));
+int ex_tag_prev __P((SCR *, EXCMD *));
+int ex_tag_nswitch __P((SCR *, TAG *, int));
+int ex_tag_Nswitch __P((SCR *, TAG *, int));
+int ex_tag_pop __P((SCR *, EXCMD *));
+int ex_tag_top __P((SCR *, EXCMD *));
+int ex_tag_display __P((SCR *));
+int ex_tag_copy __P((SCR *, SCR *));
+int tagq_free __P((SCR *, TAGQ *));
+int tagq_push __P((SCR*, TAGQ*, int, int ));
+void tag_msg __P((SCR *, tagmsg_t, char *));
+int ex_tagf_alloc __P((SCR *, const char *));
+int ex_tag_free __P((SCR *));
+int ex_tcl __P((SCR*, EXCMD *));
+int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t));
+int ex_undo __P((SCR *, EXCMD *));
+int ex_help __P((SCR *, EXCMD *));
+int ex_usage __P((SCR *, EXCMD *));
+int ex_viusage __P((SCR *, EXCMD *));
+void ex_cinit __P((SCR *, EXCMD *, int, int, db_recno_t, db_recno_t, int));
+int ex_getline __P((SCR *, FILE *, size_t *));
+int ex_ncheck __P((SCR *, int));
+int ex_init __P((SCR *));
+void ex_wemsg __P((SCR *, const CHAR_T *, exm_t));
+void ex_emsg __P((SCR *, const char *, exm_t));
+int ex_version __P((SCR *, EXCMD *));
+int ex_visual __P((SCR *, EXCMD *));
+int ex_wn __P((SCR *, EXCMD *));
+int ex_wq __P((SCR *, EXCMD *));
+int ex_write __P((SCR *, EXCMD *));
+int ex_xit __P((SCR *, EXCMD *));
+int ex_writefp __P((SCR *,
+   const char *, FILE *, MARK *, MARK *, u_long *, u_long *, int));
+int ex_yank __P((SCR *, EXCMD *));
+int ex_z __P((SCR *, EXCMD *));
diff --git a/dist/nvi/ex/script.h b/dist/nvi/ex/script.h
new file mode 100644 (file)
index 0000000..66a12f8
--- /dev/null
@@ -0,0 +1,25 @@
+/*     $NetBSD: script.h,v 1.1.1.2 2008/05/18 14:31:21 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: script.h,v 10.2 1996/03/06 19:53:00 bostic Exp (Berkeley) Date: 1996/03/06 19:53:00
+ */
+
+struct _script {
+       pid_t    sh_pid;                /* Shell pid. */
+       int      sh_master;             /* Master pty fd. */
+       int      sh_slave;              /* Slave pty fd. */
+       char    *sh_prompt;             /* Prompt. */
+       size_t   sh_prompt_len;         /* Prompt length. */
+       char     sh_name[64];           /* Pty name */
+#ifdef TIOCGWINSZ
+       struct winsize sh_win;          /* Window size. */
+#endif
+       struct termios sh_term;         /* Terminal information. */
+};
diff --git a/dist/nvi/ex/tag.h b/dist/nvi/ex/tag.h
new file mode 100644 (file)
index 0000000..fa61185
--- /dev/null
@@ -0,0 +1,111 @@
+/*     $NetBSD: tag.h,v 1.1.1.2 2008/05/18 14:31:21 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1994, 1996
+ *     Rob Mayoff.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: tag.h,v 10.8 2000/07/14 14:29:22 skimo Exp (Berkeley) Date: 2000/07/14 14:29:22
+ */
+
+/*
+ * Cscope connection information.  One of these is maintained per cscope
+ * connection, linked from the EX_PRIVATE structure.
+ */
+struct _csc {
+       LIST_ENTRY(_csc) q;     /* Linked list of cscope connections. */
+
+       char    *dname;         /* Base directory of this cscope connection. */
+       size_t   dlen;          /* Length of base directory. */
+       pid_t    pid;           /* PID of the connected cscope process. */
+       time_t   mtime;         /* Last modification time of cscope database. */
+
+       FILE    *from_fp;       /* from cscope: FILE. */
+       int      from_fd;       /* from cscope: file descriptor. */
+       FILE    *to_fp;         /* to cscope: FILE. */
+       int      to_fd;         /* to cscope: file descriptor. */
+
+       char   **paths;         /* Array of search paths for this cscope. */
+       char    *pbuf;          /* Search path buffer. */
+       size_t   pblen;         /* Search path buffer length. */
+
+       char     buf[1];        /* Variable length buffer. */
+};
+
+/*
+ * Tag file information.  One of these is maintained per tag file, linked
+ * from the EXPRIVATE structure.
+ */
+struct _tagf {                 /* Tag files. */
+       TAILQ_ENTRY(_tagf) q;   /* Linked list of tag files. */
+       char    *name;          /* Tag file name. */
+       int      errnum;        /* Errno. */
+
+#define        TAGF_ERR        0x01    /* Error occurred. */
+#define        TAGF_ERR_WARN   0x02    /* Error reported. */
+       u_int8_t flags;
+};
+
+/*
+ * Tags are structured internally as follows:
+ *
+ * +----+    +----+    +----+     +----+
+ * | EP | -> | Q1 | <-- | T1 | <-- | T2 |
+ * +----+    +----+ --> +----+ --> +----+
+ *          |
+ *          +----+     +----+
+ *          | Q2 | <-- | T1 |
+ *          +----+ --> +----+
+ *          |
+ *          +----+     +----+
+ *          | Q3 | <-- | T1 |
+ *          +----+ --> +----+
+ *
+ * Each Q is a TAGQ, or tag "query", which is the result of one tag or cscope
+ * command.  Each Q references one or more TAG's, or tagged file locations.
+ *
+ * tag:                put a new Q at the head (^])
+ * tagnext:    T1 -> T2 inside Q       (^N)
+ * tagprev:    T2 -> T1 inside Q       (^P)
+ * tagpop:     discard Q               (^T)
+ * tagtop:     discard all Q
+ */
+struct _tag {                  /* Tag list. */
+       CIRCLEQ_ENTRY(_tag) q;  /* Linked list of tags. */
+
+                               /* Tag pop/return information. */
+       FREF    *frp;           /* Saved file. */
+       db_recno_t       lno;           /* Saved line number. */
+       size_t   cno;           /* Saved column number. */
+
+       char    *fname;         /* Filename. */
+       size_t   fnlen;         /* Filename length. */
+       db_recno_t       slno;          /* Search line number. */
+       CHAR_T  *search;        /* Search string. */
+       size_t   slen;          /* Search string length. */
+       CHAR_T  *msg;           /* Message string. */
+       size_t   mlen;          /* Message string length. */
+
+       CHAR_T   buf[1];        /* Variable length buffer. */
+};
+
+struct _tagq {                 /* Tag queue. */
+       CIRCLEQ_ENTRY(_tagq) q; /* Linked list of tag queues. */
+                               /* This queue's tag list. */
+       CIRCLEQ_HEAD(_tagqh, _tag) tagq;
+
+       TAG     *current;       /* Current TAG within the queue. */
+
+       char    *tag;           /* Tag string. */
+       size_t   tlen;          /* Tag string length. */
+
+#define        TAG_CSCOPE      0x01    /* Cscope tag. */
+       u_int8_t flags;
+
+       char     buf[1];        /* Variable length buffer. */
+};
diff --git a/dist/nvi/ex/version.h b/dist/nvi/ex/version.h
new file mode 100644 (file)
index 0000000..5d3939e
--- /dev/null
@@ -0,0 +1,3 @@
+/*     $NetBSD: version.h,v 1.4 2009/08/11 21:42:03 aymeric Exp $ */
+
+#define VI_VERSION "nvi-1.81.6nb5 (2009-08-11)"
diff --git a/dist/nvi/gtk/extern.h b/dist/nvi/gtk/extern.h
new file mode 100644 (file)
index 0000000..2a07438
--- /dev/null
@@ -0,0 +1,7 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:22 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int gtk_vi_init __P((GtkVi **, int, char*[]));
+void gtk_vi_quit __P((GtkViWindow*, gint));
+void gtk_vi_show_term __P((GtkViWindow*, gint));
+void gtk_vi_key_press_event __P((GtkViWindow*, GdkEventKey*));
diff --git a/dist/nvi/gtk/gtk.h b/dist/nvi/gtk/gtk.h
new file mode 100644 (file)
index 0000000..12cf32d
--- /dev/null
@@ -0,0 +1,10 @@
+/*     $NetBSD: gtk.h,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+typedef struct {
+    GtkViScreen  *vi;
+    GtkWidget  *main;
+    gint    input_func;
+    gint    value_changed;
+    IPVI    *ipvi;
+    int            resized;
+} gtk_vi;
diff --git a/dist/nvi/gtk/gtk_main.c b/dist/nvi/gtk/gtk_main.c
new file mode 100644 (file)
index 0000000..1407c55
--- /dev/null
@@ -0,0 +1,137 @@
+/*     $NetBSD: gtk_main.c,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1999
+ *     Sven Verdoolaege.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <bitstring.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ipc/ip.h"
+
+#include <gtk/gtk.h>
+#include "gtkvi.h"
+#include "gtkviwindow.h"
+#include "gtkviscreen.h"
+#include "../gtk/extern.h"
+
+static void vi_destroyed __P((GtkWidget*,GtkWidget*));
+static void vi_rename __P((GtkWidget*,gchar*,GtkWidget*));
+static void vi_quit __P((GtkViWindow*, int));
+
+static void win_toplevel(GtkViWindow *win);
+static void create_toplevel(GtkVi *vi);
+
+static GtkItemFactoryEntry menu_items[] = {
+    { "/_File",                NULL,       NULL,           0,  "<Branch>" },
+    { "/File/E_xit",   NULL,       vi_quit,        1,  NULL },
+    { "/File/_Quit",   NULL,       vi_quit,        0,  NULL },
+    { "/_Window",      NULL,       NULL,           0,  "<Branch>" },
+    { "/Window/New Window",    NULL,    win_toplevel,  0, NULL },
+#if 0 /*wrong argument anyway*/
+    { "/Window/Show Terminal", NULL,    gtk_vi_show_term,    1,  NULL },
+    { "/Window/Show Vi",       NULL,    gtk_vi_show_term,    0,  NULL },
+#endif
+};
+
+static int n_toplevel = 0;
+
+int
+main(int argc, char **argv)
+{
+       GtkVi   *vi;
+
+       gtk_set_locale ();
+
+       gtk_init (&argc, &argv);
+
+       gtk_vi_init(&vi, argc, argv);
+
+       create_toplevel(vi);
+
+       gtk_main();
+
+       return 0;
+}
+
+static
+void win_toplevel(GtkViWindow *win)
+{
+    create_toplevel(win->vi);
+}
+
+static 
+void create_toplevel(GtkVi *vi)
+{
+       GtkWidget *window;
+       GtkWidget *box, *menubar;
+       GtkWidget *vi_window;
+       gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
+       GtkItemFactory *factory;
+       GtkAccelGroup *accel;
+
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       ++n_toplevel;
+
+       box = gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(window), box);
+       gtk_widget_show(box);
+
+       vi_window = gtk_vi_window_new(vi);
+
+       accel = gtk_accel_group_new();
+       factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel);
+       gtk_item_factory_create_items (factory, nmenu_items, menu_items, (gpointer)vi_window);
+       gtk_accel_group_attach(accel, GTK_OBJECT(window));
+       menubar = gtk_item_factory_get_widget (factory, "<main>");
+       gtk_widget_show(menubar);
+       gtk_box_pack_start(GTK_BOX(box), menubar, FALSE, FALSE, 0);
+
+       gtk_accel_group_attach(accel, GTK_OBJECT(vi_window));
+       gtk_widget_show(vi_window);
+
+       gtk_signal_connect(GTK_OBJECT(vi_window), "rename",
+                          GTK_SIGNAL_FUNC(vi_rename),
+                          window);
+       gtk_signal_connect(GTK_OBJECT(GTK_VI_WINDOW(vi_window)->vi_screen), "destroy",
+                          GTK_SIGNAL_FUNC(vi_destroyed),
+                          window);
+       gtk_box_pack_start(GTK_BOX(box), vi_window, TRUE, TRUE, 0);
+
+       /*
+       gtk_widget_grab_focus(GTK_WIDGET(vi->vi));
+       */
+
+       gtk_widget_show(window);
+}
+
+static void
+vi_quit(GtkViWindow *vi, gint write)
+{
+       gtk_vi_quit(vi, write);
+}
+
+static void
+vi_destroyed(GtkWidget *vi, GtkWidget *window)
+{
+       gtk_widget_destroy(window);
+       if (!--n_toplevel)
+               gtk_main_quit();
+}
+
+static void
+vi_rename(GtkWidget *vi, gchar *name, GtkWidget *window)
+{
+       gtk_window_set_title(GTK_WINDOW(window), name);
+}
diff --git a/dist/nvi/gtk/gtkvi.c b/dist/nvi/gtk/gtkvi.c
new file mode 100644 (file)
index 0000000..83b28c6
--- /dev/null
@@ -0,0 +1,106 @@
+/*     $NetBSD: gtkvi.c,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1999
+ *     Sven Verdoolaege.  All rights reserved.
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "../common/common.h"
+#include "../ipc/ip.h"
+
+#if 0
+#include <zvt/zvtterm.h>
+#include <zvt/vt.h>
+#endif
+#include "gtkvi.h"
+#include "gtkviscreen.h"
+#include "gtkviwindow.h"
+#include "extern.h"
+
+static int vi_key_press_event __P((GtkWidget*, GdkEventKey*, GtkVi*));
+
+
+
+#if 0
+static int
+vi_fork(ipvi)
+       IPVI    *ipvi;
+{
+       GtkVi* vi = (GtkVi*)(ipvi->private_data);
+
+       return zvt_term_forkpty(ZVT_TERM(vi->term), 0);
+}
+#endif
+
+/* 
+ * PUBLIC: int gtk_vi_init __P((GtkVi **, int, char*[]));
+ */
+int
+gtk_vi_init(GtkVi **vip, int argc, char **argv)
+{
+       GtkVi   *vi;
+       GtkWidget *term;
+
+       MALLOC_GOTO(NULL, vi, GtkVi*, sizeof(GtkVi));
+       memset(vi, 0, sizeof(GtkVi));
+
+#if 0
+       term = zvt_term_new();
+       gtk_widget_show(term);
+       vi->term = term;
+       vt_parse_vt(&ZVT_TERM(term)->vx->vt, "test\n", 5);
+#endif
+       /* doesn't work now; need to know when other process is running
+       gtk_signal_connect(GTK_OBJECT(term), "key_press_event",
+           (GtkSignalFunc) vi_key_press_event, vi);
+       */
+
+/*
+       vi_create(&vi->ipvi, IP_EX_ALLOWED);
+*/
+       vi_create(&vi->ipvi, 0);
+       vi->ipvi->private_data = vi;
+
+       /* Run vi: the parent returns, the child is the vi process. */
+       vi->ipvi->run(vi->ipvi, argc, argv);
+
+       *vip = vi;
+
+       return 0;
+
+alloc_err:
+       return 1;
+}
+
+#if 0
+static int
+vi_key_press_event(zvt, event, vi)
+       GtkVi *vi;
+       GtkWidget *zvt;
+       GdkEventKey *event;
+{
+       gtk_vi_key_press_event(vi, event);
+
+       gtk_signal_emit_stop_by_name(GTK_OBJECT(zvt), "key_press_event");
+       /* handled */
+       return 1;
+}
+#endif
diff --git a/dist/nvi/gtk/gtkvi.h b/dist/nvi/gtk/gtkvi.h
new file mode 100644 (file)
index 0000000..ed3519d
--- /dev/null
@@ -0,0 +1,15 @@
+/*     $NetBSD: gtkvi.h,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+#ifndef __GTK_VI_H__
+#define __GTK_VI_H__
+
+typedef struct _GtkVi           GtkVi;
+
+struct _GtkVi
+{
+//    GtkWidget        *term;
+//    GtkWidget        *vi;        /* XXX */
+//    GtkWidget        *vi_window;
+    IPVI    *ipvi;
+};
+#endif /* __GTK_VI_H__ */
diff --git a/dist/nvi/gtk/gtkviscreen.c b/dist/nvi/gtk/gtkviscreen.c
new file mode 100644 (file)
index 0000000..46d8150
--- /dev/null
@@ -0,0 +1,766 @@
+/*     $NetBSD: gtkviscreen.c,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
+#include "gtkviscreen.h"
+#include <gdk/gdkx.h>
+
+#define INTISUCS(c)    ((c & ~0x7F) && !(((c) >> 16) & 0x7F))
+#define INTUCS(c)      (c)
+#ifdef USE_WIDECHAR
+#define CHAR_WIDTH(sp, ch)  wcwidth(ch)
+#else
+#define CHAR_WIDTH(sp, ch)  1
+#endif
+
+void * v_strset __P((CHAR_T *s, CHAR_T c, size_t n));
+
+#define DEFAULT_VI_SCREEN_WIDTH_CHARS     80
+#define DEFAULT_VI_SCREEN_HEIGHT_LINES    25
+#define VI_SCREEN_BORDER_ROOM         1
+
+enum {
+  ARG_0,
+  ARG_VADJUSTMENT,
+};
+
+enum {
+    RESIZED,
+    LAST_SIGNAL
+};
+
+static void gtk_vi_screen_class_init     (GtkViScreenClass   *klass);
+static void gtk_vi_screen_set_arg        (GtkObject      *object,
+                                         GtkArg         *arg,
+                                         guint           arg_id);
+static void gtk_vi_screen_get_arg        (GtkObject      *object,
+                                         GtkArg         *arg,
+                                         guint           arg_id);
+static void gtk_vi_screen_init           (GtkViScreen        *vi);
+static void gtk_vi_screen_destroy        (GtkObject      *object);
+static void gtk_vi_screen_realize        (GtkWidget      *widget);
+/*
+static void gtk_vi_screen_map (GtkWidget *widget);
+static void gtk_vi_screen_unmap (GtkWidget *widget);
+*/
+static void gtk_vi_screen_size_request   (GtkWidget      *widget,
+                                     GtkRequisition *requisition);
+static void gtk_vi_screen_size_allocate  (GtkWidget      *widget,
+                                     GtkAllocation  *allocation);
+/*
+static void gtk_vi_screen_adjustment     (GtkAdjustment  *adjustment,
+                                     GtkViScreen        *text);
+*/
+
+static gint gtk_vi_screen_expose            (GtkWidget         *widget,
+                                        GdkEventExpose    *event);
+
+static void recompute_geometry (GtkViScreen* vi);
+static void expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor);
+static void draw_lines(GtkViScreen *vi, gint y, gint x, gint ymax, gint xmax);
+static void mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax);
+
+static GtkWidgetClass *parent_class = NULL;
+static guint vi_screen_signals[LAST_SIGNAL] = { 0 };
+
+static GdkFont *gb_font;
+static GdkFont *tfn;
+static GdkFont *tfw;
+
+#define CharAt(scr,y,x)        scr->chars + (y) * scr->cols + x
+#define FlagAt(scr,y,x)        (scr->reverse + (y) * scr->cols + x)
+#define ColAt(scr,y,x) (scr->endcol + (y) * scr->cols + x)
+
+#define COLOR_STANDARD     0x00
+#define COLOR_STANDOUT     0x01
+
+/* XXX */
+enum { SA_ALTERNATE, SA_INVERSE };
+
+void
+gtk_vi_screen_attribute(GtkViScreen *vi, gint attribute, gint on)
+{
+    switch (attribute) {
+    case SA_INVERSE:
+       vi->color = on ? COLOR_STANDOUT : COLOR_STANDARD;
+       break;
+    }
+}
+
+/* col is screen column */
+void
+gtk_vi_screen_move(GtkViScreen *vi, gint row, gint col)
+{
+    gint x;
+    guchar *endcol;
+
+    endcol = vi->endcol + row*vi->cols;
+    for (x = 0; col > endcol[x]; ++x);
+    vi->curx = x;
+    vi->cury = row;
+}
+
+static void
+cleartoel (GtkViScreen *vi, guint row, guint col)
+{
+    CHAR_T *p, *e;
+
+    if (MEMCMP(p = CharAt(vi,row,col), e = CharAt(vi,vi->rows,0), 
+               vi->cols - col)) {
+       MEMMOVE(p, e, vi->cols - col);
+       memset(FlagAt(vi,row,col), COLOR_STANDARD, vi->cols - col);
+       mark_lines(vi, row, col, row+1, vi->cols);
+    }
+}
+
+void
+gtk_vi_screen_clrtoel (GtkViScreen *vi)
+{
+    cleartoel(vi, vi->cury, vi->curx);
+}
+
+void
+gtk_vi_screen_addstr(GtkViScreen *vi, const char *str, int len)
+{
+    CHAR_T *p, *end;
+    CHAR_T *line;
+    guchar *endcol;
+    gint col, startcol;
+    gint x;
+
+    line = vi->chars + vi->cury*vi->cols; 
+    endcol = vi->endcol + vi->cury*vi->cols;
+    x = vi->curx;
+    startcol = x ? endcol[x-1] : -1;
+    for (p = CharAt(vi,vi->cury,vi->curx), end = p + len, col = startcol; 
+                p < end; ++x) {
+       *p++ = *str++;
+       endcol[x] = ++col;
+    }
+    memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
+
+    mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
+
+    if (endcol[x-1] >= vi->cols) {
+       if (++vi->cury >= vi->rows) {
+           vi->cury = vi->rows-1;
+           vi->curx = x-1;
+       } else {
+           vi->curx = 0;
+       }
+    } else vi->curx += len;
+    if (x < vi->cols) endcol[x] = vi->cols;
+}
+
+void
+gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len)
+{
+    CHAR_T *p, *end;
+    CHAR_T *line;
+    guchar *endcol;
+    gint col, startcol;
+    gint x;
+
+    MEMMOVE(CharAt(vi,vi->cury,vi->curx),str,len);
+    memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
+
+    line = vi->chars + vi->cury*vi->cols; 
+    endcol = vi->endcol + vi->cury*vi->cols;
+    x = vi->curx;
+    startcol = x ? endcol[x-1] : -1;
+    for (col = startcol; x < vi->curx + len; ++x)
+       endcol[x] = col += CHAR_WIDTH(NULL, *(line+x));
+
+    mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
+
+    if (endcol[x-1] >= vi->cols) {
+       if (++vi->cury >= vi->rows) {
+           vi->cury = vi->rows-1;
+           vi->curx = x-1;
+       } else {
+           vi->curx = 0;
+       }
+    } else vi->curx += len;
+    if (x < vi->cols) endcol[x] = vi->cols;
+}
+
+void
+gtk_vi_screen_deleteln(GtkViScreen *vi)
+{
+    gint y = vi->cury;
+    gint rows = vi->rows - (y+1);
+
+    MEMMOVE(CharAt(vi,y,0), CharAt(vi,y+1,0), rows * vi->cols);
+    cleartoel(vi,vi->rows-1,0);
+    memmove(FlagAt(vi,y,0), FlagAt(vi,y+1,0), rows * vi->cols);
+    memmove(ColAt(vi,y,0), ColAt(vi,y+1,0), rows * vi->cols);
+    mark_lines(vi, y, 0, vi->rows-1, vi->cols);
+}
+
+void
+gtk_vi_screen_insertln(GtkViScreen *vi)
+{
+    gint y = vi->cury;
+    gint rows = vi->rows - (y+1);
+
+    MEMMOVE(CharAt(vi,y+1,0), CharAt(vi,y,0), rows * vi->cols);
+    cleartoel(vi,y,0);
+    memmove(FlagAt(vi,y+1,0), FlagAt(vi,y,0), rows * vi->cols);
+    memmove(ColAt(vi,y+1,0), ColAt(vi,y,0), rows * vi->cols);
+    mark_lines(vi, y+1, 0, vi->rows, vi->cols);
+}
+
+void
+gtk_vi_screen_refresh(GtkViScreen *vi)
+{
+    if (vi->lastx != vi->curx || vi->lasty != vi-> cury) {
+       mark_lines(vi, vi->lasty, 
+               vi->lastx ? *ColAt(vi,vi->lasty,vi->lastx-1) + 1 : 0, 
+               vi->lasty+1, *ColAt(vi,vi->lasty,vi->lastx)+1);
+       mark_lines(vi, vi->cury, 
+               vi->curx ? *ColAt(vi,vi->cury,vi->curx-1) + 1 : 0, 
+               vi->cury+1, *ColAt(vi,vi->cury,vi->curx)+1);
+    }
+    if (vi->marked_maxy == 0)
+       return;
+    draw_lines(vi, vi->marked_y, vi->marked_x, vi->marked_maxy, vi->marked_maxx);
+    vi->marked_x = vi->cols;
+    vi->marked_y = vi->rows;
+    vi->marked_maxx = 0;
+    vi->marked_maxy = 0;
+    vi->lastx = vi->curx;
+    vi->lasty = vi->cury;
+}
+
+void
+gtk_vi_screen_rewrite(GtkViScreen *vi, gint row)
+{
+    memset(FlagAt(vi,row,0), COLOR_STANDARD, vi->cols);
+    mark_lines(vi, row, 0, row+1, vi->cols);
+}
+
+GtkType
+gtk_vi_screen_get_type (void)
+{
+  static GtkType vi_screen_type = 0;
+  
+  if (!vi_screen_type)
+    {
+      static const GtkTypeInfo vi_screen_info =
+      {
+       "GtkViScreen",
+       sizeof (GtkViScreen),
+       sizeof (GtkViScreenClass),
+       (GtkClassInitFunc) gtk_vi_screen_class_init,
+       (GtkObjectInitFunc) gtk_vi_screen_init,
+       /* reserved_1 */ NULL,
+        /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
+      
+      vi_screen_type = gtk_type_unique (GTK_TYPE_WIDGET, &vi_screen_info);
+    }
+  
+  return vi_screen_type;
+}
+
+static void
+gtk_vi_screen_class_init (GtkViScreenClass *class)
+{
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+  
+  object_class = (GtkObjectClass*) class;
+  widget_class = (GtkWidgetClass*) class;
+  parent_class = gtk_type_class (GTK_TYPE_WIDGET);
+
+  vi_screen_signals[RESIZED] =
+    gtk_signal_new ("resized",
+                   GTK_RUN_FIRST,
+                   GTK_CLASS_TYPE(object_class),
+                   GTK_SIGNAL_OFFSET (GtkViScreenClass, resized),
+                   gtk_marshal_NONE__INT_INT,
+                   GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT, 0);
+
+#ifndef HAVE_PANGO
+  gtk_object_class_add_signals(object_class, vi_screen_signals, LAST_SIGNAL);
+#endif
+
+  gtk_object_add_arg_type ("GtkViScreen::vadjustment",
+                          GTK_TYPE_ADJUSTMENT,
+                          GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+                          ARG_VADJUSTMENT);
+
+  object_class->set_arg = gtk_vi_screen_set_arg;
+  object_class->get_arg = gtk_vi_screen_get_arg;
+  object_class->destroy = gtk_vi_screen_destroy;
+
+  widget_class->realize = gtk_vi_screen_realize;
+  /*
+  widget_class->map = gtk_vi_screen_map;
+  widget_class->unmap = gtk_vi_screen_unmap;
+  */
+  widget_class->size_request = gtk_vi_screen_size_request;
+  widget_class->size_allocate = gtk_vi_screen_size_allocate;
+  widget_class->expose_event = gtk_vi_screen_expose;
+
+  class->rename = NULL;
+  class->resized = NULL;
+
+  gb_font = gdk_font_load ("-*-*-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*");
+  /*
+  tf = gdk_font_load ("-misc-fixed-*-*-*-*-16-*-*-*-*-*-iso10646-*");
+  */
+  tfn = gdk_font_load ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646");
+  tfw = gdk_font_load ("-Misc-Fixed-Medium-R-*-*-13-120-75-75-C-120-ISO10646-1");
+}
+
+static void
+gtk_vi_screen_set_arg (GtkObject        *object,
+                     GtkArg           *arg,
+                     guint             arg_id)
+{
+  GtkViScreen *vi_screen;
+  
+  vi_screen = GTK_VI_SCREEN (object);
+  
+  switch (arg_id)
+    {
+    case ARG_VADJUSTMENT:
+      gtk_vi_screen_set_adjustment (vi_screen, GTK_VALUE_POINTER (*arg));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+gtk_vi_screen_get_arg (GtkObject        *object,
+                     GtkArg           *arg,
+                     guint             arg_id)
+{
+  GtkViScreen *vi_screen;
+  
+  vi_screen = GTK_VI_SCREEN (object);
+  
+  switch (arg_id)
+    {
+    case ARG_VADJUSTMENT:
+      GTK_VALUE_POINTER (*arg) = vi_screen->vadj;
+      break;
+    default:
+      arg->type = GTK_TYPE_INVALID;
+      break;
+    }
+}
+
+static void
+gtk_vi_screen_init (GtkViScreen *vi)
+{
+  GtkStyle *style;
+
+  GTK_WIDGET_SET_FLAGS (vi, GTK_CAN_FOCUS);
+
+  vi->text_area = NULL;
+  vi->chars = 0;
+  vi->reverse = 0;
+  vi->cols = 0;
+  vi->color = COLOR_STANDARD;
+  vi->cols = 0;
+  vi->rows = 0;
+
+#ifdef HAVE_PANGO
+  vi->conx = NULL;
+#endif
+
+  style = gtk_style_copy(GTK_WIDGET(vi)->style);
+  gdk_font_unref(style->font);
+  style->font = gdk_font_load("-*-fixed-*-*-*-*-16-*-*-*-*-*-iso8859-*");
+  GTK_WIDGET(vi)->style = style;
+}
+
+static void
+gtk_vi_screen_destroy (GtkObject *object)
+{
+  GtkViScreen *vi_screen;
+  
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_VI_SCREEN (object));
+  
+  vi_screen = (GtkViScreen*) object;
+
+  /*
+  gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
+  */
+
+  GTK_OBJECT_CLASS(parent_class)->destroy (object);
+}
+
+GtkWidget*
+gtk_vi_screen_new (GtkAdjustment *vadj)
+{
+  GtkWidget *vi;
+
+  vi = gtk_widget_new (GTK_TYPE_VI_SCREEN,
+                        "vadjustment", vadj,
+                        NULL);
+
+
+  return vi;
+}
+
+void
+gtk_vi_screen_set_adjustment (GtkViScreen       *vi_screen,
+                         GtkAdjustment *vadj)
+{
+  g_return_if_fail (vi_screen != NULL);
+  g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
+  if (vadj)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
+  else
+    vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 0.0, 1.0, 0.0, 0.0));
+  
+  if (vi_screen->vadj && (vi_screen->vadj != vadj))
+    {
+      gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
+      gtk_object_unref (GTK_OBJECT (vi_screen->vadj));
+    }
+  
+  if (vi_screen->vadj != vadj)
+    {
+      vi_screen->vadj = vadj;
+      gtk_object_ref (GTK_OBJECT (vi_screen->vadj));
+      gtk_object_sink (GTK_OBJECT (vi_screen->vadj));
+      
+      /*
+      gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "changed",
+                         (GtkSignalFunc) gtk_vi_screen_adjustment,
+                         vi_screen);
+      gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "value_changed",
+                         (GtkSignalFunc) gtk_vi_screen_adjustment,
+                         vi_screen);
+      gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "disconnect",
+                         (GtkSignalFunc) gtk_vi_screen_disconnect,
+                         vi_screen);
+      gtk_vi_screen_adjustment (vadj, vi_screen);
+      */
+    }
+}
+
+static void
+gtk_vi_screen_realize (GtkWidget *widget)
+{
+  GtkViScreen *vi;
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_VI_SCREEN (widget));
+  
+  vi = GTK_VI_SCREEN (widget);
+  GTK_WIDGET_SET_FLAGS (vi, GTK_REALIZED);
+  
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x;
+  attributes.y = widget->allocation.y;
+  attributes.width = widget->allocation.width;
+  attributes.height = widget->allocation.height;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |= (GDK_EXPOSURE_MASK |
+                           GDK_BUTTON_PRESS_MASK |
+                           GDK_BUTTON_RELEASE_MASK |
+                           GDK_BUTTON_MOTION_MASK |
+                           GDK_ENTER_NOTIFY_MASK |
+                           GDK_LEAVE_NOTIFY_MASK |
+                           GDK_KEY_PRESS_MASK);
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, vi);
+  
+  attributes.x = (widget->style->xthickness + VI_SCREEN_BORDER_ROOM);
+  attributes.y = (widget->style->ythickness + VI_SCREEN_BORDER_ROOM);
+  attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
+  attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
+  
+  vi->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
+  gdk_window_set_user_data (vi->text_area, vi);
+  
+  widget->style = gtk_style_attach (widget->style, widget->window);
+  
+  /* Can't call gtk_style_set_background here because it's handled specially */
+  gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
+  gdk_window_set_background (vi->text_area, &widget->style->base[GTK_STATE_NORMAL]);
+
+  vi->gc = gdk_gc_new (vi->text_area);
+  /* What's this ? */
+  gdk_gc_set_exposures (vi->gc, TRUE);
+  gdk_gc_set_foreground (vi->gc, &widget->style->text[GTK_STATE_NORMAL]);
+
+  vi->reverse_gc = gdk_gc_new (vi->text_area);
+  gdk_gc_set_foreground (vi->reverse_gc, &widget->style->base[GTK_STATE_NORMAL]);
+
+  gdk_window_show (vi->text_area);
+
+  recompute_geometry (vi);
+}  
+
+static void
+gtk_vi_screen_size_request (GtkWidget      *widget,
+                      GtkRequisition *requisition)
+{
+  gint xthick;
+  gint ythick;
+  gint char_height;
+  gint char_width;
+  GtkViScreen *vi;
+  
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_VI_SCREEN (widget));
+  g_return_if_fail (requisition != NULL);
+  
+  vi = GTK_VI_SCREEN (widget);
+
+  xthick = widget->style->xthickness + VI_SCREEN_BORDER_ROOM;
+  ythick = widget->style->ythickness + VI_SCREEN_BORDER_ROOM;
+  
+  vi->ch_ascent = widget->style->font->ascent;
+  vi->ch_height = (widget->style->font->ascent + widget->style->font->descent) + 1;
+  vi->ch_width = gdk_text_width (widget->style->font, "A", 1);
+  char_height = DEFAULT_VI_SCREEN_HEIGHT_LINES * vi->ch_height;
+  char_width = DEFAULT_VI_SCREEN_WIDTH_CHARS * vi->ch_width;
+  
+  requisition->width  = char_width  + xthick * 2;
+  requisition->height = char_height + ythick * 2;
+}
+
+static void
+gtk_vi_screen_size_allocate (GtkWidget     *widget,
+                       GtkAllocation *allocation)
+{
+  GtkViScreen *vi;
+  
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_VI_SCREEN (widget));
+  g_return_if_fail (allocation != NULL);
+  
+  vi = GTK_VI_SCREEN (widget);
+  
+  widget->allocation = *allocation;
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (widget->window,
+                             allocation->x, allocation->y,
+                             allocation->width, allocation->height);
+      
+      gdk_window_move_resize (vi->text_area,
+                             widget->style->xthickness + VI_SCREEN_BORDER_ROOM,
+                             widget->style->ythickness + VI_SCREEN_BORDER_ROOM,
+                             MAX (1, (gint)widget->allocation.width - (gint)(widget->style->xthickness +
+                                                         (gint)VI_SCREEN_BORDER_ROOM) * 2),
+                             MAX (1, (gint)widget->allocation.height - (gint)(widget->style->ythickness +
+                                                          (gint)VI_SCREEN_BORDER_ROOM) * 2));
+      
+      recompute_geometry (vi);
+    }
+}
+
+/*
+static void
+gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
+                        GtkViScreen       *vi_screen)
+{
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+  g_return_if_fail (vi_screen != NULL);
+  g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
+
+}
+*/
+  
+static gint
+gtk_vi_screen_expose (GtkWidget      *widget,
+                GdkEventExpose *event)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_VI_SCREEN (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+  
+  if (event->window == GTK_VI_SCREEN (widget)->text_area)
+    {
+      expose_text (GTK_VI_SCREEN (widget), &event->area, TRUE);
+    }
+  
+  return FALSE;
+}
+
+static void
+recompute_geometry (GtkViScreen* vi)
+{
+    //gint xthickness;
+    //gint ythickness;
+    gint height;
+    gint width;
+    gint rows, cols;
+    gint i;
+
+    //xthickness = widget->style->xthickness + VI_SCREEN_BORDER_ROOM;
+    //ythickness = widget->style->ythickness + VI_SCREEN_BORDER_ROOM;
+
+    gdk_window_get_size (vi->text_area, &width, &height);
+
+    rows = height / vi->ch_height;
+    cols = width / vi->ch_width;
+
+    if (rows == vi->rows && cols == vi->cols)
+       return;
+
+    vi->marked_x = vi->cols = cols;
+    vi->marked_y = vi->rows = rows;
+    vi->marked_maxx = 0;
+    vi->marked_maxy = 0;
+
+    g_free(vi->chars);
+    vi->chars = (CHAR_T*)g_new(gchar, (vi->rows+1)*vi->cols * sizeof(CHAR_T));
+    STRSET(vi->chars, L(' '), (vi->rows+1)*vi->cols);
+    g_free(vi->endcol);
+    vi->endcol = g_new(guchar, vi->rows*vi->cols);
+    g_free(vi->reverse);
+    vi->reverse = g_new(guchar, vi->rows*vi->cols);
+    memset(vi->reverse, 0, vi->rows*vi->cols);
+
+    gtk_signal_emit(GTK_OBJECT(vi), vi_screen_signals[RESIZED], vi->rows, vi->cols);
+}
+
+static void
+expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor)
+{
+    gint ymax;
+    gint xmax, xmin;
+
+    gdk_window_clear_area (vi->text_area, area->x, area->y, 
+                           area->width, area->height);
+    ymax = MIN((area->y + area->height + vi->ch_height - 1) / vi->ch_height,
+               vi->rows);
+    xmin = area->x / vi->ch_width;
+    xmax = MIN((area->x + area->width + vi->ch_width - 1) / vi->ch_width,
+               vi->cols);
+    draw_lines(vi, area->y / vi->ch_height, xmin, ymax, xmax);
+}
+
+#define Inverse(screen,y,x) \
+    ((*FlagAt(screen,y,x) == COLOR_STANDOUT) ^ \
+       (screen->cury == y && screen->curx == x))
+
+static void
+draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
+{
+    gint y, x, len, blen, xpos;
+    CHAR_T *line;
+    GdkGC *fg, *bg;
+    GdkFont *font;
+    gchar buf[2];
+    gchar *p;
+    gboolean pango;
+
+    for (y = ymin, line = vi->chars + y*vi->cols; 
+                            y < ymax; ++y, line += vi->cols) {
+       for (x = 0, xpos = 0; xpos <= xmin; ++x)
+           xpos += CHAR_WIDTH(NULL, *(line+x));
+       --x;
+       xpos -= CHAR_WIDTH(NULL, *(line+x));
+       for (; xpos < xmax; x+=len, xpos+= blen) {
+           gchar inverse;
+           inverse = Inverse(vi,y,x); 
+           len = 1;
+           if (sizeof(CHAR_T) == sizeof(gchar))
+               for (; x+len < xmax && 
+                      Inverse(vi,y,x+len) == inverse; ++len);
+           if (inverse) {
+               fg = vi->reverse_gc;
+               bg = vi->gc;
+           } else {
+               bg = vi->reverse_gc;
+               fg = vi->gc;
+           }
+           pango = 0;
+#ifdef HAVE_PANGO
+           if (INTISUCS(*(line+x))) {
+               if (!vi->conx) {
+                   PangoFontDescription font_description;
+
+                   font_description.family_name = g_strdup ("monospace");
+                   font_description.style = PANGO_STYLE_NORMAL;
+                   font_description.variant = PANGO_VARIANT_NORMAL;
+                   font_description.weight = 500;
+                   font_description.stretch = PANGO_STRETCH_NORMAL;
+                   font_description.size = 15000;
+
+                   vi->conx = gdk_pango_context_get();
+                   pango_context_set_font_description (vi->conx, 
+                       &font_description);
+                   pango_context_set_lang(vi->conx, "en_US");
+                   vi->alist = pango_attr_list_new();
+               }
+               blen = CHAR_WIDTH(NULL, *(line+x));
+               pango = 1;
+           } else 
+#endif
+           {
+               font = GTK_WIDGET(vi)->style->font;
+               if (sizeof(CHAR_T) == sizeof(gchar))
+                   p = (gchar*)line+x;
+               else {
+                   buf[0] = *(line+x);
+                   p = buf;
+               }
+               blen = len;
+           }
+           gdk_draw_rectangle(vi->text_area, bg, 1, xpos * vi->ch_width,
+                               y * vi->ch_height, blen * vi->ch_width,
+                               vi->ch_height);
+           /* hack to not display half a wide character that wasn't
+            * removed.
+            */
+           if (!pango)
+               gdk_draw_text (vi->text_area, font, fg,
+                               xpos * vi->ch_width, 
+                               y * vi->ch_height + vi->ch_ascent, 
+                               p, blen);
+#ifdef HAVE_PANGO
+           else {
+               PangoGlyphString *gs;
+               GList *list;
+               PangoItem *item;
+               char buf[3];
+               int len;
+
+               len = ucs2utf8(line+x, 1, buf);
+               list = pango_itemize(vi->conx, buf, 0, len, vi->alist, NULL);
+               item = list->data;
+               gs = pango_glyph_string_new ();
+               pango_shape(buf, len, &item->analysis, gs);
+
+               gdk_draw_glyphs (vi->text_area, fg, item->analysis.font,
+                               xpos * vi->ch_width, 
+                               y * vi->ch_height + vi->ch_ascent, gs);
+           }
+#endif
+       }
+    }
+}
+
+static void
+mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
+{
+    if (ymin < vi->marked_y) vi->marked_y = ymin;
+    if (xmin < vi->marked_x) vi->marked_x = xmin;
+    if (ymax > vi->marked_maxy) vi->marked_maxy = ymax;
+    if (xmax > vi->marked_maxx) vi->marked_maxx = xmax;
+}
diff --git a/dist/nvi/gtk/gtkviscreen.h b/dist/nvi/gtk/gtkviscreen.h
new file mode 100644 (file)
index 0000000..d174478
--- /dev/null
@@ -0,0 +1,78 @@
+/*     $NetBSD: gtkviscreen.h,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+#ifndef __GTK_VI_SCREEN_H__
+#define __GTK_VI_SCREEN_H__
+
+#include <sys/types.h>
+#include "config.h"
+#include "port.h"
+#include "../common/multibyte.h"
+
+#ifdef HAVE_PANGO
+#include <pango/pango.h>
+#include <pango/pangox.h>
+#else
+#define xthickness klass->xthickness
+#define ythickness klass->ythickness
+#define GTK_CLASS_TYPE(class)  class->type
+#endif
+
+#define GTK_TYPE_VI_SCREEN                  (gtk_vi_screen_get_type ())
+#define GTK_VI_SCREEN(obj)                  (GTK_CHECK_CAST ((obj), GTK_TYPE_VI_SCREEN, GtkViScreen))
+#define GTK_VI_SCREEN_CLASS(klass)          (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_VI_SCREEN, GtkViScreenClass))
+#define GTK_IS_VI_SCREEN(obj)               (GTK_CHECK_TYPE ((obj), GTK_TYPE_VI_SCREEN))
+#define GTK_IS_VI_SCREEN_CLASS(klass)       (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_VI_SCREEN))
+
+typedef struct _GtkViScreen           GtkViScreen;
+typedef struct _GtkViScreenClass      GtkViScreenClass;
+
+struct _GtkViScreen
+{
+  GtkWidget widget;
+
+  GdkWindow *text_area;
+
+  GtkAdjustment *vadj;
+
+  GdkGC *gc;
+  GdkGC *reverse_gc;
+
+  CHAR_T  *chars;
+  guchar  *endcol;         
+  guchar  *reverse;
+  guchar  color;
+
+  gint cols, rows;
+  gint ch_width, ch_height, ch_ascent;
+  gint  curx, cury;                     /* character position */
+  gint  lastx, lasty;
+  gint marked_x, marked_y, marked_maxx, marked_maxy;
+
+#ifdef HAVE_PANGO
+  PangoContext *conx;
+  PangoAttrList* alist;
+#endif
+};
+
+struct _GtkViScreenClass
+{
+  GtkWidgetClass parent_class;
+
+  void (*rename) (GtkViScreen *vi, gchar *name, gint len);
+  void (*resized) (GtkViScreen *vi, gint width, gint height);
+};
+
+GtkType    gtk_vi_screen_get_type        (void);
+GtkWidget* gtk_vi_screen_new             (GtkAdjustment *vadj);
+void      gtk_vi_screen_set_adjustment (GtkViScreen       *vi_screen,
+                                         GtkAdjustment *vadj);
+void      gtk_vi_screen_move             (GtkViScreen *vi, gint row, gint col);
+void      gtk_vi_screen_clrtoel          (GtkViScreen *vi);
+void      gtk_vi_screen_attribute(GtkViScreen *vi, gint attribute, gint on);
+void      gtk_vi_screen_addstr   (GtkViScreen *vi, const char *str, int len);
+void      gtk_vi_screen_deleteln       (GtkViScreen *vi);
+void      gtk_vi_screen_insertln       (GtkViScreen *vi);
+void      gtk_vi_screen_refresh        (GtkViScreen *vi);
+void      gtk_vi_screen_rewrite        (GtkViScreen *vi, gint row);
+
+#endif /* __GTK_VI_SCREEN_H__ */
diff --git a/dist/nvi/gtk/gtkviwindow.c b/dist/nvi/gtk/gtkviwindow.c
new file mode 100644 (file)
index 0000000..391b82c
--- /dev/null
@@ -0,0 +1,692 @@
+/*     $NetBSD: gtkviwindow.c,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+/* change further to gtkviwindow have no knowledge of ipvi */
+#include "config.h"
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#if 0
+#ifdef HAVE_ZVT
+#include <zvt/zvtterm.h>
+#include <zvt/vt.h>
+#endif
+#endif
+
+#include "../common/common.h"
+#include "../ipc/ip.h"
+
+#include "gtkvi.h"
+#include "gtkviscreen.h"
+#include "gtkviwindow.h"
+#include "extern.h"
+
+enum {
+    RENAME,
+    LAST_SIGNAL
+};
+
+static void gtk_vi_window_class_init     (GtkViWindowClass   *klass);
+static void gtk_vi_window_init           (GtkViWindow        *vi);
+static void gtk_vi_window_destroy       (GtkObject *object);
+
+static int vi_key_press_event __P((GtkWidget*, GdkEventKey*, GtkViWindow*));
+static void vi_map __P((GtkWidget *, GtkWidget*));
+static void vi_resized __P((GtkWidget *, int, int, IPVIWIN*));
+static void vi_adjustment_value_changed __P((GtkAdjustment *, IPVIWIN *));
+
+static void vi_input_func __P((gpointer , gint , GdkInputCondition));
+
+static void vi_init_window __P((GtkViWindow *window, int));
+
+static int vi_addstr __P((IPVIWIN*, const char *, u_int32_t));
+static int vi_waddstr __P((IPVIWIN*, const CHAR_T *, u_int32_t));
+static int vi_attribute __P((IPVIWIN*,u_int32_t  ,u_int32_t   ));
+static int vi_bell __P((IPVIWIN*));
+static int vi_busyon __P((IPVIWIN*, const char *, u_int32_t));
+static int vi_busyoff __P((IPVIWIN*));
+static int vi_clrtoeol __P((IPVIWIN*));
+static int vi_deleteln __P((IPVIWIN*));
+static int vi_discard __P((IPVIWIN*));
+static int vi_editopt __P((IPVIWIN*, const char *, u_int32_t,
+                            const char *, u_int32_t, u_int32_t));
+static int vi_insertln __P((IPVIWIN*));
+static int vi_move __P((IPVIWIN*, u_int32_t, u_int32_t));
+static int vi_quit __P((IPVIWIN*));
+static int vi_redraw __P((IPVIWIN*));
+static int vi_refresh __P((IPVIWIN*));
+static int vi_rename __P((IPVIWIN*, const char *, u_int32_t));
+static int vi_rewrite __P((IPVIWIN*, u_int32_t));
+static int vi_scrollbar __P((IPVIWIN*, u_int32_t, u_int32_t , u_int32_t ));
+static int vi_select __P((IPVIWIN*, const char *, u_int32_t));
+static int vi_split __P((IPVIWIN*));
+static int vi_ex_init __P((IPVIWIN*));
+static int vi_vi_init __P((IPVIWIN*));
+static int vi_fork __P((IPVIWIN*));
+
+static GtkWidgetClass *parent_class = NULL;
+static guint vi_window_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gtk_vi_window_get_type (void)
+{
+  static GtkType vi_window_type = 0;
+  
+  if (!vi_window_type)
+    {
+      static const GtkTypeInfo vi_window_info =
+      {
+       "GtkViWindow",
+       sizeof (GtkViWindow),
+       sizeof (GtkViWindowClass),
+       (GtkClassInitFunc) gtk_vi_window_class_init,
+       (GtkObjectInitFunc) gtk_vi_window_init,
+       /* reserved_1 */ NULL,
+        /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
+      
+      vi_window_type = gtk_type_unique (GTK_TYPE_NOTEBOOK, &vi_window_info);
+    }
+  
+  return vi_window_type;
+}
+
+static void
+gtk_vi_window_class_init (GtkViWindowClass *class)
+{
+  GtkObjectClass *object_class;
+  
+  object_class = (GtkObjectClass*) class;
+  parent_class = gtk_type_class (GTK_TYPE_WIDGET);
+
+  vi_window_signals[RENAME] =
+    gtk_signal_new ("rename",
+                   GTK_RUN_FIRST,
+                   GTK_CLASS_TYPE(object_class),
+                   GTK_SIGNAL_OFFSET (GtkViScreenClass, rename),
+                   gtk_marshal_VOID__STRING,
+                   GTK_TYPE_NONE, 1, GTK_TYPE_STRING, 0);
+
+#ifndef HAVE_PANGO
+  gtk_object_class_add_signals(object_class, vi_window_signals, LAST_SIGNAL);
+#endif
+
+  object_class->destroy = gtk_vi_window_destroy;
+}
+
+static void 
+gtk_vi_window_init (GtkViWindow *vi)
+{
+}
+
+GtkWidget *
+gtk_vi_window_new (GtkVi *vi)
+{
+    GtkViWindow* window;
+    GtkWidget *vi_widget;
+    GtkWidget *vscroll;
+    GtkWidget *table;
+    GtkWidget *term;
+    int               fd;
+#ifdef HAVE_ZVT
+    int               pty[2];
+#endif
+
+    window = gtk_type_new(gtk_vi_window_get_type());
+
+    window->vi = vi;
+    //vi->vi_window = GTK_WIDGET(window);
+
+    vi_widget = gtk_vi_screen_new(NULL);
+    gtk_widget_show(GTK_WIDGET(vi_widget));
+    /*
+    vi->vi = vi_widget;
+    */
+    window->vi_screen = vi_widget;
+
+    vscroll = gtk_vscrollbar_new(GTK_VI_SCREEN(vi_widget)->vadj);
+    gtk_widget_show(vscroll);
+
+    table = gtk_table_new(2, 2, FALSE);
+    gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(vi_widget),
+       0, 1, 0, 1);
+    gtk_table_attach(GTK_TABLE(table), vscroll, 1, 2, 0, 1,
+       (GtkAttachOptions)0, GTK_FILL, 0, 0);
+    gtk_widget_show(table);
+    gtk_signal_connect(GTK_OBJECT(table), "map", GTK_SIGNAL_FUNC(vi_map), 
+                       vi_widget/*->ipvi*/);
+    window->table = table;
+
+
+    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(window), FALSE);
+    gtk_notebook_set_show_border(GTK_NOTEBOOK(window), FALSE);
+    gtk_notebook_append_page(GTK_NOTEBOOK(window), table, NULL);
+
+    term = 0;
+    fd = -1;
+
+#if 0
+#ifdef HAVE_ZVT
+    term = zvt_term_new();
+    zvt_term_set_blink(ZVT_TERM(term), FALSE);
+    zvt_term_get_ptys(ZVT_TERM(term), 0, pty);
+    fd = pty[1]; /* slave */
+    gtk_widget_show(term);
+    gtk_notebook_append_page(GTK_NOTEBOOK(window), term, NULL);
+#endif
+#endif
+    window->term = term;
+
+    vi_init_window(window, fd);
+
+    gtk_signal_connect(GTK_OBJECT(vi_widget), "resized",
+       GTK_SIGNAL_FUNC(vi_resized), window->ipviwin);
+    gtk_signal_connect(GTK_OBJECT(vi_widget), "key_press_event",
+       (GtkSignalFunc) vi_key_press_event, window);
+    window->value_changed = 
+       gtk_signal_connect(GTK_OBJECT(GTK_VI_SCREEN(vi_widget)->vadj), 
+           "value_changed",
+           (GtkSignalFunc) vi_adjustment_value_changed, window->ipviwin);
+
+    return GTK_WIDGET(window);
+}
+
+static void
+gtk_vi_window_destroy (GtkObject *object)
+{
+  GtkViWindow *vi_window;
+  
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_VI_WINDOW (object));
+  
+  vi_window = (GtkViWindow*) object;
+
+  if (vi_window->table) {
+    gtk_signal_disconnect_by_data(GTK_OBJECT(vi_window->table), 
+                                 vi_window->vi_screen);
+    vi_window->table = 0;
+  }
+
+  if (vi_window->vi_screen) {
+    gtk_signal_disconnect_by_data(GTK_OBJECT(vi_window->vi_screen), 
+                                 vi_window->ipviwin);
+    gtk_signal_disconnect(GTK_OBJECT(GTK_VI_SCREEN(vi_window->vi_screen)->vadj), 
+       vi_window->value_changed);
+    gtk_widget_destroy(vi_window->vi_screen);
+    vi_window->vi_screen = 0;
+  }
+
+  GTK_OBJECT_CLASS(parent_class)->destroy (object);
+}
+
+void
+gtk_vi_window_scrollbar(GtkViWindow *vi, guint top, guint size, guint max)
+{
+    GtkViScreen *vi_screen;
+    /* work around gcc bug */
+    volatile guint mymax = max;
+    volatile guint mysize = size;
+
+    vi_screen = GTK_VI_SCREEN(vi->vi_screen);
+    vi_screen->vadj->value = top;
+    vi_screen->vadj->upper = mymax;
+    vi_screen->vadj->page_size =
+       vi_screen->vadj->page_increment = mysize;
+    gtk_signal_handler_block(GTK_OBJECT(vi_screen->vadj), vi->value_changed);
+    gtk_adjustment_changed(vi_screen->vadj);
+    /*
+    gtk_adjustment_value_changed(vi_screen->vadj);
+    */
+    gtk_signal_handler_unblock(GTK_OBJECT(vi_screen->vadj), vi->value_changed);
+}
+
+/*
+ * PUBLIC: void gtk_vi_quit __P((GtkViWindow*, gint));
+ */
+void
+gtk_vi_quit(vi, write)
+    GtkViWindow *vi;
+    gint write;
+{
+    if (write)
+       vi->ipviwin->wq(vi->ipviwin);
+    else
+       vi->ipviwin->quit(vi->ipviwin);
+}
+
+/*
+ * PUBLIC: void gtk_vi_show_term __P((GtkViWindow*, gint));
+ */
+void
+gtk_vi_show_term(window, show)
+    GtkViWindow *window;
+    gint show;
+{
+    gtk_notebook_set_page(GTK_NOTEBOOK(window), show ? 1 : 0);
+}
+
+/*
+ * PUBLIC: void gtk_vi_key_press_event __P((GtkViWindow*, GdkEventKey*));
+ */
+void
+gtk_vi_key_press_event(window, event)
+    GtkViWindow *window;
+    GdkEventKey *event;
+{
+#if 0
+    static struct {
+       guint key;
+       gint offset;
+    } table[] = {
+       {GDK_Home,      GTK_STRUCT_OFFSET(IPVI, c_bol)      },
+       //{VI_C_BOTTOM, GTK_STRUCT_OFFSET(IPVI, c_bottom)   },
+       {GDK_End,       GTK_STRUCT_OFFSET(IPVI, c_eol)      },
+       {GDK_Insert,    GTK_STRUCT_OFFSET(IPVI, c_insert)   },
+       {GDK_Left,      GTK_STRUCT_OFFSET(IPVI, c_left)     },
+       {GDK_Right,     GTK_STRUCT_OFFSET(IPVI, c_right)    },
+       //{VI_C_TOP,    GTK_STRUCT_OFFSET(IPVI, c_top)      },
+    };
+#endif
+    static struct {
+       guint   keyval;
+       char    key;
+    } table[] = {
+       { GDK_Left,         'h' },
+       { GDK_Right,        'l' },
+       { GDK_Up,           'k' },
+       { GDK_Down,         'j' },
+       { GDK_Page_Up,      'B' - '@' },
+       { GDK_Page_Down,    'F' - '@' },
+    };
+    char key = event->keyval;
+    int i;
+
+#if 0
+    for (i = 0; i < sizeof(table)/sizeof(*table); ++i)
+       if (table[i].key == event->keyval) {
+           int (*fun) __P((IPVI*)) = 
+               *(int (**) __P((IPVI*)) )(((char *)vi->ipvi)+table[i].offset);
+           fun(vi->ipvi);
+           return;
+       }
+#endif
+    for (i = 0; i < sizeof(table)/sizeof(*table); ++i)
+       if (table[i].keyval == event->keyval) {
+           window->ipviwin->string(window->ipviwin, &table[i].key, 1);
+           return;
+       }
+
+    if (event->state & GDK_CONTROL_MASK) {
+       if ((key >= 'a') && (key <= 'z'))
+           key -= 'a' - 'A';
+       key -= '@';
+    }
+    /*
+    fprintf(stderr, "key_press %d %d %d %c %p\n", 
+       event->length, event->keyval, event->keyval, key, ipvi);
+    */
+    if (event->length > 0)
+       window->ipviwin->string(window->ipviwin, &key, 1);
+}
+
+
+
+static int
+vi_key_press_event(vi_screen, event, vi)
+    GtkViWindow *vi;
+    GtkWidget *vi_screen;
+    GdkEventKey *event;
+{
+    gint handled;
+
+    handled = gtk_accel_groups_activate (GTK_OBJECT (vi), 
+                   event->keyval, (GdkModifierType) event->state);
+    if (handled)
+       return 1;
+
+    gtk_vi_key_press_event(vi, event);
+    gtk_signal_emit_stop_by_name(GTK_OBJECT(vi_screen), "key_press_event");
+    /* handled */
+    return 1;
+}
+
+static void
+vi_map(table, vi_screen)
+       GtkWidget *vi_screen;
+       GtkWidget *table;
+{
+       gtk_widget_grab_focus(vi_screen);
+}
+
+static void
+vi_resized(vi_screen, rows, cols, ipviwin)
+    int rows,cols;
+    IPVIWIN *ipviwin;
+    GtkWidget *vi_screen;
+{
+       GtkViWindow *vi_window = GTK_VI_WINDOW((GtkVi*)(ipviwin->private_data));
+
+       ipviwin->resize(ipviwin, rows, cols);
+       vi_window->resized = 1;
+}
+
+static void 
+vi_adjustment_value_changed (adjustment, ipviwin)
+    GtkAdjustment *adjustment;
+    IPVIWIN *ipviwin;
+{
+       GtkViWindow *vi_window = GTK_VI_WINDOW((GtkVi*)(ipviwin->private_data));
+
+       if (vi_window->resized)
+               ipviwin->c_settop(ipviwin, adjustment->value);
+}
+
+
+static void 
+vi_input_func (gpointer data, gint source, GdkInputCondition condition)
+{
+    IPVIWIN *ipviwin = (IPVIWIN *) data;
+
+    (void)ipviwin->input(ipviwin, source);
+}
+
+static void
+vi_init_window (GtkViWindow *window, int fd)
+{
+    static struct ip_si_operations ipsi_ops_gtk = {
+       vi_addstr,
+       vi_attribute,
+       vi_bell,
+       vi_busyoff,
+       vi_busyon,
+       vi_clrtoeol,
+       vi_deleteln,
+       vi_discard,
+       vi_editopt,
+       vi_insertln,
+       vi_move,
+       vi_quit,
+       vi_redraw,
+       vi_refresh,
+       vi_rename,
+       vi_rewrite,
+       vi_scrollbar,
+       vi_select,
+       vi_split,
+       (IPFunc_a)vi_waddstr,
+    };
+    GtkVi *vi = window->vi;
+
+    vi->ipvi->new_window(vi->ipvi, &window->ipviwin, fd);
+
+    window->ipviwin->private_data = window;
+    window->ipviwin->set_ops(window->ipviwin, &ipsi_ops_gtk);
+    window->input_func = gtk_input_add_full(window->ipviwin->ifd, 
+                           GDK_INPUT_READ, 
+                           vi_input_func, 0, (gpointer)window->ipviwin, 0);
+}
+
+static int
+vi_addstr(ipviwin, str, len)
+       IPVIWIN *ipviwin;
+       const char *str;
+       u_int32_t len;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_addstr(GTK_VI_SCREEN(vi->vi_screen), str, len);
+       return (0);
+}
+
+static int
+vi_waddstr(ipviwin, str, len)
+       IPVIWIN *ipviwin;
+       const CHAR_T *str;
+       u_int32_t len;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_waddstr(GTK_VI_SCREEN(vi->vi_screen), str, len/sizeof(CHAR_T));
+       return (0);
+}
+
+static int
+vi_attribute(ipviwin,attribute,on)
+       IPVIWIN *ipviwin;
+       u_int32_t   attribute, on;
+{
+       GtkViWindow* window = (GtkViWindow*)(ipviwin->private_data);
+
+       if (attribute == SA_ALTERNATE) {
+               gtk_vi_show_term(window, !on);
+       }
+       else
+               gtk_vi_screen_attribute(GTK_VI_SCREEN(window->vi_screen), attribute, on);
+       return (0);
+}
+
+static int
+vi_bell(ipbp)
+       IPVIWIN *ipbp;
+{
+    /*
+    fprintf(stderr, "vi_bell\n");
+    */
+#if 0
+       /*
+        * XXX
+        * Future... implement visible bell.
+        */
+       XBell(XtDisplay(__vi_screen->area), 0);
+#endif
+       return (0);
+}
+
+static int 
+vi_busyon (IPVIWIN* ipviwin, const char *a, u_int32_t s)
+{
+    /*
+    fprintf(stderr, "vi_busyon\n");
+    */
+#if 0
+       __vi_set_cursor(__vi_screen, 1);
+#endif
+       return (0);
+}
+
+static int
+vi_busyoff(ipbp)
+       IPVIWIN *ipbp;
+{
+    /*
+    fprintf(stderr, "vi_busyoff\n");
+    */
+#if 0
+       __vi_set_cursor(__vi_screen, 0);
+#endif
+       return (0);
+}
+
+static int
+vi_clrtoeol(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_clrtoel(GTK_VI_SCREEN(vi->vi_screen));
+       return 0;
+}
+
+static int
+vi_deleteln(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_deleteln(GTK_VI_SCREEN(vi->vi_screen));
+       return (0);
+}
+
+static int 
+vi_editopt (IPVIWIN* a, const char *b, u_int32_t c,
+                            const char *d, u_int32_t e, u_int32_t f)
+{
+    /*
+    fprintf(stderr, "%p %p vi_editopt\n", a, a->private_data);
+    */
+#if 0
+       /* XXX: Nothing. */
+#endif
+       return (0);
+}
+
+
+static int
+vi_discard(ipbp)
+       IPVIWIN *ipbp;
+{
+    /*
+    fprintf(stderr, "vi_discard\n");
+    */
+#if 0
+       /* XXX: Nothing. */
+#endif
+       return (0);
+}
+
+static int
+vi_insertln(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+    gtk_vi_screen_insertln(GTK_VI_SCREEN(vi->vi_screen));
+    return (0);
+}
+
+static int
+vi_move(ipviwin, row, col)
+       IPVIWIN *ipviwin;
+       u_int32_t row;
+       u_int32_t col;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_move(GTK_VI_SCREEN(vi->vi_screen), row, col);
+       return (0);
+}
+
+static int
+vi_redraw(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_widget_draw(GTK_WIDGET(vi->vi_screen), NULL);
+       return (0);
+}
+
+static int
+vi_refresh(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_refresh(GTK_VI_SCREEN(vi->vi_screen));
+       return (0);
+}
+
+static int
+vi_quit(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_input_remove(vi->input_func);
+       gtk_widget_destroy(GTK_WIDGET(vi));
+       return (0);
+}
+
+static int
+vi_rename(ipviwin, str, len)
+       IPVIWIN *ipviwin;
+       const char *str;
+       u_int32_t len;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gchar* name = g_strndup(str, len);
+       gtk_signal_emit_by_name(GTK_OBJECT(vi), "rename", name);
+       g_free(name);
+       return (0);
+}
+
+static int
+vi_rewrite(ipviwin, row)
+       IPVIWIN *ipviwin;
+       u_int32_t row;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_screen_rewrite(GTK_VI_SCREEN(vi->vi_screen), row);
+       return (0);
+}
+
+
+static int
+vi_scrollbar(ipviwin, top, size, max)
+       IPVIWIN *ipviwin;
+       u_int32_t top, size, max;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+       gtk_vi_window_scrollbar(vi, top, size, max);
+
+       return (0);
+}
+
+static int vi_select (IPVIWIN* a, const char * b, u_int32_t c)
+{
+    /*
+    fprintf(stderr, "vi_select\n");
+    */
+#if 0
+       /* XXX: Nothing. */
+#endif
+       return (0);
+}
+
+static int
+vi_split(ipbp)
+       IPVIWIN *ipbp;
+{
+    fprintf(stderr, "vi_split\n");
+#if 0
+       /* XXX: Nothing. */
+#endif
+       return (0);
+}
+
+static int
+vi_ex_init(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+/*
+       gtk_vi_show_term(vi, 1);
+*/
+       return 0;
+}
+
+static int
+vi_vi_init(ipviwin)
+       IPVIWIN *ipviwin;
+{
+       GtkViWindow* vi = (GtkViWindow*)(ipviwin->private_data);
+
+/*
+       gtk_vi_show_term(vi, 0);
+*/
+       return 0;
+}
diff --git a/dist/nvi/gtk/gtkviwindow.h b/dist/nvi/gtk/gtkviwindow.h
new file mode 100644 (file)
index 0000000..d94541a
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: gtkviwindow.h,v 1.1.1.2 2008/05/18 14:31:22 aymeric Exp $ */
+
+#ifndef __GTK_VI_WINDOW_H__
+#define __GTK_VI_WINDOW_H__
+
+#ifndef HAVE_PANGO
+#define gtk_marshal_VOID__STRING gtk_marshal_NONE__STRING
+#define GTK_CLASS_TYPE(class)  class->type
+#endif
+
+#define GTK_TYPE_VI_WINDOW                  (gtk_vi_window_get_type ())
+#define GTK_VI_WINDOW(obj)                  (GTK_CHECK_CAST ((obj), GTK_TYPE_VI_WINDOW, GtkViWindow))
+#define GTK_VI_WINDOW_CLASS(klass)          (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_VI_WINDOW, GtkViWindowClass))
+#define GTK_IS_VI_WINDOW(obj)               (GTK_CHECK_TYPE ((obj), GTK_TYPE_VI_WINDOW))
+#define GTK_IS_VI_WINDOW_CLASS(klass)       (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_VI_WINDOW))
+
+typedef struct _GtkViWindow           GtkViWindow;
+typedef struct _GtkViWindowClass      GtkViWindowClass;
+
+struct _GtkViWindow
+{
+  GtkNotebook  notebook;
+
+  GtkWidget *term;
+
+  GtkVi            *vi;
+  GtkWidget *table;
+  GtkWidget *vi_screen;
+  gint      value_changed;
+  int      resized;
+
+  gint      input_func;
+  IPVIWIN   *ipviwin;
+};
+
+struct _GtkViWindowClass
+{
+  GtkNotebookClass  parent_class;
+};
+
+GtkType     gtk_vi_window_get_type (void);
+GtkWidget * gtk_vi_window_new (GtkVi *vi);
+void       gtk_vi_window_scrollbar(GtkViWindow *vi, guint top, guint size, guint max);
+
+#endif /* __GTK_VI_WINDOW_H__ */
diff --git a/dist/nvi/include/bitstring.h b/dist/nvi/include/bitstring.h
new file mode 100644 (file)
index 0000000..af0f92c
--- /dev/null
@@ -0,0 +1,145 @@
+/*     $NetBSD: bitstring.h,v 1.1.1.2 2008/05/18 14:31:23 aymeric Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Vixie.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)bitstring.h 8.1 (Berkeley) 7/19/93
+ */
+
+#ifndef _BITSTRING_H_
+#define        _BITSTRING_H_
+
+typedef        unsigned char bitstr_t;
+
+/* internal macros */
+                               /* byte of the bitstring bit is in */
+#define        _bit_byte(bit) \
+       ((bit) >> 3)
+
+                               /* mask for the bit within its byte */
+#define        _bit_mask(bit) \
+       (1 << ((bit)&0x7))
+
+/* external macros */
+                               /* bytes in a bitstring of nbits bits */
+#define        bitstr_size(nbits) \
+       ((((nbits) - 1) >> 3) + 1)
+
+                               /* allocate a bitstring */
+#define        bit_alloc(nbits) \
+       (bitstr_t *)calloc(1, \
+           (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t))
+
+                               /* allocate a bitstring on the stack */
+#define        bit_decl(name, nbits) \
+       (name)[bitstr_size(nbits)]
+
+                               /* is bit N of bitstring name set? */
+#define        bit_test(name, bit) \
+       ((name)[_bit_byte(bit)] & _bit_mask(bit))
+
+                               /* set bit N of bitstring name */
+#define        bit_set(name, bit) \
+       (name)[_bit_byte(bit)] |= _bit_mask(bit)
+
+                               /* clear bit N of bitstring name */
+#define        bit_clear(name, bit) \
+       (name)[_bit_byte(bit)] &= ~_bit_mask(bit)
+
+                               /* clear bits start ... stop in bitstring */
+#define        bit_nclear(name, start, stop) { \
+       register bitstr_t *_name = name; \
+       register int _start = start, _stop = stop; \
+       register int _startbyte = _bit_byte(_start); \
+       register int _stopbyte = _bit_byte(_stop); \
+       if (_startbyte == _stopbyte) { \
+               _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
+                                     (0xff << ((_stop&0x7) + 1))); \
+       } else { \
+               _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
+               while (++_startbyte < _stopbyte) \
+                       _name[_startbyte] = 0; \
+               _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
+       } \
+}
+
+                               /* set bits start ... stop in bitstring */
+#define        bit_nset(name, start, stop) { \
+       register bitstr_t *_name = name; \
+       register int _start = start, _stop = stop; \
+       register int _startbyte = _bit_byte(_start); \
+       register int _stopbyte = _bit_byte(_stop); \
+       if (_startbyte == _stopbyte) { \
+               _name[_startbyte] |= ((0xff << (_start&0x7)) & \
+                                   (0xff >> (7 - (_stop&0x7)))); \
+       } else { \
+               _name[_startbyte] |= 0xff << ((_start)&0x7); \
+               while (++_startbyte < _stopbyte) \
+                       _name[_startbyte] = 0xff; \
+               _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
+       } \
+}
+
+                               /* find first bit clear in name */
+#define        bit_ffc(name, nbits, value) { \
+       register bitstr_t *_name = name; \
+       register int _byte, _nbits = nbits; \
+       register int _stopbyte = _bit_byte(_nbits), _value = -1; \
+       for (_byte = 0; _byte <= _stopbyte; ++_byte) \
+               if (_name[_byte] != 0xff) { \
+                       _value = _byte << 3; \
+                       for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
+                           ++_value, _stopbyte >>= 1); \
+                       break; \
+               } \
+       *(value) = _value; \
+}
+
+                               /* find first bit set in name */
+#define        bit_ffs(name, nbits, value) { \
+       register bitstr_t *_name = name; \
+       register int _byte, _nbits = nbits; \
+       register int _stopbyte = _bit_byte(_nbits), _value = -1; \
+       for (_byte = 0; _byte <= _stopbyte; ++_byte) \
+               if (_name[_byte]) { \
+                       _value = _byte << 3; \
+                       for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
+                           ++_value, _stopbyte >>= 1); \
+                       break; \
+               } \
+       *(value) = _value; \
+}
+
+#endif /* !_BITSTRING_H_ */
diff --git a/dist/nvi/include/sys/queue.h b/dist/nvi/include/sys/queue.h
new file mode 100644 (file)
index 0000000..4d70109
--- /dev/null
@@ -0,0 +1,261 @@
+/*     $NetBSD: queue.h,v 1.1.1.2 2008/05/18 14:31:23 aymeric Exp $ */
+
+/* 
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)queue.h     8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef        _SYS_QUEUE_H_
+#define        _SYS_QUEUE_H_
+
+/*
+ * This file defines three types of data structures: lists, tail queues,
+ * and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may only be traversed in the forward direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)                                          \
+struct name {                                                          \
+       struct type *lh_first;  /* first element */                     \
+}
+
+#define LIST_ENTRY(type)                                               \
+struct {                                                               \
+       struct type *le_next;   /* next element */                      \
+       struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * List functions.
+ */
+#define        LIST_INIT(head) {                                               \
+       (head)->lh_first = NULL;                                        \
+}
+
+#define LIST_INSERT_AFTER(listelm, elm, field) {                       \
+       if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
+               (listelm)->field.le_next->field.le_prev =               \
+                   &(elm)->field.le_next;                              \
+       (listelm)->field.le_next = (elm);                               \
+       (elm)->field.le_prev = &(listelm)->field.le_next;               \
+}
+
+#define        LIST_INSERT_BEFORE(listelm, elm, field) {                       \
+       (elm)->field.le_prev = (listelm)->field.le_prev;                \
+       (elm)->field.le_next = (listelm);                               \
+       *(listelm)->field.le_prev = (elm);                              \
+       (listelm)->field.le_prev = &(elm)->field.le_next;               \
+}
+
+#define LIST_INSERT_HEAD(head, elm, field) {                           \
+       if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
+               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+       (head)->lh_first = (elm);                                       \
+       (elm)->field.le_prev = &(head)->lh_first;                       \
+}
+
+#define LIST_REMOVE(elm, field) {                                      \
+       if ((elm)->field.le_next != NULL)                               \
+               (elm)->field.le_next->field.le_prev =                   \
+                   (elm)->field.le_prev;                               \
+       *(elm)->field.le_prev = (elm)->field.le_next;                   \
+}
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)                                         \
+struct name {                                                          \
+       struct type *tqh_first; /* first element */                     \
+       struct type **tqh_last; /* addr of last next element */         \
+}
+
+#define TAILQ_ENTRY(type)                                              \
+struct {                                                               \
+       struct type *tqe_next;  /* next element */                      \
+       struct type **tqe_prev; /* address of previous next element */  \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define        TAILQ_INIT(head) {                                              \
+       (head)->tqh_first = NULL;                                       \
+       (head)->tqh_last = &(head)->tqh_first;                          \
+}
+
+#define TAILQ_INSERT_HEAD(head, elm, field) {                          \
+       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
+               (head)->tqh_first->field.tqe_prev =                     \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (head)->tqh_first = (elm);                                      \
+       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
+}
+
+#define TAILQ_INSERT_TAIL(head, elm, field) {                          \
+       (elm)->field.tqe_next = NULL;                                   \
+       (elm)->field.tqe_prev = (head)->tqh_last;                       \
+       *(head)->tqh_last = (elm);                                      \
+       (head)->tqh_last = &(elm)->field.tqe_next;                      \
+}
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) {                        \
+       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (listelm)->field.tqe_next = (elm);                              \
+       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
+}
+
+#define        TAILQ_INSERT_BEFORE(listelm, elm, field) {                      \
+       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+       (elm)->field.tqe_next = (listelm);                              \
+       *(listelm)->field.tqe_prev = (elm);                             \
+       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
+}
+
+#define TAILQ_REMOVE(head, elm, field) {                               \
+       if (((elm)->field.tqe_next) != NULL)                            \
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   (elm)->field.tqe_prev;                              \
+       else                                                            \
+               (head)->tqh_last = (elm)->field.tqe_prev;               \
+       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
+}
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)                                       \
+struct name {                                                          \
+       struct type *cqh_first;         /* first element */             \
+       struct type *cqh_last;          /* last element */              \
+}
+
+#define CIRCLEQ_ENTRY(type)                                            \
+struct {                                                               \
+       struct type *cqe_next;          /* next element */              \
+       struct type *cqe_prev;          /* previous element */          \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define        CIRCLEQ_INIT(head) {                                            \
+       (head)->cqh_first = (void *)(head);                             \
+       (head)->cqh_last = (void *)(head);                              \
+}
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {              \
+       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
+       (elm)->field.cqe_prev = (listelm);                              \
+       if ((listelm)->field.cqe_next == (void *)(head))                \
+               (head)->cqh_last = (elm);                               \
+       else                                                            \
+               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
+       (listelm)->field.cqe_next = (elm);                              \
+}
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {             \
+       (elm)->field.cqe_next = (listelm);                              \
+       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
+       if ((listelm)->field.cqe_prev == (void *)(head))                \
+               (head)->cqh_first = (elm);                              \
+       else                                                            \
+               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
+       (listelm)->field.cqe_prev = (elm);                              \
+}
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) {                                \
+       (elm)->field.cqe_next = (head)->cqh_first;                      \
+       (elm)->field.cqe_prev = (void *)(head);                         \
+       if ((head)->cqh_last == (void *)(head))                         \
+               (head)->cqh_last = (elm);                               \
+       else                                                            \
+               (head)->cqh_first->field.cqe_prev = (elm);              \
+       (head)->cqh_first = (elm);                                      \
+}
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) {                                \
+       (elm)->field.cqe_next = (void *)(head);                         \
+       (elm)->field.cqe_prev = (head)->cqh_last;                       \
+       if ((head)->cqh_first == (void *)(head))                        \
+               (head)->cqh_first = (elm);                              \
+       else                                                            \
+               (head)->cqh_last->field.cqe_next = (elm);               \
+       (head)->cqh_last = (elm);                                       \
+}
+
+#define        CIRCLEQ_REMOVE(head, elm, field) {                              \
+       if ((elm)->field.cqe_next == (void *)(head))                    \
+               (head)->cqh_last = (elm)->field.cqe_prev;               \
+       else                                                            \
+               (elm)->field.cqe_next->field.cqe_prev =                 \
+                   (elm)->field.cqe_prev;                              \
+       if ((elm)->field.cqe_prev == (void *)(head))                    \
+               (head)->cqh_first = (elm)->field.cqe_next;              \
+       else                                                            \
+               (elm)->field.cqe_prev->field.cqe_next =                 \
+                   (elm)->field.cqe_next;                              \
+}
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/dist/nvi/ip/extern.h b/dist/nvi/ip/extern.h
new file mode 100644 (file)
index 0000000..932bb29
--- /dev/null
@@ -0,0 +1,33 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:24 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int ip_waddstr __P((SCR *, const CHAR_T *, size_t));
+int ip_addstr __P((SCR *, const char *, size_t));
+int ip_attr __P((SCR *, scr_attr_t, int));
+int ip_baud __P((SCR *, u_long *));
+int ip_bell __P((SCR *));
+void ip_busy __P((SCR *, const char *, busy_t));
+int ip_child __P((SCR *));
+int ip_clrtoeol __P((SCR *));
+int ip_cursor __P((SCR *, size_t *, size_t *));
+int ip_deleteln __P((SCR *));
+int ip_discard __P((SCR *, SCR **));
+int ip_ex_adjust __P((SCR *, exadj_t));
+int ip_insertln __P((SCR *));
+int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+int ip_move __P((SCR *, size_t, size_t));
+void ip_msg __P((SCR *, mtype_t, char *, size_t));
+int ip_refresh __P((SCR *, int));
+int ip_rename __P((SCR *, char *, int));
+int ip_reply __P((SCR *, int, char *));
+int ip_split __P((SCR *, SCR *));
+int ip_suspend __P((SCR *, int *));
+void ip_usage __P((void));
+int ip_event __P((SCR *, EVENT *, u_int32_t, int));
+int ip_wevent __P((WIN *, SCR *, EVENT *, u_int32_t, int));
+int ip_screen __P((SCR *, u_int32_t));
+int ip_quit __P((WIN *));
+int ip_term_init __P((SCR *));
+int ip_term_end __P((GS *));
+int ip_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+int ip_optchange __P((SCR *, int, char *, u_long *));
diff --git a/dist/nvi/ip/ip_funcs.c b/dist/nvi/ip/ip_funcs.c
new file mode 100644 (file)
index 0000000..be381f1
--- /dev/null
@@ -0,0 +1,522 @@
+/*     $NetBSD: ip_funcs.c,v 1.1.1.2 2008/05/18 14:31:24 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_funcs.c,v 8.23 2001/06/25 15:19:23 skimo Exp (Berkeley) Date: 2001/06/25 15:19:23";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "../ipc/ip.h"
+#include "extern.h"
+
+/*
+ * ip_addstr --
+ *     Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int ip_waddstr __P((SCR *, const CHAR_T *, size_t));
+ */
+int
+ip_waddstr(SCR *sp, const CHAR_T *str, size_t len)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp;
+       int iv, rval;
+
+       ipp = IPP(sp);
+
+       ipb.code = SI_WADDSTR;
+       ipb.len1 = len * sizeof(CHAR_T);
+       ipb.str1 = (char *)str;
+       rval = vi_send(ipp->o_fd, "a", &ipb);
+       /* XXXX */
+       ipp->col += len;
+
+       return (rval);
+}
+
+/*
+ * ip_addstr --
+ *     Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
+ */
+int
+ip_addstr(SCR *sp, const char *str, size_t len)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp;
+       int iv, rval;
+
+       ipp = IPP(sp);
+
+       /*
+        * If ex isn't in control, it's the last line of the screen and
+        * it's a split screen, use inverse video.
+        */
+       iv = 0;
+       if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
+           ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
+               iv = 1;
+               ip_attr(sp, SA_INVERSE, 1);
+       }
+       ipb.code = SI_ADDSTR;
+       ipb.len1 = len;
+       ipb.str1 = str;
+       rval = vi_send(ipp->o_fd, "a", &ipb);
+       /* XXXX */
+       ipp->col += len;
+
+       if (iv)
+               ip_attr(sp, SA_INVERSE, 0);
+       return (rval);
+}
+
+/*
+ * ip_attr --
+ *     Toggle a screen attribute on/off.
+ *
+ * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
+ */
+int
+ip_attr(SCR *sp, scr_attr_t attribute, int on)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       if (attribute == SA_ALTERNATE) {
+               if (on) F_SET(ipp, IP_ON_ALTERNATE);
+               else F_CLR(ipp, IP_ON_ALTERNATE);
+       }
+
+       ipb.code = SI_ATTRIBUTE;
+       ipb.val1 = attribute;
+       ipb.val2 = on;
+
+       return (vi_send(ipp->o_fd, "12", &ipb));
+}
+
+/*
+ * ip_baud --
+ *     Return the baud rate.
+ *
+ * PUBLIC: int ip_baud __P((SCR *, u_long *));
+ */
+int
+ip_baud(SCR *sp, u_long *ratep)
+{
+       *ratep = 9600;          /* XXX: Translation: fast. */
+       return (0);
+}
+
+/*
+ * ip_bell --
+ *     Ring the bell/flash the screen.
+ *
+ * PUBLIC: int ip_bell __P((SCR *));
+ */
+int
+ip_bell(SCR *sp)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       ipb.code = SI_BELL;
+
+       return (vi_send(ipp->o_fd, NULL, &ipb));
+}
+
+/*
+ * ip_busy --
+ *     Display a busy message.
+ *
+ * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
+ */
+void
+ip_busy(SCR *sp, const char *str, busy_t bval)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       switch (bval) {
+       case BUSY_ON:
+               ipb.code = SI_BUSY_ON;
+               ipb.str1 = str;
+               ipb.len1 = strlen(str);
+               (void)vi_send(ipp->o_fd, "a", &ipb);
+               break;
+       case BUSY_OFF:
+               ipb.code = SI_BUSY_OFF;
+               (void)vi_send(ipp->o_fd, NULL, &ipb);
+               break;
+       case BUSY_UPDATE:
+               break;
+       }
+       return;
+}
+
+/*
+ * ip_child --
+ *     Prepare child.
+ *
+ * PUBLIC: int ip_child __P((SCR *));
+ */
+int
+ip_child(SCR *sp)
+{
+       IP_PRIVATE *ipp = IPP(sp);
+
+       if (ipp->t_fd != -1) {
+           dup2(ipp->t_fd, 0);
+           dup2(ipp->t_fd, 1);
+           dup2(ipp->t_fd, 2);
+           close(ipp->t_fd);
+       }
+       return 0;
+}
+
+/*
+ * ip_clrtoeol --
+ *     Clear from the current cursor to the end of the line.
+ *
+ * PUBLIC: int ip_clrtoeol __P((SCR *));
+ */
+int
+ip_clrtoeol(SCR *sp)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+       /* Temporary hack until we can pass screen pointers
+        * or name screens
+        */
+       if (IS_VSPLIT(sp)) {
+               size_t x, y, spcnt;
+               IP_PRIVATE *ipp;
+               int error;
+               ipp = IPP(sp);
+               y = ipp->row;
+               x = ipp->col;
+               error = 0;
+               for (spcnt = sp->cols - x; 
+                    spcnt > 0 && ! error; --spcnt)
+                       error = ip_addstr(sp, " ", 1);
+               if (sp->coff == 0)
+                       error |= ip_addstr(sp, "|", 1);
+               error |= ip_move(sp, y, x);
+               return error;
+       }
+
+       ipb.code = SI_CLRTOEOL;
+
+       return (vi_send(ipp->o_fd, NULL, &ipb));
+}
+
+/*
+ * ip_cursor --
+ *     Return the current cursor position.
+ *
+ * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
+ */
+int
+ip_cursor(SCR *sp, size_t *yp, size_t *xp)
+{
+       IP_PRIVATE *ipp;
+
+       ipp = IPP(sp);
+       *yp = ipp->row;
+       *xp = ipp->col;
+       return (0);
+}
+
+/*
+ * ip_deleteln --
+ *     Delete the current line, scrolling all lines below it.
+ *
+ * PUBLIC: int ip_deleteln __P((SCR *));
+ */
+int
+ip_deleteln(SCR *sp)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       /*
+        * This clause is required because the curses screen uses reverse
+        * video to delimit split screens.  If the screen does not do this,
+        * this code won't be necessary.
+        *
+        * If the bottom line was in reverse video, rewrite it in normal
+        * video before it's scrolled.
+        */
+       if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
+               ipb.code = SI_REWRITE;
+               ipb.val1 = RLNO(sp, LASTLINE(sp));
+               if (vi_send(ipp->o_fd, "1", &ipb))
+                       return (1);
+       }
+
+       /*
+        * The bottom line is expected to be blank after this operation,
+        * and other screens must support that semantic.
+        */
+       ipb.code = SI_DELETELN;
+       return (vi_send(ipp->o_fd, NULL, &ipb));
+}
+
+/*
+ * ip_discard --
+ *     Discard a screen.
+ *
+ * PUBLIC: int ip_discard __P((SCR *, SCR **));
+ */
+int
+ip_discard(SCR *discardp, SCR **acquirep)
+{
+       return (0);
+}
+
+/* 
+ * ip_ex_adjust --
+ *     Adjust the screen for ex.
+ *
+ * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
+ */
+int
+ip_ex_adjust(SCR *sp, exadj_t action)
+{
+       abort();
+       /* NOTREACHED */
+}
+
+/*
+ * ip_insertln --
+ *     Push down the current line, discarding the bottom line.
+ *
+ * PUBLIC: int ip_insertln __P((SCR *));
+ */
+int
+ip_insertln(SCR *sp)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       ipb.code = SI_INSERTLN;
+
+       return (vi_send(ipp->o_fd, NULL, &ipb));
+}
+
+/*
+ * ip_keyval --
+ *     Return the value for a special key.
+ *
+ * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ */
+int
+ip_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep)
+{
+       /*
+        * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
+        * VWERASE is a 4BSD extension.
+        */
+       switch (val) {
+       case KEY_VEOF:
+               *dnep = '\004';         /* ^D */
+               break;
+       case KEY_VERASE:
+               *dnep = '\b';           /* ^H */
+               break;
+       case KEY_VKILL:
+               *dnep = '\025';         /* ^U */
+               break;
+#ifdef VWERASE
+       case KEY_VWERASE:
+               *dnep = '\027';         /* ^W */
+               break;
+#endif
+       default:
+               *dnep = 1;
+               break;
+       }
+       return (0);
+}
+
+/*
+ * ip_move --
+ *     Move the cursor.
+ *
+ * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
+ */
+int
+ip_move(SCR *sp, size_t lno, size_t cno)
+{
+       IP_PRIVATE *ipp;
+       IP_BUF ipb;
+
+       ipp = IPP(sp);
+       ipp->row = lno;
+       ipp->col = cno;
+
+       ipb.code = SI_MOVE;
+       ipb.val1 = RLNO(sp, lno);
+       ipb.val2 = RCNO(sp, cno);
+       return (vi_send(ipp->o_fd, "12", &ipb));
+}
+
+/*
+ * PUBLIC: void ip_msg __P((SCR *, mtype_t, char *, size_t));
+ */
+void
+ip_msg(SCR *sp, mtype_t mtype, char *line, size_t len)
+{
+       IP_PRIVATE *ipp = IPP(sp);
+
+       if (F_ISSET(ipp, IP_ON_ALTERNATE))
+               vs_msg(sp, mtype, line, len);
+       else {
+               write(ipp->t_fd, line, len);
+               F_CLR(sp, SC_EX_WAIT_NO);
+       }
+}
+
+/*
+ * ip_refresh --
+ *     Refresh the screen.
+ *
+ * PUBLIC: int ip_refresh __P((SCR *, int));
+ */
+int
+ip_refresh(SCR *sp, int repaint)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp;
+       db_recno_t total;
+
+       ipp = IPP(sp);
+
+       /*
+        * If the scroll bar information has changed since we last sent
+        * it, resend it.  Currently, we send three values:
+        *
+        * top          The line number of the first line in the screen.
+        * num          The number of lines visible on the screen.
+        * total        The number of lines in the file.
+        *
+        * XXX
+        * This is a gross violation of layering... we're looking at data
+        * structures at which we have absolutely no business whatsoever
+        * looking...
+        */
+       ipb.val1 = HMAP->lno;
+       ipb.val2 = TMAP->lno - HMAP->lno;
+       if (sp->ep != NULL && sp->ep->db != NULL)
+               (void)db_last(sp, &total);
+       ipb.val3 = total == 0 ? 1 : total;
+       if (ipb.val1 != ipp->sb_top ||
+           ipb.val2 != ipp->sb_num || ipb.val3 != ipp->sb_total) {
+               ipb.code = SI_SCROLLBAR;
+               (void)vi_send(ipp->o_fd, "123", &ipb);
+               ipp->sb_top = ipb.val1;
+               ipp->sb_num = ipb.val2;
+               ipp->sb_total = ipb.val3;
+       }
+
+       /* Refresh/repaint the screen. */
+       ipb.code = repaint ? SI_REDRAW : SI_REFRESH;
+       return (vi_send(ipp->o_fd, NULL, &ipb));
+}
+
+/*
+ * ip_rename --
+ *     Rename the file.
+ *
+ * PUBLIC: int ip_rename __P((SCR *, char *, int));
+ */
+int
+ip_rename(SCR *sp, char *name, int on)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       ipb.code = SI_RENAME;
+       ipb.str1 = name;
+       ipb.len1 = name ? strlen(name) : 0;
+       return (vi_send(ipp->o_fd, "a", &ipb));
+}
+
+/*
+ * ip_reply --
+ *     Reply to a message.
+ *
+ * PUBLIC: int ip_reply __P((SCR *, int, char *));
+ */
+int
+ip_reply(SCR *sp, int status, char *msg)
+{
+       IP_BUF ipb;
+       IP_PRIVATE *ipp = IPP(sp);
+
+       ipb.code = SI_REPLY;
+       ipb.val1 = status;
+       ipb.str1 = msg == NULL ? "" : msg;
+       ipb.len1 = strlen(ipb.str1);
+       return (vi_send(ipp->o_fd, "1a", &ipb));
+}
+
+/*
+ * ip_split --
+ *     Split a screen.
+ *
+ * PUBLIC: int ip_split __P((SCR *, SCR *));
+ */
+int
+ip_split(SCR *origp, SCR *newp)
+{
+       return (0);
+}
+
+/*
+ * ip_suspend --
+ *     Suspend a screen.
+ *
+ * PUBLIC: int ip_suspend __P((SCR *, int *));
+ */
+int
+ip_suspend(SCR *sp, int *allowedp)
+{
+       *allowedp = 0;
+       return (0);
+}
+
+/*      
+ * ip_usage --
+ *      Print out the ip usage messages.
+ *
+ * PUBLIC: void ip_usage __P((void));
+ */
+void    
+ip_usage(void)
+{       
+#define USAGE "\
+usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
+        (void)fprintf(stderr, "%s", USAGE);
+#undef  USAGE
+}
diff --git a/dist/nvi/ip/ip_main.c b/dist/nvi/ip/ip_main.c
new file mode 100644 (file)
index 0000000..5bb749e
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $NetBSD: ip_main.c,v 1.2 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_main.c,v 8.24 2001/07/29 19:07:30 skimo Exp (Berkeley) Date: 2001/07/29 19:07:30";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/uio.h>
+
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "extern.h"
+
+GS *__global_list;                             /* GLOBAL: List of screens. */
+
+static void       ip_func_std __P((WIN *));
+static IP_PRIVATE *ip_init __P((WIN *wp, int i_fd, int o_fd, int, int argc, char *argv[]));
+static void       perr __P((char *, char *));
+static int        get_fds __P((char *ip_arg, int *i_fd, int *o_fd));
+static int  get_connection __P((WIN *wp, int main_ifd, int main_ofd, 
+                               int *i_fd, int *o_fd, int *, int can_pass));
+static void *run_editor __P((void * vp));
+
+/*
+ * ip_main --
+ *      This is the main loop for the vi-as-library editor.
+ */
+int
+main(int argc, char **argv)
+{
+       IP_PRIVATE *ipp;
+       int rval;
+       char *ip_arg;
+       char **p_av, **t_av;
+       GS *gp;
+       WIN *wp;
+       int i_fd, o_fd, t_fd, main_ifd, main_ofd;
+
+       /* Create and initialize the global structure. */
+       __global_list = gp = gs_init(argv[0]);
+
+       /*
+        * Strip out any arguments that vi isn't going to understand.  There's
+        * no way to portably call getopt twice, so arguments parsed here must
+        * be removed from the argument list.
+        */
+       ip_arg = NULL;
+       for (p_av = t_av = argv;;) {
+               if (*t_av == NULL) {
+                       *p_av = NULL;
+                       break;
+               }
+               if (!strcmp(*t_av, "--")) {
+                       while ((*p_av++ = *t_av++) != NULL);
+                       break;
+               }
+               if (!memcmp(*t_av, "-I", sizeof("-I") - 1)) {
+                       if (t_av[0][2] != '\0') {
+                               ip_arg = t_av[0] + 2;
+                               ++t_av;
+                               --argc;
+                               continue;
+                       }
+                       else if (t_av[1] != NULL) {
+                               ip_arg = t_av[1];
+                               t_av += 2;
+                               argc -= 2;
+                               continue;
+                       }
+               }
+               *p_av++ = *t_av++;
+       }
+
+       if (get_fds(ip_arg, &main_ifd, &main_ofd))
+               return 1;
+
+       wp = NULL;
+
+       while (get_connection(wp, main_ifd, main_ofd, &i_fd, &o_fd, &t_fd, 1) == 0) {
+               /* Create new window */
+               wp = gs_new_win(gp);
+
+               /* Create and partially initialize the IP structure. */
+               if ((ipp = ip_init(wp, i_fd, o_fd, t_fd, argc, argv)) == NULL)
+                       return (1);
+
+               gp->run(wp, run_editor, (void *)wp);
+       }
+
+       /* Clean out the global structure. */
+       gs_end(gp);
+
+       /* Free the global and IP private areas. */
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+       free(gp);
+#endif
+       exit (rval);
+}
+
+static void *
+run_editor(void * vp)
+{
+       GS *gp;
+       IP_PRIVATE *ipp;
+       WIN *wp;
+       EVENT ev;
+       int rval;
+       IP_BUF ipb;
+
+       wp = (WIN *) vp;
+       gp = wp->gp;
+       ipp = wp->ip_private;
+
+       /* Add the terminal type to the global structure. */
+       if ((OG_D_STR(gp, GO_TERM) =
+           OG_STR(gp, GO_TERM) = strdup("ip_curses")) == NULL)
+               perr(gp->progname, NULL);
+
+       /*
+        * Figure out how big the screen is -- read events until we get
+        * the rows and columns.
+        */
+       for (;;) {
+               if (ip_wevent(wp, NULL, &ev, 0, 0))
+                       return;
+               if (ev.e_event == E_WRESIZE)
+                       break;
+               if (ev.e_event == E_EOF || ev.e_event == E_ERR ||
+                   ev.e_event == E_SIGHUP || ev.e_event == E_SIGTERM)
+                       return;
+               if (ev.e_event == E_IPCOMMAND && ev.e_ipcom == VI_QUIT)
+                       return;
+       }
+
+       /* Run ex/vi. */
+       rval = editor(wp, ipp->argc, ipp->argv);
+
+       /* Clean up the screen. */
+       (void)ip_quit(wp);
+
+       /* Send the quit message. */
+       ipb.code = SI_QUIT;
+       (void)vi_send(ipp->o_fd, NULL, &ipb);
+
+       /* Give the screen a couple of seconds to deal with it. */
+       sleep(2);
+
+       /* Remove window; correct place ? */
+       win_end(wp);
+
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+       free(ipp);
+#endif
+       return NULL;
+}
+
+/*
+ * ip_init --
+ *     Create and partially initialize the GS structure.
+ */
+static IP_PRIVATE *
+ip_init(WIN *wp, int i_fd, int o_fd, int t_fd, int argc, char *argv[])
+{
+       IP_PRIVATE *ipp;
+
+       /* Allocate the IP private structure. */
+       CALLOC_NOMSG(NULL, ipp, IP_PRIVATE *, 1, sizeof(IP_PRIVATE));
+       if (ipp == NULL)
+               perr(wp->gp->progname,  NULL);
+       wp->ip_private = ipp;
+
+       ipp->i_fd = i_fd;
+       ipp->o_fd = o_fd;
+       ipp->t_fd = t_fd;
+       ipp->argc = argc;
+       ipp->argv = argv;
+       /* Initialize the list of ip functions. */
+       ip_func_std(wp);
+
+       return (ipp);
+}
+
+static int
+get_fds(char *ip_arg, int *i_fd, int *o_fd)
+{
+       char *ep;
+
+       /*
+        * Crack ip_arg -- it's of the form #.#, where the first number is the
+        * file descriptor from the screen, the second is the file descriptor
+        * to the screen.
+        */
+       if (!ip_arg || !isdigit((unsigned char)ip_arg[0]))
+               goto usage;
+       *i_fd = strtol(ip_arg, &ep, 10);
+       if (ep[0] != '.' || !isdigit((unsigned char)ep[1]))
+               goto usage;
+       *o_fd = strtol(++ep, &ep, 10);
+       if (ep[0] != '\0') {
+usage:         ip_usage();
+               return 1;
+       }
+
+       return 0;
+}
+
+static int
+get_connection(WIN *wp, int main_ifd, int main_ofd, 
+       int *i_fd, int *o_fd, int *t_fd, int can_pass)
+{
+    *t_fd = -1;
+
+    if (!can_pass) {
+       if (wp == NULL) {                   /* First call */
+           *i_fd = main_ifd;
+           *o_fd = main_ofd;
+       } else {
+           return 1;
+       }
+    } else {
+       struct msghdr   mh;
+       IPCMSGHDR           ch;
+       char        dummy;
+       struct iovec    iov;
+
+       mh.msg_namelen = 0;
+       mh.msg_iovlen = 1;
+       mh.msg_iov = &iov;
+       mh.msg_controllen = sizeof(ch);
+       mh.msg_control = (void *)&ch;
+
+       iov.iov_len = 1;
+       iov.iov_base = &dummy;
+
+       if (recvmsg(main_ifd, &mh, 0) != 1)
+           return 1;
+       *i_fd = *(int *)CMSG_DATA(&ch.header);
+       if (recvmsg(*i_fd, &mh, 0) != 1)
+           return 1;
+       *o_fd = *(int *)CMSG_DATA(&ch.header);
+       if (dummy == 'F') {
+           if (recvmsg(*i_fd, &mh, 0) != 1)
+               return 1;
+           *t_fd = *(int *)CMSG_DATA(&ch.header);
+       }
+    }
+
+    return 0;
+}
+
+/*
+ * ip_func_std --
+ *     Initialize the standard ip functions.
+ */
+static void
+ip_func_std(WIN *wp)
+{
+       GS *gp;
+
+       gp = wp->gp;
+
+       gp->scr_addstr = ip_addstr;
+       gp->scr_waddstr = ip_waddstr;
+       gp->scr_attr = ip_attr;
+       gp->scr_baud = ip_baud;
+       gp->scr_bell = ip_bell;
+       gp->scr_busy = ip_busy;
+       gp->scr_child = ip_child;
+       gp->scr_clrtoeol = ip_clrtoeol;
+       gp->scr_cursor = ip_cursor;
+       gp->scr_deleteln = ip_deleteln;
+       gp->scr_discard = ip_discard;
+       gp->scr_event = ip_event;
+       gp->scr_ex_adjust = ip_ex_adjust;
+       gp->scr_fmap = ip_fmap;
+       gp->scr_insertln = ip_insertln;
+       gp->scr_keyval = ip_keyval;
+       gp->scr_move = ip_move;
+       wp->scr_msg = ip_msg;
+       gp->scr_optchange = ip_optchange;
+       gp->scr_refresh = ip_refresh;
+       gp->scr_rename = ip_rename;
+       gp->scr_reply = ip_reply;
+       gp->scr_screen = ip_screen;
+       gp->scr_split = ip_split;
+       gp->scr_suspend = ip_suspend;
+       gp->scr_usage = ip_usage;
+}
+
+/*
+ * perr --
+ *     Print system error.
+ */
+static void
+perr(char *name, char *msg)
+{
+       (void)fprintf(stderr, "%s:", name);
+       if (msg != NULL)
+               (void)fprintf(stderr, "%s:", msg);
+       (void)fprintf(stderr, "%s\n", strerror(errno));
+       exit(1);
+}
diff --git a/dist/nvi/ip/ip_read.c b/dist/nvi/ip/ip_read.c
new file mode 100644 (file)
index 0000000..1bbc5b5
--- /dev/null
@@ -0,0 +1,387 @@
+/*     $NetBSD: ip_read.c,v 1.1.1.2 2008/05/18 14:31:24 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_read.c,v 8.23 2001/06/25 15:19:24 skimo Exp (Berkeley) Date: 2001/06/25 15:19:24";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include "../common/common.h"
+#include "../ex/script.h"
+#include "../ipc/ip.h"
+#include "extern.h"
+
+extern GS *__global_list;
+
+VIPFUNLIST const vipfuns[] = {
+/* VI_C_BOL        Cursor to start of line. */
+    {"",    E_IPCOMMAND},
+/* VI_C_BOTTOM  2      /* Cursor to bottom. */
+    {"",    E_IPCOMMAND},
+/* VI_C_DEL     3      /* Cursor delete. */
+    {"",    E_IPCOMMAND},
+/* VI_C_DOWN       Cursor down N lines: IPO_INT. */
+    {"1",   E_IPCOMMAND},
+/* VI_C_EOL     5      /* Cursor to end of line. */
+    {"",    E_IPCOMMAND},
+/* VI_C_INSERT  6      /* Cursor: enter insert mode. */
+    {"",    E_IPCOMMAND},
+/* VI_C_LEFT    7      /* Cursor left. */
+    {"",    E_IPCOMMAND},
+/* VI_C_PGDOWN  8      /* Cursor down N pages: IPO_INT. */
+    {"1",   E_IPCOMMAND},
+/* VI_C_PGUP    9      /* Cursor up N lines: IPO_INT. */
+    {"1",   E_IPCOMMAND},
+/* VI_C_RIGHT  10      /* Cursor right. */
+    {"",    E_IPCOMMAND},
+/* VI_C_SEARCH 11      /* Cursor: search: IPO_INT, IPO_STR. */
+    {"a1",  E_IPCOMMAND},
+/* VI_C_SETTOP 12      /* Cursor: set screen top line: IPO_INT. */
+    {"1",   E_IPCOMMAND},
+/* VI_C_TOP    13      /* Cursor to top. */
+    {"",    E_IPCOMMAND},
+/* VI_C_UP             14      /* Cursor up N lines: IPO_INT. */
+    {"1",   E_IPCOMMAND},
+/* VI_EDIT             15      /* Edit a file: IPO_STR. */
+    {"a",   E_IPCOMMAND},
+/* VI_EDITOPT  16      /* Edit option: 2 * IPO_STR, IPO_INT. */
+    {"ab1", E_IPCOMMAND},
+/* VI_EDITSPLIT        17      /* Split to a file: IPO_STR. */
+    {"a",   E_IPCOMMAND},
+/* VI_EOF              18      /* End of input (NOT ^D). */
+    {"",    E_EOF},
+/* VI_ERR              19      /* Input error. */
+    {"",    E_ERR},
+/* VI_FLAGS        Flags */
+    {"1",   E_FLAGS},
+/* VI_INTERRUPT        20      /* Interrupt. */
+    {"",    E_INTERRUPT},
+/* VI_MOUSE_MOVE       21      /* Mouse click move: IPO_INT, IPO_INT. */
+    {"12",  E_IPCOMMAND},
+/* VI_QUIT             22      /* Quit. */
+    {"",    E_IPCOMMAND},
+/* VI_RESIZE       Screen resize: IPO_INT, IPO_INT. */
+    {"12",  E_WRESIZE},
+/* VI_SEL_END  24      /* Select end: IPO_INT, IPO_INT. */
+    {"12",  E_IPCOMMAND},
+/* VI_SEL_START        25      /* Select start: IPO_INT, IPO_INT. */
+    {"12",  E_IPCOMMAND},
+/* VI_SIGHUP   26      /* SIGHUP. */
+    {"",    E_SIGHUP},
+/* VI_SIGTERM  27      /* SIGTERM. */
+    {"",    E_SIGTERM},
+/* VI_STRING       Input string: IPO_STR. */
+    {"a",   E_STRING},
+/* VI_TAG              29      /* Tag. */
+    {"",    E_IPCOMMAND},
+/* VI_TAGAS    30      /* Tag to a string: IPO_STR. */
+    {"a",   E_IPCOMMAND},
+/* VI_TAGSPLIT 31      /* Split to a tag. */
+    {"",    E_IPCOMMAND},
+/* VI_UNDO             32      /* Undo. */
+    {"",    E_IPCOMMAND},
+/* VI_WQ               33      /* Write and quit. */
+    {"",    E_IPCOMMAND},
+/* VI_WRITE    34      /* Write. */
+    {"",    E_IPCOMMAND},
+/* VI_WRITEAS  35      /* Write as another file: IPO_STR. */
+    {"a",   E_IPCOMMAND},
+/* VI_EVENT_SUP */
+};
+
+typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t;
+
+static input_t ip_read __P((SCR *, IP_PRIVATE *, struct timeval *, int, int*));
+static int     ip_resize __P((SCR *, u_int32_t, u_int32_t));
+static int     ip_trans __P((SCR *, IP_PRIVATE *, EVENT *));
+
+/*
+ * ip_event --
+ *     Return a single event.
+ *
+ * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
+ */
+int
+ip_event(SCR *sp, EVENT *evp, u_int32_t flags, int ms)
+{
+       return ip_wevent(sp->wp, sp, evp, flags, ms);
+}
+
+/*
+ * XXX probably better to require new_window to send size
+ *     so we never have to call ip_wevent with sp == NULL
+ *
+ * ip_wevent --
+ *     Return a single event.
+ *
+ * PUBLIC: int ip_wevent __P((WIN *, SCR *, EVENT *, u_int32_t, int));
+ */
+int
+ip_wevent(WIN *wp, SCR *sp, EVENT *evp, u_int32_t flags, int ms)
+{
+       IP_PRIVATE *ipp;
+       struct timeval t, *tp;
+       int termread;
+       int nr;
+
+       if (LF_ISSET(EC_INTERRUPT)) {           /* XXX */
+               evp->e_event = E_TIMEOUT;
+               return (0);
+       }
+
+       ipp = sp == NULL ? WIPP(wp) : IPP(sp);
+
+       /* Discard the last command. */
+       if (ipp->iskip != 0) {
+               ipp->iblen -= ipp->iskip;
+               memmove(ipp->ibuf, ipp->ibuf + ipp->iskip, ipp->iblen);
+               ipp->iskip = 0;
+       }
+
+       termread = F_ISSET(ipp, IP_IN_EX) ||
+                   (sp && F_ISSET(sp, SC_SCR_EXWROTE));
+
+       /* Process possible remaining commands */
+       if (!termread && ipp->iblen >= IPO_CODE_LEN && ip_trans(sp, ipp, evp))
+               return 0;
+
+       /* Set timer. */
+       if (ms == 0)
+               tp = NULL;
+       else {
+               t.tv_sec = ms / 1000;
+               t.tv_usec = (ms % 1000) * 1000;
+               tp = &t;
+       }
+
+       /* Read input events. */
+       for (;;) {
+               switch (ip_read(sp, ipp, tp, termread, &nr)) {
+               case INP_OK:
+                       if (termread) {
+                               evp->e_csp = ipp->tbuf;
+                               evp->e_len = nr;
+                               evp->e_event = E_STRING;
+                       } else if (!ip_trans(sp, ipp, evp))
+                               continue;
+                       break;
+               case INP_EOF:
+                       evp->e_event = E_EOF;
+                       break;
+               case INP_ERR:
+                       evp->e_event = E_ERR;
+                       break;
+               case INP_TIMEOUT:
+                       evp->e_event = E_TIMEOUT;
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       }
+       return (0);
+}
+
+/*
+ * ip_read --
+ *     Read characters from the input.
+ */
+static input_t
+ip_read(SCR *sp, IP_PRIVATE *ipp, struct timeval *tp, int termread, int *nr)
+{
+       struct timeval poll;
+       GS *gp;
+       fd_set rdfd;
+       input_t rval;
+       size_t blen;
+       int maxfd;
+       char *bp;
+       int fd;
+       CHAR_T *wp;
+       size_t wlen;
+
+       gp = sp == NULL ? __global_list : sp->gp;
+       bp = ipp->ibuf + ipp->iblen;
+       blen = sizeof(ipp->ibuf) - ipp->iblen;
+       fd = termread ? ipp->t_fd : ipp->i_fd;
+
+       /*
+        * 1: A read with an associated timeout, e.g., trying to complete
+        *    a map sequence.  If input exists, we fall into #2.
+        */
+       FD_ZERO(&rdfd);
+       poll.tv_sec = 0;
+       poll.tv_usec = 0;
+       if (tp != NULL) {
+               FD_SET(fd, &rdfd);
+               switch (select(fd + 1,
+                   &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
+               case 0:
+                       return (INP_TIMEOUT);
+               case -1:
+                       goto err;
+               default:
+                       break;
+               }
+       }
+       
+       /*
+        * 2: Wait for input.
+        *
+        * Select on the command input and scripting window file descriptors.
+        * It's ugly that we wait on scripting file descriptors here, but it's
+        * the only way to keep from locking out scripting windows.
+        */
+       if (sp != NULL && F_ISSET(gp, G_SCRWIN)) {
+               FD_ZERO(&rdfd);
+               FD_SET(fd, &rdfd);
+               maxfd = fd;
+               if (sscr_check_input(sp, &rdfd, maxfd))
+                       goto err;
+       }
+
+       /*
+        * 3: Read the input.
+        */
+       switch (*nr = read(fd, termread ? (char *)ipp->tbuf : bp, 
+                             termread ? sizeof(ipp->tbuf)/sizeof(CHAR_T) 
+                                      : blen)) {
+       case  0:                                /* EOF. */
+               rval = INP_EOF;
+               break;
+       case -1:                                /* Error or interrupt. */
+err:           rval = INP_ERR;
+               msgq(sp, M_SYSERR, "input");
+               break;
+       default:                                /* Input characters. */
+               if (!termread) ipp->iblen += *nr;
+               else {
+                       CHAR2INT(sp, (char *)ipp->tbuf, *nr, wp, wlen);
+                       MEMMOVEW(ipp->tbuf, wp, wlen);
+               }
+               rval = INP_OK;
+               break;
+       }
+       return (rval);
+}
+
+/*
+ * ip_trans --
+ *     Translate messages into events.
+ */
+static int
+ip_trans(SCR *sp, IP_PRIVATE *ipp, EVENT *evp)
+{
+       u_int32_t skip, val;
+       char *fmt;
+       CHAR_T *wp;
+       size_t wlen;
+
+       if (ipp->ibuf[0] == CODE_OOB ||
+           ipp->ibuf[0] >= VI_EVENT_SUP)
+       {
+               /*
+                * XXX: Protocol is out of sync?
+                */
+               abort();
+       }
+       fmt = vipfuns[ipp->ibuf[0]-1].format;
+       evp->e_event = vipfuns[ipp->ibuf[0]-1].e_event;
+       evp->e_ipcom = ipp->ibuf[0];
+
+       for (skip = IPO_CODE_LEN; *fmt != '\0'; ++fmt)
+               switch (*fmt) {
+               case '1':
+               case '2':
+                       if (ipp->iblen < skip + IPO_INT_LEN)
+                               return (0);
+                       memcpy(&val, ipp->ibuf + skip, IPO_INT_LEN);
+                       val = ntohl(val);
+                       if (*fmt == '1')
+                               evp->e_val1 = val;
+                       else
+                               evp->e_val2 = val;
+                       skip += IPO_INT_LEN;
+                       break;
+               case 'a':
+               case 'b':
+                       if (ipp->iblen < skip + IPO_INT_LEN)
+                               return (0);
+                       memcpy(&val, ipp->ibuf + skip, IPO_INT_LEN);
+                       val = ntohl(val);
+                       skip += IPO_INT_LEN;
+                       if (ipp->iblen < skip + val)
+                               return (0);
+                       if (*fmt == 'a') {
+                               CHAR2INT(sp, ipp->ibuf + skip, val,
+                                        wp, wlen);
+                               MEMCPYW(ipp->tbuf, wp, wlen);
+                               evp->e_str1 = ipp->tbuf;
+                               evp->e_len1 = wlen;
+                       } else {
+                               CHAR2INT(sp, ipp->ibuf + skip, val,
+                                        wp, wlen);
+                               MEMCPYW(ipp->tbuf, wp, wlen);
+                               evp->e_str2 = ipp->tbuf;
+                               evp->e_len2 = wlen;
+                       }
+                       skip += val;
+                       break;
+               }
+
+       ipp->iskip = skip;
+
+       if (evp->e_event == E_WRESIZE)
+               (void)ip_resize(sp, evp->e_val1, evp->e_val2);
+
+       return (1);
+}
+
+/* 
+ * ip_resize --
+ *     Reset the options for a resize event.
+ */
+static int
+ip_resize(SCR *sp, u_int32_t lines, u_int32_t columns)
+{
+       GS *gp;
+       int rval;
+
+       /*
+        * XXX
+        * The IP screen has to know the lines and columns before anything
+        * else happens.  So, we may not have a valid SCR pointer, and we
+        * have to deal with that.
+        */
+       if (sp == NULL) {
+               gp = __global_list;
+               OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = lines;
+               OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = columns;
+               return (0);
+       }
+
+       rval = api_opts_set(sp, L("lines"), NULL, lines, 0);
+       if (api_opts_set(sp, L("columns"), NULL, columns, 0))
+               rval = 1;
+       return (rval);
+}
diff --git a/dist/nvi/ip/ip_screen.c b/dist/nvi/ip/ip_screen.c
new file mode 100644 (file)
index 0000000..39293f7
--- /dev/null
@@ -0,0 +1,95 @@
+/*     $NetBSD: ip_screen.c,v 1.1.1.2 2008/05/18 14:31:24 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_screen.c,v 8.8 2001/06/25 15:19:24 skimo Exp (Berkeley) Date: 2001/06/25 15:19:24";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "extern.h"
+
+/*
+ * ip_screen --
+ *     Initialize/shutdown the IP screen.
+ *
+ * PUBLIC: int ip_screen __P((SCR *, u_int32_t));
+ */
+int
+ip_screen(SCR *sp, u_int32_t flags)
+{
+       GS *gp;
+       IP_PRIVATE *ipp;
+
+       gp = sp->gp;
+       ipp = IPP(sp);
+
+       /* See if the current information is incorrect. */
+       if (F_ISSET(gp, G_SRESTART)) {
+               if (ip_quit(sp->wp))
+                       return (1);
+               F_CLR(gp, G_SRESTART);
+       }
+       
+       /* See if we're already in the right mode. */
+       if (LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX) ||
+           LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI))
+               return (0);
+
+       /* Ex isn't possible if there is no terminal. */
+       if (LF_ISSET(SC_EX) && ipp->t_fd == -1)
+               return (1);
+
+       if (F_ISSET(sp, SC_SCR_EX))
+               F_CLR(sp, SC_SCR_EX);
+
+       if (F_ISSET(sp, SC_SCR_VI))
+               F_CLR(sp, SC_SCR_VI);
+
+       if (LF_ISSET(SC_EX)) {
+               F_SET(ipp, IP_IN_EX);
+       } else {
+               /* Initialize terminal based information. */
+               if (ip_term_init(sp)) 
+                       return (1);
+
+               F_CLR(ipp, IP_IN_EX);
+               F_SET(ipp, IP_SCR_VI_INIT);
+       }
+       return (0);
+}
+
+/*
+ * ip_quit --
+ *     Shutdown the screens.
+ *
+ * PUBLIC: int ip_quit __P((WIN *));
+ */
+int
+ip_quit(WIN *wp)
+{
+       IP_PRIVATE *ipp;
+       int rval;
+
+       /* Clean up the terminal mappings. */
+       rval = ip_term_end(wp->gp);
+
+       ipp = WIPP(wp);
+       F_CLR(ipp, IP_SCR_VI_INIT);
+
+       return (rval);
+}
diff --git a/dist/nvi/ip/ip_term.c b/dist/nvi/ip/ip_term.c
new file mode 100644 (file)
index 0000000..5b3dcb7
--- /dev/null
@@ -0,0 +1,136 @@
+/*     $NetBSD: ip_term.c,v 1.1.1.2 2008/05/18 14:31:24 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_term.c,v 8.9 2001/06/25 15:19:24 skimo Exp (Berkeley) Date: 2001/06/25 15:19:24";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <string.h>
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "extern.h"
+
+/*
+ * ip_term_init --
+ *     Initialize the terminal special keys.
+ *
+ * PUBLIC: int ip_term_init __P((SCR *));
+ */
+int
+ip_term_init(SCR *sp)
+{
+       SEQ *qp;
+
+       /*
+        * Rework any function key mappings that were set before the
+        * screen was initialized.
+        */
+       for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
+               if (F_ISSET(qp, SEQ_FUNCMAP))
+                       (void)ip_fmap(sp, qp->stype,
+                           qp->input, qp->ilen, qp->output, qp->olen);
+       return (0);
+}
+
+/*
+ * ip_term_end --
+ *     End the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int ip_term_end __P((GS *));
+ */
+int
+ip_term_end(GS *gp)
+{
+       SEQ *qp, *nqp;
+
+       /* Delete screen specific mappings. */
+       for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
+               nqp = qp->q.le_next;
+               if (F_ISSET(qp, SEQ_SCREEN))
+                       (void)seq_mdel(qp);
+       }
+       return (0);
+}
+
+/*
+ * ip_fmap --
+ *     Map a function key.
+ *
+ * PUBLIC: int ip_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ */
+int
+ip_fmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
+{
+       /* Bind a function key to a string sequence. */
+       return (1);
+}
+
+/*
+ * ip_optchange --
+ *     IP screen specific "option changed" routine.
+ *
+ * PUBLIC: int ip_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+ip_optchange(SCR *sp, int offset, char *str, u_long *valp)
+{
+       IP_BUF ipb;
+       OPTLIST const *opt;
+       IP_PRIVATE *ipp = IPP(sp);
+       char *np;
+       size_t nlen;
+
+       switch (offset) {
+       case O_COLUMNS:
+       case O_LINES:
+               F_SET(sp->gp, G_SRESTART);
+               F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+               break;
+       case O_TERM:
+               /* Called with "ip_curses"; previously wasn't shown
+                * because switching to EX wasn't allowed
+               msgq(sp, M_ERR, "The screen type may not be changed");
+               */
+               return (1);
+       }
+
+       opt = optlist + offset;
+       switch (opt->type) {
+       case OPT_0BOOL:
+       case OPT_1BOOL:
+       case OPT_NUM:
+               ipb.val1 = *valp;
+               ipb.len2 = 0;
+               break;
+       case OPT_STR:
+               if (str == NULL) {
+                       ipb.str2 = "";
+                       ipb.len2 = 1;
+               } else {
+                       ipb.str2 = str;
+                       ipb.len2 = strlen(str) + 1;
+               }
+               break;
+       }
+
+       ipb.code = SI_EDITOPT;
+       ipb.str1 = (char*)opt->name;
+       ipb.len1 = STRLEN(opt->name) * sizeof(CHAR_T);
+
+       (void)vi_send(ipp->o_fd, "ab1", &ipb);
+       return (0);
+}
diff --git a/dist/nvi/ip/vipc.pl b/dist/nvi/ip/vipc.pl
new file mode 100644 (file)
index 0000000..c0d2a8d
--- /dev/null
@@ -0,0 +1,30 @@
+#      @(#)vipc.pl     10.1 (Berkeley) 6/8/95
+if (/^\/\* (VI_[0-9A-Z_]*)/) {
+       $cmd = $1;
+       $name = lc $1;
+       $_ = <>;
+       next unless /"([^"]*)"/;
+       @fpars = "IPVIWIN *ipvi";
+       @pars = $cmd;
+       for (split "", $1) {
+           if (/\d/) {
+               push @fpars, "u_int32_t val$_";
+               push @pars, "val$_";
+           }
+           if (/[a-z]/) {
+               push @fpars, "const char *str$_, u_int32_t len$_";
+               push @pars, "str$_, len$_";
+           }
+       }
+       $fpars = join ', ', @fpars;
+       $pars = join ', ', @pars;
+       print <<EOI
+static int
+$name($fpars)
+{
+       return vi_send_$1(ipvi, $pars);
+}
+
+EOI
+}
diff --git a/dist/nvi/ipc/extern.h b/dist/nvi/ipc/extern.h
new file mode 100644 (file)
index 0000000..8555dae
--- /dev/null
@@ -0,0 +1,9 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:25 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int vi_run __P((IPVI *, int, char *[]));
+int vi_send __P((int, char *, IP_BUF *));
+int vi_input __P((IPVIWIN *, int));
+int vi_wsend __P((IPVIWIN*, char *, IP_BUF *));
+int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *));
+int vi_create __P((IPVI **, u_int32_t));
diff --git a/dist/nvi/ipc/ip.h b/dist/nvi/ipc/ip.h
new file mode 100644 (file)
index 0000000..7223f10
--- /dev/null
@@ -0,0 +1,250 @@
+/*     $NetBSD: ip.h,v 1.1.1.2 2008/05/18 14:31:25 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: ip.h,v 8.29 2000/07/17 21:17:54 skimo Exp (Berkeley) Date: 2000/07/17 21:17:54
+ */
+
+#include <sys/socket.h>
+#include "ipc_def.h"
+
+typedef struct ipcmsghdr {
+       struct  cmsghdr header;
+       int     __room_for_fd;
+} IPCMSGHDR;
+
+struct _ip_vi_win;
+
+typedef struct _ip_private {
+       int      i_fd;          /* Input file descriptor. */
+       int      o_fd;          /* Output file descriptor. */
+       int      t_fd;          /* Terminal file descriptor. */
+
+       int      argc;
+       char    **argv;
+
+       size_t   row;           /* Current row. */
+       size_t   col;           /* Current column. */
+
+       db_recno_t       sb_total;      /* scrollbar: total lines in file. */
+       db_recno_t       sb_top;        /* scrollbar: top line on screen. */
+       size_t   sb_num;        /* scrollbar: number of lines on screen. */
+
+       size_t   iblen;         /* Input buffer length. */
+       size_t   iskip;         /* Returned input buffer. */
+       char     ibuf[256];     /* Input buffer. */
+
+       CHAR_T   tbuf[256];     /* Input keys. */
+
+#define        IP_IN_EX        0x0001  /* Currently running ex. */
+#define IP_ON_ALTERNATE 0x0002 /* Alternate on. */
+#define        IP_SCR_VI_INIT  0x0004  /* Vi screen initialized. */
+       u_int32_t flags;
+} IP_PRIVATE;
+
+#define        IPP(sp)         ((IP_PRIVATE *)((sp)->wp->ip_private))
+#define        WIPP(wp)        ((IP_PRIVATE *)((wp)->ip_private))
+
+/* The screen line relative to a specific window. */
+#define        RLNO(sp, lno)   (sp)->roff + (lno)
+#define        RCNO(sp, cno)   (sp)->coff + (cno)
+
+#define        IPO_CODE_LEN    1       /* Length of a code value. */
+#define        IPO_INT_LEN     4       /* Length of an integer. */
+
+/* A structure that can hold the information for any frame. */
+typedef struct _ip_buf {
+       int code;               /* Event code. */
+       const char *str1;       /* String #1. */
+       u_int32_t len1;         /* String #1 length. */
+       const char *str2;       /* String #1. */
+       u_int32_t len2;         /* String #1 length. */
+       u_int32_t val1;         /* Value #1. */
+       u_int32_t val2;         /* Value #2. */
+       u_int32_t val3;         /* Value #3. */
+} IP_BUF;
+
+typedef int (*IPFunc) (struct _ip_vi_win *);
+typedef int (*IPFunc_1) (struct _ip_vi_win *, u_int32_t);
+typedef int (*IPFunc_1a) (struct _ip_vi_win *, u_int32_t, const char *, u_int32_t);
+typedef int (*IPFunc_a) (struct _ip_vi_win *, const char *, u_int32_t);
+typedef int (*IPFunc_ab1) (struct _ip_vi_win *, const char *, u_int32_t, 
+                           const char *, u_int32_t, u_int32_t);
+typedef int (*IPFunc_12) (struct _ip_vi_win *, u_int32_t, u_int32_t);
+typedef int (*IPFunc_123) (struct _ip_vi_win *, u_int32_t, u_int32_t, u_int32_t);
+
+typedef int (*IPUnmarshall) (struct _ip_vi_win *, IP_BUF *, IPFunc);
+
+typedef struct _ipfunlist {
+    char                  *format;
+    IPUnmarshall    unmarshall;
+    size_t         offset;
+} IPFUNLIST;
+
+typedef struct _vipfunlist {
+    char                  *format;
+    e_event_t      e_event;
+} VIPFUNLIST;
+
+typedef struct ip_si_operations {
+    IPFunc_a   addstr;
+    IPFunc_12  attribute;
+    IPFunc      bell;
+    IPFunc      busy_off;
+    IPFunc_a    busy_on;
+    IPFunc      clrtoeol;
+    IPFunc      deleteln;
+    IPFunc      discard;
+    IPFunc_ab1  editopt;
+    IPFunc      insertln;
+    IPFunc_12   move;
+    IPFunc      quit;
+    IPFunc      redraw;
+    IPFunc      refresh;
+    IPFunc_a    rename;
+    IPFunc_1    rewrite;
+    IPFunc_123  scrollbar;
+    IPFunc_a    select;
+    IPFunc      split;
+    IPFunc_a   waddstr;
+} IPSIOPS;
+
+struct _ip_vi; 
+typedef struct _ip_vi IPVI;
+
+struct _ip_vi_win;
+typedef struct _ip_vi_win IPVIWIN;
+
+struct _ip_vi {
+    int                ifd;            /* Input file descriptor. */
+    int                ofd;            /* Output file descriptor. */
+    pid_t      pid;
+
+    void       *private_data;
+
+    u_int32_t  flags;
+
+    int                (*run) __P((IPVI*, int, char*[]));
+    int        (*new_window) __P((IPVI *, IPVIWIN **, int));
+    int                (*close) __P((IPVI*));
+};
+
+struct _ip_vi_win {
+    int                ifd;            /* Input file descriptor. */
+    int                ofd;            /* Output file descriptor. */
+
+    void       *private_data;
+
+    IPSIOPS     *si_ops;
+
+    int                (*c_bol) __P((IPVIWIN*));
+    int                (*c_bottom) __P((IPVIWIN*));
+    int                (*c_del) __P((IPVIWIN*));
+    int                (*c_eol) __P((IPVIWIN*));
+    int                (*c_insert) __P((IPVIWIN*));
+    int                (*c_left) __P((IPVIWIN*));
+    int                (*c_right) __P((IPVIWIN*));
+    int                (*c_top) __P((IPVIWIN*));
+    int                (*c_settop) __P((IPVIWIN*, u_int32_t));
+
+    int                (*string) __P((IPVIWIN*, const char*, u_int32_t));
+    int                (*wq) __P((IPVIWIN*));
+    int                (*quit) __P((IPVIWIN*));
+    int                (*resize) __P((IPVIWIN*, u_int32_t, u_int32_t));
+
+    int                (*input) __P((IPVIWIN*, int));
+    int                (*close) __P((IPVIWIN*));
+
+    int                (*set_ops) __P((IPVIWIN*, IPSIOPS*));
+};
+
+/*
+ * Screen/editor IP_CODE's.
+ *
+ * The program structure depends on the event loop being able to return
+ * IPO_EOF/IPO_ERR multiple times -- eventually enough things will end
+ * due to the events that vi will reach the command level for the screen,
+ * at which point the exit flags will be set and vi will exit.
+ *
+ * IP events sent from the screen to vi.
+ */
+#define        CODE_OOB         0      /* Illegal code. */
+#if 0
+#define        VI_C_BOL         1      /* Cursor to start of line. */
+#define        VI_C_BOTTOM      2      /* Cursor to bottom. */
+#define        VI_C_DEL         3      /* Cursor delete. */
+#define        VI_C_DOWN        4      /* Cursor down N lines: IPO_INT. */
+#define        VI_C_EOL         5      /* Cursor to end of line. */
+#define        VI_C_INSERT      6      /* Cursor: enter insert mode. */
+#define        VI_C_LEFT        7      /* Cursor left. */
+#define        VI_C_PGDOWN      8      /* Cursor down N pages: IPO_INT. */
+#define        VI_C_PGUP        9      /* Cursor up N lines: IPO_INT. */
+#define        VI_C_RIGHT      10      /* Cursor right. */
+#define        VI_C_SEARCH     11      /* Cursor: search: IPO_INT, IPO_STR. */
+#define        VI_C_SETTOP     12      /* Cursor: set screen top line: IPO_INT. */
+#define        VI_C_TOP        13      /* Cursor to top. */
+#define        VI_C_UP         14      /* Cursor up N lines: IPO_INT. */
+#define        VI_EDIT         15      /* Edit a file: IPO_STR. */
+#define        VI_EDITOPT      16      /* Edit option: 2 * IPO_STR, IPO_INT. */
+#define        VI_EDITSPLIT    17      /* Split to a file: IPO_STR. */
+#define        VI_EOF          18      /* End of input (NOT ^D). */
+#define        VI_ERR          19      /* Input error. */
+#define        VI_INTERRUPT    20      /* Interrupt. */
+#define        VI_MOUSE_MOVE   21      /* Mouse click move: IPO_INT, IPO_INT. */
+#define        VI_QUIT         22      /* Quit. */
+#define        VI_RESIZE       23      /* Screen resize: IPO_INT, IPO_INT. */
+#define        VI_SEL_END      24      /* Select end: IPO_INT, IPO_INT. */
+#define        VI_SEL_START    25      /* Select start: IPO_INT, IPO_INT. */
+#define        VI_SIGHUP       26      /* SIGHUP. */
+#define        VI_SIGTERM      27      /* SIGTERM. */
+#define        VI_STRING       28      /* Input string: IPO_STR. */
+#define        VI_TAG          29      /* Tag. */
+#define        VI_TAGAS        30      /* Tag to a string: IPO_STR. */
+#define        VI_TAGSPLIT     31      /* Split to a tag. */
+#define        VI_UNDO         32      /* Undo. */
+#define        VI_WQ           33      /* Write and quit. */
+#define        VI_WRITE        34      /* Write. */
+#define        VI_WRITEAS      35      /* Write as another file: IPO_STR. */
+#define VI_FLAGS       36      /* Flags passed to nvi_create */
+#endif
+
+#define        VI_SEARCH_EXT   0x001   /* VI_C_SEARCH: ignore case. */
+#define        VI_SEARCH_IC    0x002   /* VI_C_SEARCH: ignore case. */
+#define        VI_SEARCH_ICL   0x004   /* VI_C_SEARCH: ignore case if lower-case. */
+#define        VI_SEARCH_INCR  0x008   /* VI_C_SEARCH: incremental search. */
+#define        VI_SEARCH_LIT   0x010   /* VI_C_SEARCH: literal string. */
+#define        VI_SEARCH_REV   0x020   /* VI_C_SEARCH: reverse direction. */
+#define        VI_SEARCH_WR    0x040   /* VI_C_SEARCH: wrap at sof/eof. */
+
+/*
+ * IP events sent from vi to the screen.
+ */
+#if 0
+#define        SI_ADDSTR        1      /* Add a string: IPO_STR. */
+#define        SI_ATTRIBUTE     2      /* Set screen attribute: 2 * IPO_INT. */
+#define        SI_BELL          3      /* Beep/bell/flash the terminal. */
+#define        SI_BUSY_OFF      4      /* Display a busy message: IPO_STR. */
+#define        SI_BUSY_ON       5      /* Display a busy message: IPO_STR. */
+#define        SI_CLRTOEOL      6      /* Clear to the end of the line. */
+#define        SI_DELETELN      7      /* Delete a line. */
+#define        SI_DISCARD       8      /* Discard the screen. */
+#define        SI_EDITOPT       9      /* Edit option: 2 * IPO_STR, IPO_INT. */
+#define        SI_INSERTLN     10      /* Insert a line. */
+#define        SI_MOVE         11      /* Move the cursor: 2 * IPO_INT. */
+#define        SI_QUIT         12      /* Quit. */
+#define        SI_REDRAW       13      /* Redraw the screen. */
+#define        SI_REFRESH      14      /* Refresh the screen. */
+#define        SI_RENAME       15      /* Rename the screen: IPO_STR. */
+#define        SI_REPLY        16      /* Reply: IPO_INT (0/1), IPO_STR. */
+#define        SI_REWRITE      17      /* Rewrite a line: IPO_INT. */
+#define        SI_SCROLLBAR    18      /* Reset the scrollbar: 3 * IPO_INT. */
+#define        SI_SELECT       19      /* Select area: IPO_STR. */
+#define        SI_SPLIT        20      /* Split the screen. */
+#define        SI_EVENT_MAX    20
+#endif
+
+#include "extern.h"
diff --git a/dist/nvi/ipc/ip_run.c b/dist/nvi/ipc/ip_run.c
new file mode 100644 (file)
index 0000000..94c27ff
--- /dev/null
@@ -0,0 +1,267 @@
+/*     $NetBSD: ip_run.c,v 1.1.1.2 2008/05/18 14:31:25 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_run.c,v 8.17 2000/07/04 21:48:54 skimo Exp (Berkeley) Date: 2000/07/04 21:48:54";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+
+#include "../common/common.h"
+#include "ip.h"
+#include "pathnames.h"
+
+static void arg_format __P((char *, int *, char **[], int, int));
+static void fatal __P((void));
+#ifdef DEBUG
+static void attach __P((void));
+#endif
+static int channel(int rpipe[2], int wpipe[2]);
+
+char   *vi_progname = "vi";                    /* Global: program name. */
+
+/*
+ * vi_run --
+ *     Run the vi program.
+ *
+ * PUBLIC: int vi_run __P((IPVI *, int, char *[]));
+ */
+int
+vi_run(ipvi, argc, argv)
+       IPVI *ipvi;
+       int argc;
+       char *argv[];
+{
+       struct stat sb;
+       int pflag, rpipe[2], wpipe[2];
+       char *execp, **p_av, **t_av;
+
+       pflag = 0;
+       execp = VI;
+
+       /* Strip out any arguments that vi isn't going to understand. */
+       for (p_av = t_av = argv;;) {
+               if (*t_av == NULL) {
+                       *p_av = NULL;
+                       break;
+               }
+               if (!strcmp(*t_av, "--")) {
+                       while ((*p_av++ = *++t_av) != NULL);
+                       break;
+               }
+#ifdef DEBUG
+               if (!memcmp(*t_av, "-D", sizeof("-D") - 1)) {
+                       attach();
+
+                       ++t_av;
+                       --argc;
+                       continue;
+               }
+#endif
+#ifdef TRACE
+               if (!memcmp(*t_av, "-T", sizeof("-T") - 1)) {
+                       char *p = &t_av[0][sizeof("-T") - 1];
+                       if (*p == '\0') {
+                               --argc;
+                               p = *++t_av;
+                       }
+                       vtrace_init(p);
+                       ++t_av;
+                       --argc;
+                       continue;
+               }
+#endif
+               if (!memcmp(*t_av, "-P", sizeof("-P") - 1)) {
+                       if (t_av[0][2] != '\0') {
+                               pflag = 1;
+                               execp = t_av[0] + 2;
+                               ++t_av;
+                               --argc;
+                               continue;
+                       }
+                       if (t_av[1] != NULL) {
+                               pflag = 1;
+                               execp = t_av[1];
+                               t_av += 2;
+                               argc -= 2;
+                               continue;
+                       }
+               }
+               *p_av++ = *t_av++;
+       }
+
+       /*
+        * Open the communications channels.  The pipes are named from the
+        * parent's viewpoint, meaning the screen reads from rpipe[0] and
+        * writes to wpipe[1].  The vi process reads from wpipe[0], and it
+        * writes to rpipe[1].
+        */
+       if (channel(rpipe, wpipe) == -1)
+               fatal();
+       ipvi->ifd = rpipe[0];
+       ipvi->ofd = wpipe[1];
+
+       /*
+        * Reformat our arguments, adding a -I to the list.  The first file
+        * descriptor for the -I argument is vi's input, and the second is
+        * vi's output.
+        */
+       arg_format(execp, &argc, &argv, wpipe[0], rpipe[1]);
+
+       /* Run vi. */
+       switch (ipvi->pid = fork()) {
+       case -1:                                /* Error. */
+               fatal();
+               /* NOTREACHED */
+       case 0:                                 /* Child: Vi. */
+               (void)close(rpipe[0]);
+               (void)close(wpipe[1]);
+
+               /*
+                * If the user didn't override the path and there's a local
+                * (debugging) nvi, run it, otherwise run the user's path,
+                * if specified, else run the compiled in path.
+                */
+               if (!pflag && stat("vi-ipc", &sb) == 0)
+                       execv("vi-ipc", argv);
+               execv(execp, argv);
+               (void)fprintf(stderr,
+                   "%s: %s %s\n", vi_progname, execp, strerror(errno));
+               (void)fprintf(stderr,
+#ifdef DEBUG
+           "usage: %s [-D] [-P vi_program] [-T trace] [vi arguments]\n",
+#else
+           "usage: %s [-P vi_program] [vi arguments]\n",
+#endif
+                   vi_progname);
+               _exit (1);
+       default:                                /* Parent: Screen. */
+               (void)close(rpipe[1]);
+               (void)close(wpipe[0]);
+               break;
+       }
+       return (0);
+}
+
+/*
+ * fatal --
+ *     Fatal error.
+ */
+static void
+fatal()
+{
+       (void)fprintf(stderr, "%s: %s\n", vi_progname, strerror(errno));
+       exit (1);
+}
+
+static 
+int channel(int rpipe[2], int wpipe[2])
+{
+       if (0) {
+
+       if (pipe(rpipe) == -1 || pipe(wpipe) == -1)
+               return -1;
+
+       } else {
+
+       int sockets[2];
+
+       if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) == -1)
+               return -1;
+
+       rpipe[0] = sockets[0];
+       wpipe[0] = sockets[1];
+       if (((rpipe[1] = dup(sockets[1])) == -1) ||
+           ((wpipe[1] = dup(sockets[0])) == -1))
+               return -1;
+
+       }
+}
+
+/*
+ * arg_format --
+ *     Reformat our arguments to add the -I argument for vi.
+ */
+static void
+arg_format(execp, argcp, argvp, i_fd, o_fd)
+       char *execp, **argvp[];
+       int *argcp, i_fd, o_fd;
+{
+       char *iarg, **largv, *p, **p_av, **t_av;
+
+       /* Get space for the argument array and the -I argument. */
+       if ((iarg = malloc(64)) == NULL ||
+           (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL)
+               fatal();
+       memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
+
+       /* Reset argv[0] to be the exec'd program. */
+       if ((p = strrchr(execp, '/')) == NULL)
+               largv[0] = execp;
+       else
+               largv[0] = p + 1;
+
+       /* Create the -I argument. */
+       (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
+       largv[1] = iarg;
+
+       /* Copy any remaining arguments into the array. */
+       for (p_av = (*argvp) + 1, t_av = largv + 2;;)
+               if ((*t_av++ = *p_av++) == NULL)
+                       break;
+
+       /* Reset the argument array. */
+       *argvp = largv;
+}
+
+#ifdef DEBUG
+/*
+ * attach --
+ *     Pause and let the user attach a debugger.
+ */
+static void
+attach()
+{
+       int fd;
+       char ch;
+
+       (void)printf("process %lu waiting, enter <CR> to continue: ",
+           (u_long)getpid());
+       (void)fflush(stdout);
+
+       if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
+               (void)fprintf(stderr,
+                   "%s: %s, %s\n", vi_progname, _PATH_TTY, strerror(errno));
+               exit (1);;
+       }
+       do {
+               if (read(fd, &ch, 1) != 1) {
+                       (void)close(fd);
+                       return;
+               }
+       } while (ch != '\n' && ch != '\r');
+       (void)close(fd);
+}
+#endif
diff --git a/dist/nvi/ipc/ip_send.c b/dist/nvi/ipc/ip_send.c
new file mode 100644 (file)
index 0000000..4348ff6
--- /dev/null
@@ -0,0 +1,114 @@
+/*     $NetBSD: ip_send.c,v 1.1.1.2 2008/05/18 14:31:24 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_send.c,v 8.10 2001/06/25 15:19:25 skimo Exp (Berkeley) Date: 2001/06/25 15:19:25";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+/*
+ * vi_send --
+ *     Construct and send an IP buffer.
+ *
+ * PUBLIC: int vi_send __P((int, char *, IP_BUF *));
+ */
+int
+vi_send(int ofd, char *fmt, IP_BUF *ipbp)
+{
+       static char *bp;
+       static size_t blen;
+       size_t off;
+       u_int32_t ilen;
+       int nlen, n, nw;
+       char *p;
+
+       /*
+        * Have not created the channel to vi yet?  -- RAZ
+        *
+        * XXX
+        * How is that possible!?!?
+        *
+        * We'll soon find out.
+        */
+       if (ofd == 0) {
+               fprintf(stderr, "No channel\n");
+               abort();
+       }
+
+       if (blen == 0 && (bp = malloc(blen = 512)) == NULL)
+               return (1);
+
+       p = bp;
+       nlen = 0;
+       *p++ = ipbp->code;
+       nlen += IPO_CODE_LEN;
+
+       if (fmt != NULL)
+               for (; *fmt != '\0'; ++fmt)
+                       switch (*fmt) {
+                       case '1':                               /* Value #1. */
+                               ilen = htonl(ipbp->val1);
+                               goto value;
+                       case '2':                               /* Value #2. */
+                               ilen = htonl(ipbp->val2);
+                               goto value;
+                       case '3':                               /* Value #3. */
+                               ilen = htonl(ipbp->val3);
+value:                         nlen += IPO_INT_LEN;
+                               if (nlen >= blen) {
+                                       blen = blen * 2 + nlen;
+                                       off = p - bp;
+                                       if ((bp = realloc(bp, blen)) == NULL)
+                                               return (1);
+                                       p = bp + off;
+                               }
+                               memcpy(p, &ilen, IPO_INT_LEN);
+                               p += IPO_INT_LEN;
+                               break;
+                       case 'a':                               /* String #1. */
+                       case 'b':                               /* String #2. */
+                               ilen = *fmt == 'a' ? ipbp->len1 : ipbp->len2;
+                               nlen += IPO_INT_LEN + ilen;
+                               if (nlen >= blen) {
+                                       blen = blen * 2 + nlen;
+                                       off = p - bp;
+                                       if ((bp = realloc(bp, blen)) == NULL)
+                                               return (1);
+                                       p = bp + off;
+                               }
+                               ilen = htonl(ilen);
+                               memcpy(p, &ilen, IPO_INT_LEN);
+                               p += IPO_INT_LEN;
+                               if (*fmt == 'a') {
+                                       memcpy(p, ipbp->str1, ipbp->len1);
+                                       p += ipbp->len1;
+                               } else {
+                                       memcpy(p, ipbp->str2, ipbp->len2);
+                                       p += ipbp->len2;
+                               }
+                               break;
+                       }
+       for (n = p - bp, p = bp; n > 0; n -= nw, p += nw)
+               if ((nw = write(ofd, p, n)) < 0)
+                       return (1);
+       return (0);
+}
diff --git a/dist/nvi/ipc/ip_trans.c b/dist/nvi/ipc/ip_trans.c
new file mode 100644 (file)
index 0000000..2f88bf9
--- /dev/null
@@ -0,0 +1,209 @@
+/*     $NetBSD: ip_trans.c,v 1.1.1.2 2008/05/18 14:31:25 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: ip_trans.c,v 8.18 2001/06/25 15:19:25 skimo Exp (Berkeley) Date: 2001/06/25 15:19:25";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "../common/common.h"
+#include "ip.h"
+#include "ipc_def.h"
+
+static char ibuf[2048];                                /* Input buffer. */
+static size_t ibuf_len;                                /* Length of current input. */
+
+extern IPFUNLIST const ipfuns[];
+
+/*
+ * vi_input --
+ *     Read from the vi message queue.
+ *
+ * PUBLIC: int vi_input __P((IPVIWIN *, int));
+ */
+int
+vi_input(IPVIWIN *ipviwin, int fd)
+{
+       ssize_t nr;
+
+       /* Read waiting vi messages and translate to X calls. */
+       switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
+       case 0:
+               return (0);
+       case -1:
+               return (-1);
+       default:
+               break;
+       }
+       ibuf_len += nr;
+
+       /* Parse to data end or partial message. */
+       (void)vi_translate(ipviwin, ibuf, &ibuf_len, NULL);
+
+       return (ibuf_len > 0);
+}
+
+/*
+ * vi_wsend --
+ *     Construct and send an IP buffer, and wait for an answer.
+ *
+ * PUBLIC: int vi_wsend __P((IPVIWIN*, char *, IP_BUF *));
+ */
+int
+vi_wsend(IPVIWIN *ipviwin, char *fmt, IP_BUF *ipbp)
+{
+       fd_set rdfd;
+       ssize_t nr;
+
+       if (vi_send(ipviwin->ofd, fmt, ipbp))
+               return (1);
+
+       FD_ZERO(&rdfd);
+       ipbp->code = CODE_OOB;
+
+       for (;;) {
+               FD_SET(ipviwin->ifd, &rdfd);
+               if (select(ipviwin->ifd + 1, &rdfd, NULL, NULL, NULL) != 0)
+                       return (-1);
+
+               /* Read waiting vi messages and translate to X calls. */
+               switch (nr =
+                   read(ipviwin->ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
+               case 0:
+                       return (0);
+               case -1:
+                       return (-1);
+               default:
+                       break;
+               }
+               ibuf_len += nr;
+
+               /* Parse to data end or partial message. */
+               (void)vi_translate(ipviwin, ibuf, &ibuf_len, ipbp);
+
+               if (ipbp->code != CODE_OOB)
+                       break;
+       }
+       return (0);
+}
+
+/*
+ * vi_translate --
+ *     Translate vi messages into function calls.
+ *
+ * PUBLIC: int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *));
+ */
+int
+vi_translate(IPVIWIN *ipviwin, char *bp, size_t *lenp, IP_BUF *ipbp)
+{
+       IP_BUF ipb;
+       size_t len, needlen;
+       u_int32_t *vp;
+       char *fmt, *p, *s_bp;
+       const char **vsp;
+       IPFunc fun;
+
+       for (s_bp = bp, len = *lenp; len > 0;) {
+               fmt = ipfuns[(ipb.code = bp[0])-1].format;
+
+               p = bp + IPO_CODE_LEN;
+               needlen = IPO_CODE_LEN;
+               for (; *fmt != '\0'; ++fmt)
+                       switch (*fmt) {
+                       case '1':                               /* Value #1. */
+                               vp = &ipb.val1;
+                               goto value;
+                       case '2':                               /* Value #2. */
+                               vp = &ipb.val2;
+                               goto value;
+                       case '3':                               /* Value #3. */
+                               vp = &ipb.val3;
+value:                         needlen += IPO_INT_LEN;
+                               if (len < needlen)
+                                       goto partial;
+                               memcpy(vp, p, IPO_INT_LEN);
+                               *vp = ntohl(*vp);
+                               p += IPO_INT_LEN;
+                               break;
+                       case 'a':                               /* String #1. */
+                               vp = &ipb.len1;
+                               vsp = &ipb.str1;
+                               goto string;
+                       case 'b':                               /* String #2. */
+                               vp = &ipb.len2;
+                               vsp = &ipb.str2;
+string:                                needlen += IPO_INT_LEN;
+                               if (len < needlen)
+                                       goto partial;
+                               memcpy(vp, p, IPO_INT_LEN);
+                               *vp = ntohl(*vp);
+                               p += IPO_INT_LEN;
+                               needlen += *vp;
+                               if (len < needlen)
+                                       goto partial;
+                               *vsp = p;
+                               p += *vp;
+                               break;
+                       }
+               bp += needlen;
+               len -= needlen;
+
+               /*
+                * XXX
+                * Protocol error!?!?
+                */
+               if (ipb.code >= SI_EVENT_SUP) {
+                       len = 0;
+                       break;
+               }
+
+               /*
+                * If we're waiting for a reply and we got it, return it, and
+                * leave any unprocessed data in the buffer.  If we got a reply
+                * and we're not waiting for one, discard it -- callers wait
+                * for responses.
+                */
+               if (ipb.code == SI_REPLY) {
+                       if (ipbp == NULL)
+                               continue;
+                       *ipbp = ipb;
+                       break;
+               }
+
+               /* Call the underlying routine. */
+               fun = *(IPFunc *)
+                   (((char *)ipviwin->si_ops)+ipfuns[ipb.code - 1].offset);
+               if (fun != NULL &&
+                   ipfuns[ipb.code - 1].unmarshall(ipviwin, &ipb, fun))
+                       break;
+       }
+partial:
+       if ((*lenp = len) != 0)
+               memmove(s_bp, bp, len);
+       return (0);
+}
diff --git a/dist/nvi/ipc/ipc.awk b/dist/nvi/ipc/ipc.awk
new file mode 100644 (file)
index 0000000..828a642
--- /dev/null
@@ -0,0 +1,6 @@
+#      @(#)ipc.awk     10.1 (Berkeley) 6/8/95
+/^\/\* SI_[0-9A-Z_]* \*\/$/ {
+       printf("#define %s %d\n", $2, ++cnt);
+       next;
+}
diff --git a/dist/nvi/ipc/ipc_cmd.c b/dist/nvi/ipc/ipc_cmd.c
new file mode 100644 (file)
index 0000000..6519695
--- /dev/null
@@ -0,0 +1,112 @@
+/*     $NetBSD: ipc_cmd.c,v 1.1.1.2 2008/05/18 14:31:25 aymeric Exp $ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+#include "ip.h"
+
+static int ipc_unmarshall_a __P((IPVIWIN *, IP_BUF*, IPFunc));
+static int ipc_unmarshall_12 __P((IPVIWIN *, IP_BUF*, IPFunc));
+static int ipc_unmarshall __P((IPVIWIN *, IP_BUF*, IPFunc));
+static int ipc_unmarshall_ab1 __P((IPVIWIN *, IP_BUF*, IPFunc));
+static int ipc_unmarshall_1a __P((IPVIWIN *, IP_BUF*, IPFunc));
+static int ipc_unmarshall_1 __P((IPVIWIN *, IP_BUF*, IPFunc));
+static int ipc_unmarshall_123 __P((IPVIWIN *, IP_BUF*, IPFunc));
+
+#define OFFSET(t,m) ((size_t)&((t *)0)->m)
+
+IPFUNLIST const ipfuns[] = {
+/* SI_ADDSTR */
+    {"a",   ipc_unmarshall_a,  OFFSET(IPSIOPS, addstr)},
+/* SI_ATTRIBUTE */
+    {"12",  ipc_unmarshall_12, OFFSET(IPSIOPS, attribute)},
+/* SI_BELL */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, bell)},
+/* SI_BUSY_OFF */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, busy_off)},
+/* SI_BUSY_ON */
+    {"a",   ipc_unmarshall_a,  OFFSET(IPSIOPS, busy_on)},
+/* SI_CLRTOEOL */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, clrtoeol)},
+/* SI_DELETELN */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, deleteln)},
+/* SI_DISCARD */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, discard)},
+/* SI_EDITOPT */
+    {"ab1", ipc_unmarshall_ab1,        OFFSET(IPSIOPS, editopt)},
+/* SI_INSERTLN */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, insertln)},
+/* SI_MOVE */
+    {"12",  ipc_unmarshall_12, OFFSET(IPSIOPS, move)},
+/* SI_QUIT */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, quit)},
+/* SI_REDRAW */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, redraw)},
+/* SI_REFRESH */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, refresh)},
+/* SI_RENAME */
+    {"a",   ipc_unmarshall_a,  OFFSET(IPSIOPS, rename)},
+/* SI_REPLY */
+    {"1a",  NULL,              0},
+/* SI_REWRITE */
+    {"1",   ipc_unmarshall_1,  OFFSET(IPSIOPS, rewrite)},
+/* SI_SCROLLBAR */
+    {"123", ipc_unmarshall_123,        OFFSET(IPSIOPS, scrollbar)},
+/* SI_SELECT */
+    {"a",   ipc_unmarshall_a,  OFFSET(IPSIOPS, select)},
+/* SI_SPLIT */
+    {"",    ipc_unmarshall,    OFFSET(IPSIOPS, split)},
+/* SI_WADDSTR */
+    {"a",   ipc_unmarshall_a,  OFFSET(IPSIOPS, waddstr)},
+/* SI_EVENT_SUP */
+};
+
+static int
+ipc_unmarshall_a(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return ((IPFunc_a)func)(ipvi, ipb->str1, ipb->len1);
+}
+
+static int
+ipc_unmarshall_12(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return ((IPFunc_12)func)(ipvi, ipb->val1, ipb->val2);
+}
+
+static int
+ipc_unmarshall(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return func(ipvi);
+}
+
+static int
+ipc_unmarshall_ab1(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return ((IPFunc_ab1)func)(ipvi, ipb->str1, ipb->len1, ipb->str2, ipb->len2, ipb->val1);
+}
+
+static int
+ipc_unmarshall_1a(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return ((IPFunc_1a)func)(ipvi, ipb->val1, ipb->str1, ipb->len1);
+}
+
+static int
+ipc_unmarshall_1(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return ((IPFunc_1)func)(ipvi, ipb->val1);
+}
+
+static int
+ipc_unmarshall_123(IPVIWIN *ipvi, IP_BUF *ipb, IPFunc func)
+{
+    return ((IPFunc_123)func)(ipvi, ipb->val1, ipb->val2, ipb->val3);
+}
diff --git a/dist/nvi/ipc/ipc_def.h b/dist/nvi/ipc/ipc_def.h
new file mode 100644 (file)
index 0000000..ac910dc
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD: ipc_def.h,v 1.1.1.1 2008/05/18 14:31:25 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+#define SI_ADDSTR 1
+#define SI_ATTRIBUTE 2
+#define SI_BELL 3
+#define SI_BUSY_OFF 4
+#define SI_BUSY_ON 5
+#define SI_CLRTOEOL 6
+#define SI_DELETELN 7
+#define SI_DISCARD 8
+#define SI_EDITOPT 9
+#define SI_INSERTLN 10
+#define SI_MOVE 11
+#define SI_QUIT 12
+#define SI_REDRAW 13
+#define SI_REFRESH 14
+#define SI_RENAME 15
+#define SI_REPLY 16
+#define SI_REWRITE 17
+#define SI_SCROLLBAR 18
+#define SI_SELECT 19
+#define SI_SPLIT 20
+#define SI_WADDSTR 21
+#define SI_EVENT_SUP 22
+#define VI_C_BOL 1
+#define VI_C_BOTTOM 2
+#define VI_C_DEL 3
+#define VI_C_DOWN 4
+#define VI_C_EOL 5
+#define VI_C_INSERT 6
+#define VI_C_LEFT 7
+#define VI_C_PGDOWN 8
+#define VI_C_PGUP 9
+#define VI_C_RIGHT 10
+#define VI_C_SEARCH 11
+#define VI_C_SETTOP 12
+#define VI_C_TOP 13
+#define VI_C_UP 14
+#define VI_EDIT 15
+#define VI_EDITOPT 16
+#define VI_EDITSPLIT 17
+#define VI_EOF 18
+#define VI_ERR 19
+#define VI_FLAGS 20
+#define VI_INTERRUPT 21
+#define VI_MOUSE_MOVE 22
+#define VI_QUIT 23
+#define VI_RESIZE 24
+#define VI_SEL_END 25
+#define VI_SEL_START 26
+#define VI_SIGHUP 27
+#define VI_SIGTERM 28
+#define VI_STRING 29
+#define VI_TAG 30
+#define VI_TAGAS 31
+#define VI_TAGSPLIT 32
+#define VI_UNDO 33
+#define VI_WQ 34
+#define VI_WRITE 35
+#define VI_WRITEAS 36
+#define VI_EVENT_SUP 37
diff --git a/dist/nvi/ipc/ipc_gen.c b/dist/nvi/ipc/ipc_gen.c
new file mode 100644 (file)
index 0000000..6fdc31f
--- /dev/null
@@ -0,0 +1,219 @@
+/*     $NetBSD: ipc_gen.c,v 1.1.1.1 2008/05/18 14:31:25 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+static int
+vi_c_bol(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_BOL);
+}
+
+static int
+vi_c_bottom(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_BOTTOM);
+}
+
+static int
+vi_c_del(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_DEL);
+}
+
+static int
+vi_c_down(IPVIWIN *ipvi, u_int32_t val1)
+{
+       return vi_send_1(ipvi, VI_C_DOWN, val1);
+}
+
+static int
+vi_c_eol(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_EOL);
+}
+
+static int
+vi_c_insert(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_INSERT);
+}
+
+static int
+vi_c_left(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_LEFT);
+}
+
+static int
+vi_c_pgdown(IPVIWIN *ipvi, u_int32_t val1)
+{
+       return vi_send_1(ipvi, VI_C_PGDOWN, val1);
+}
+
+static int
+vi_c_pgup(IPVIWIN *ipvi, u_int32_t val1)
+{
+       return vi_send_1(ipvi, VI_C_PGUP, val1);
+}
+
+static int
+vi_c_right(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_RIGHT);
+}
+
+static int
+vi_c_search(IPVIWIN *ipvi, const char *stra, u_int32_t lena, u_int32_t val1)
+{
+       return vi_send_a1(ipvi, VI_C_SEARCH, stra, lena, val1);
+}
+
+static int
+vi_c_settop(IPVIWIN *ipvi, u_int32_t val1)
+{
+       return vi_send_1(ipvi, VI_C_SETTOP, val1);
+}
+
+static int
+vi_c_top(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_C_TOP);
+}
+
+static int
+vi_c_up(IPVIWIN *ipvi, u_int32_t val1)
+{
+       return vi_send_1(ipvi, VI_C_UP, val1);
+}
+
+static int
+vi_edit(IPVIWIN *ipvi, const char *stra, u_int32_t lena)
+{
+       return vi_send_a(ipvi, VI_EDIT, stra, lena);
+}
+
+static int
+vi_editopt(IPVIWIN *ipvi, const char *stra, u_int32_t lena, const char *strb, u_int32_t lenb, u_int32_t val1)
+{
+       return vi_send_ab1(ipvi, VI_EDITOPT, stra, lena, strb, lenb, val1);
+}
+
+static int
+vi_editsplit(IPVIWIN *ipvi, const char *stra, u_int32_t lena)
+{
+       return vi_send_a(ipvi, VI_EDITSPLIT, stra, lena);
+}
+
+static int
+vi_eof(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_EOF);
+}
+
+static int
+vi_err(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_ERR);
+}
+
+static int
+vi_flags(IPVIWIN *ipvi, u_int32_t val1)
+{
+       return vi_send_1(ipvi, VI_FLAGS, val1);
+}
+
+static int
+vi_interrupt(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_INTERRUPT);
+}
+
+static int
+vi_mouse_move(IPVIWIN *ipvi, u_int32_t val1, u_int32_t val2)
+{
+       return vi_send_12(ipvi, VI_MOUSE_MOVE, val1, val2);
+}
+
+static int
+vi_quit(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_QUIT);
+}
+
+static int
+vi_resize(IPVIWIN *ipvi, u_int32_t val1, u_int32_t val2)
+{
+       return vi_send_12(ipvi, VI_RESIZE, val1, val2);
+}
+
+static int
+vi_sel_end(IPVIWIN *ipvi, u_int32_t val1, u_int32_t val2)
+{
+       return vi_send_12(ipvi, VI_SEL_END, val1, val2);
+}
+
+static int
+vi_sel_start(IPVIWIN *ipvi, u_int32_t val1, u_int32_t val2)
+{
+       return vi_send_12(ipvi, VI_SEL_START, val1, val2);
+}
+
+static int
+vi_sighup(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_SIGHUP);
+}
+
+static int
+vi_sigterm(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_SIGTERM);
+}
+
+static int
+vi_string(IPVIWIN *ipvi, const char *stra, u_int32_t lena)
+{
+       return vi_send_a(ipvi, VI_STRING, stra, lena);
+}
+
+static int
+vi_tag(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_TAG);
+}
+
+static int
+vi_tagas(IPVIWIN *ipvi, const char *stra, u_int32_t lena)
+{
+       return vi_send_a(ipvi, VI_TAGAS, stra, lena);
+}
+
+static int
+vi_tagsplit(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_TAGSPLIT);
+}
+
+static int
+vi_undo(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_UNDO);
+}
+
+static int
+vi_wq(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_WQ);
+}
+
+static int
+vi_write(IPVIWIN *ipvi)
+{
+       return vi_send_(ipvi, VI_WRITE);
+}
+
+static int
+vi_writeas(IPVIWIN *ipvi, const char *stra, u_int32_t lena)
+{
+       return vi_send_a(ipvi, VI_WRITEAS, stra, lena);
+}
+
diff --git a/dist/nvi/ipc/ipc_method.c b/dist/nvi/ipc/ipc_method.c
new file mode 100644 (file)
index 0000000..ad7db84
--- /dev/null
@@ -0,0 +1,246 @@
+/*     $NetBSD: ipc_method.c,v 1.1.1.2 2008/05/18 14:31:25 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/uio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+static int vi_send_ __P((IPVIWIN   *, int));
+static int vi_send_1 __P((IPVIWIN   *, int, u_int32_t  ));
+static int vi_send_12 __P((IPVIWIN *ipvi, int code, u_int32_t val1, u_int32_t val2));
+static int vi_send_ab1 __P((IPVIWIN *ipvi, int code, 
+           const char *str1, u_int32_t len1, 
+           const char *str2, u_int32_t len2, u_int32_t val));
+static int vi_send_a1 __P((IPVIWIN *ipvi, int code, const char *str, u_int32_t len, 
+          u_int32_t val));
+static int vi_send_a __P((IPVIWIN *ipvi, int code, const char *str, u_int32_t len));
+
+#include "ipc_gen.c"
+
+static int vi_set_ops __P((IPVIWIN *, IPSIOPS *));
+static int vi_win_close __P((IPVIWIN *));
+
+static int vi_close __P((IPVI *));
+static int vi_new_window __P((IPVI *, IPVIWIN **, int));
+
+/* 
+ * vi_create
+ *
+ * PUBLIC: int vi_create __P((IPVI **, u_int32_t));
+ */
+int
+vi_create(IPVI **ipvip, u_int32_t flags)
+{
+       IPVI    *ipvi;
+
+       MALLOC_GOTO(NULL, ipvi, IPVI*, sizeof(IPVI));
+       memset(ipvi, 0, sizeof(IPVI));
+
+       ipvi->flags = flags;
+
+       ipvi->run = vi_run;
+       ipvi->new_window = vi_new_window;
+       ipvi->close = vi_close;
+
+       *ipvip = ipvi;
+
+       return 0;
+
+alloc_err:
+       return 1;
+}
+
+static int 
+vi_new_window (IPVI *ipvi, IPVIWIN **ipviwinp, int fd)
+{
+       IPVIWIN *ipviwin;
+
+       MALLOC_GOTO(NULL, ipviwin, IPVIWIN*, sizeof(IPVIWIN));
+       memset(ipviwin, 0, sizeof(IPVIWIN));
+
+       if (0) {
+       ipviwin->ifd = ipvi->ifd;
+       ipviwin->ofd = ipvi->ofd;
+       } else {
+       int sockets[2];
+       struct msghdr   mh;
+       IPCMSGHDR           ch;
+       char        dummy;
+       struct iovec    iov;
+
+       socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets);
+
+       mh.msg_namelen = 0;
+       mh.msg_iovlen = 1;
+       mh.msg_iov = &iov;
+       mh.msg_controllen = sizeof(ch);
+       mh.msg_control = (void *)&ch;
+
+       iov.iov_len = 1;
+       iov.iov_base = &dummy;
+
+       ch.header.cmsg_level = SOL_SOCKET;
+       ch.header.cmsg_type = SCM_RIGHTS;
+       ch.header.cmsg_len = sizeof(ch);
+
+       *(int *)CMSG_DATA(&ch.header) = sockets[1];
+       sendmsg(ipvi->ofd, &mh, 0);
+       dummy = (fd == -1) ? ' ' : 'F';
+       *(int *)CMSG_DATA(&ch.header) = sockets[1];
+       sendmsg(sockets[0], &mh, 0);
+       close(sockets[1]);
+
+       if (fd != -1) {
+               *(int *)CMSG_DATA(&ch.header) = fd;
+               sendmsg(sockets[0], &mh, 0);
+               close(fd);
+       }
+
+       ipviwin->ifd = sockets[0];
+       ipviwin->ofd = sockets[0];
+       }
+
+#define IPVISET(func) \
+       ipviwin->func = vi_##func;
+
+       IPVISET(c_bol);
+       IPVISET(c_bottom);
+       IPVISET(c_del);
+       IPVISET(c_eol);
+       IPVISET(c_insert);
+       IPVISET(c_left);
+       IPVISET(c_right);
+       IPVISET(c_top);
+       IPVISET(c_settop);
+       IPVISET(resize);
+       IPVISET(string);
+       IPVISET(quit);
+       IPVISET(wq);
+
+       IPVISET(input);
+       /*
+       IPVISET(close);
+       */
+       ipviwin->close = vi_win_close;
+       IPVISET(set_ops);
+
+       *ipviwinp = ipviwin;
+
+       return 0;
+
+alloc_err:
+       return 1;
+}
+
+static int 
+vi_set_ops(IPVIWIN *ipvi, IPSIOPS *ops)
+{
+       ipvi->si_ops = ops;
+       return 0;
+}
+
+static int  vi_close(IPVI *ipvi)
+{
+       memset(ipvi, 6, sizeof(IPVI));
+       free(ipvi);
+       return 0;
+}
+
+static int  vi_win_close(IPVIWIN *ipviwin)
+{
+       memset(ipviwin, 6, sizeof(IPVIWIN));
+       free(ipviwin);
+       return 0;
+}
+
+
+static int
+vi_send_(IPVIWIN *ipvi, int code)
+{
+       IP_BUF  ipb;
+       ipb.code = code;
+       return vi_send(ipvi->ofd, NULL, &ipb);
+}
+
+static int
+vi_send_1(IPVIWIN *ipvi, int code, u_int32_t val)
+{
+       IP_BUF  ipb;
+       ipb.code = code;
+       ipb.val1 = val;
+       return vi_send(ipvi->ofd, "1", &ipb);
+}
+
+static int
+vi_send_12(IPVIWIN *ipvi, int code, u_int32_t val1, u_int32_t val2)
+{
+       IP_BUF  ipb;
+
+       ipb.val1 = val1;
+       ipb.val2 = val2;
+       ipb.code = code;
+       return vi_send(ipvi->ofd, "12", &ipb);
+}
+
+static int
+vi_send_a(IPVIWIN *ipvi, int code, const char *str, u_int32_t len)
+{
+       IP_BUF  ipb;
+
+       ipb.str1 = str;
+       ipb.len1 = len;
+       ipb.code = code;
+       return vi_send(ipvi->ofd, "a", &ipb);
+}
+
+static int
+vi_send_a1(IPVIWIN *ipvi, int code, const char *str, u_int32_t len, 
+          u_int32_t val)
+{
+       IP_BUF  ipb;
+
+       ipb.str1 = str;
+       ipb.len1 = len;
+       ipb.val1 = val;
+       ipb.code = code;
+       return vi_send(ipvi->ofd, "a1", &ipb);
+}
+
+static int
+vi_send_ab1(IPVIWIN *ipvi, int code, const char *str1, u_int32_t len1, 
+           const char *str2, u_int32_t len2, u_int32_t val)
+{
+       IP_BUF  ipb;
+
+       ipb.str1 = str1;
+       ipb.len1 = len1;
+       ipb.str2 = str2;
+       ipb.len2 = len2;
+       ipb.val1 = val;
+       ipb.code = code;
+       return vi_send(ipvi->ofd, "ab1", &ipb);
+}
+
diff --git a/dist/nvi/ipc/vipc.awk b/dist/nvi/ipc/vipc.awk
new file mode 100644 (file)
index 0000000..8e1305d
--- /dev/null
@@ -0,0 +1,6 @@
+#      @(#)vipc.awk    10.1 (Berkeley) 6/8/95
+/^\/\* VI_[0-9A-Z_]*/ {
+       printf("#define %s %d\n", $2, ++cnt);
+       next;
+}
diff --git a/dist/nvi/motif/extern.h b/dist/nvi/motif/extern.h
new file mode 100644 (file)
index 0000000..6254668
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:26 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int is_cde __P((Display *));
diff --git a/dist/nvi/motif/m_cde.c b/dist/nvi/motif/m_cde.c
new file mode 100644 (file)
index 0000000..f06a1b3
--- /dev/null
@@ -0,0 +1,150 @@
+/*     $NetBSD: m_cde.c,v 1.1.1.2 2008/05/18 14:31:25 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_cde.c,v 8.11 2003/11/05 17:09:58 skimo Exp (Berkeley) Date: 2003/11/05 17:09:58";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "extern.h"
+
+#if SelfTest
+#define        _TRACE( x )     printf x
+#else
+#define        _TRACE( x )
+#endif
+
+#define        Required        10
+#define        Useful          3
+#define        Present         (Required+Useful)
+
+static struct {
+    char       *name;
+    int                value;
+} Atoms[] = {
+    { "_VUE_SM_WINDOW_INFO",   Required,       /* "vue" */             },
+    { "_DT_SM_WINDOW_INFO",    Required,       /* "dtwm" */            },
+    { "_SUN_WM_PROTOCOLS",     Useful,         /* "olwm" */            },
+    { "_MOTIF_WM_INFO",                Useful,         /* "mwm/dtwm" */        },
+};
+
+/*
+ * is_cde --
+ *
+ * When running under CDE (or VUE on HPUX) applications should not define
+ * fallback colors (or fonts).  The only way to tell is to check the atoms
+ * attached to the server.  This routine does that.
+ *
+ * PUBLIC: int is_cde __P((Display *));
+ */
+int
+is_cde(Display *d)
+{
+    int                        i, r, format;
+    unsigned long      nitems, remaining;
+    unsigned char      *prop;
+    Window             root = DefaultRootWindow( d );
+    Atom               atom, type;
+    int                        retval = 0;
+
+    _TRACE( ( "Root window is 0x%x\n", root ) );
+
+    /* create our atoms */
+    for (i=0; i< (sizeof(Atoms)/sizeof(Atoms[0])); i++ ) {
+
+       atom = XInternAtom( d, Atoms[i].name, True );
+       if ( atom == None ) {
+           _TRACE( ( "Atom \"%s\" does not exist\n", Atoms[i].name ) );
+           continue;
+       }
+
+       /* what is the value of the atom? */
+       r = XGetWindowProperty( d,
+                               root,
+                               atom,
+                               0,
+                               1024,
+                               False,                  /* do not delete */
+                               AnyPropertyType,        /* request type */
+                               &type,                  /* actual type */
+                               &format,                /* byte size */
+                               &nitems,                /* number of items */
+                               &remaining,             /* anything left over? */
+                               &prop                   /* the data itself */
+                               );
+       if ( r != Success ) {
+           _TRACE( ( "Atom \"%s\" cannot be converted to string\n", Atoms[i].name ) );
+           continue;
+       }
+
+       retval += Atoms[i].value;
+
+
+#if SelfTest
+       _TRACE( ( "Atom \"%s\"\n", Atoms[i].name ) );
+
+       switch ( type ) {
+           case 0:
+               _TRACE( ( "\t does not exist on the root window\n", Atoms[i].name ) );
+
+           case XA_ATOM:
+               for (j=0; j<nitems; j++) {
+                   name = XGetAtomName( d, ((Atom *) prop)[j] );
+                   _TRACE( ( "\t[%d] = \"%s\"\n", j, name ) );
+                   XFree( name );
+               }
+               break;
+
+           case XA_STRING:
+               _TRACE( ( "\t is a string\n", Atoms[i].name ) );
+               break;
+
+           default:
+               _TRACE( ( "\tunknown type %s\n", XGetAtomName( d, type ) ) );
+               break;
+       }
+#endif
+
+       /* done */
+       XFree( (caddr_t) prop );
+
+    }
+
+    _TRACE( ( "retval = %d\n", retval ) );
+    return retval >= Present;
+}
+
+#if SelfTest
+
+main () {
+    Display *d = XOpenDisplay( 0 );
+
+    if ( d == 0 )
+       printf ( "Could not open display\n" );
+    else {
+       printf ( "_vi_is_cde() == %d\n", _vi_is_cde( d ) );
+       XCloseDisplay( d );
+    }
+}
+#endif
diff --git a/dist/nvi/motif/m_main.c b/dist/nvi/motif/m_main.c
new file mode 100644 (file)
index 0000000..13cf285
--- /dev/null
@@ -0,0 +1,404 @@
+/*     $NetBSD: m_main.c,v 1.1.1.2 2008/05/18 14:31:26 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_main.c,v 8.40 2003/11/05 17:09:58 skimo Exp (Berkeley) Date: 2003/11/05 17:09:58";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <Xm/MainW.h>
+
+#include <bitstring.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "../motif_l/m_motif.h"
+#include "../motif_l/vi_mextern.h"
+#include "extern.h"
+
+int     vi_ifd = -1;
+int     vi_ofd = -1;
+IPVIWIN   *ipvi_motif;
+
+#if XtSpecificationRelease == 4
+#define        ArgcType        Cardinal *
+#else
+#define        ArgcType        int *
+#endif
+
+#if defined(ColorIcon)
+#if XT_REVISION >= 6
+#include <X11/xpm.h>
+#else
+#include "xpm.h"
+#endif
+
+#include "nvi.xpm"             /* Icon pixmap. */
+#else
+#include "nvi.xbm"             /* Icon bitmap. */
+#endif
+
+static pid_t           pid;
+static Pixel           icon_fg,
+                       icon_bg;
+static Pixmap          icon_pm;
+static Widget          top_level;
+static XtAppContext    ctx;
+
+static void XutInstallColormap __P((String, Widget));
+static void XutSetIcon __P((Widget, int, int, Pixmap));
+static void onchld __P((int));
+static void onexit __P((void));
+
+#if ! defined(ColorIcon)
+static  XutResource resource[] = {
+    { "iconForeground",        XutRKpixel,     &icon_fg        },
+    { "iconBackground",        XutRKpixel,     &icon_bg        },
+};
+#endif
+
+\f
+/* resources for the vi widgets unless the user overrides them */
+String fallback_rsrcs[] = {
+
+    "*font:                    -*-*-*-r-*--14-*-*-*-m-*-*-*",
+    "*text*fontList:           -*-*-*-r-*--14-*-*-*-m-*-*-*",
+    "*Menu*fontList:           -*-helvetica-bold-r-normal--14-*-*-*-*-*-*-*",
+    "*fontList:                        -*-helvetica-medium-r-normal--14-*-*-*-*-*-*-*",
+    "*pointerShape:            xterm",
+    "*busyShape:               watch",
+    "*iconName:                        vi",
+
+#if ! defined(ColorIcon)
+    /* coloring for the icons */
+    "*iconForeground:  XtDefaultForeground",
+    "*iconBackground:  XtDefaultBackground",
+#endif
+
+    /* layout for the tag stack dialog */
+    "*Tags*visibleItemCount:                   5",
+
+    /* for the text ruler */
+    "*rulerFont:               -*-helvetica-medium-r-normal--14-*-*-*-*-*-*-*",
+    "*rulerBorder:             5",
+
+    /* layout for the new, temporary preferences page */
+    "*toggleOptions.numColumns:                        6",     /* also used by Find */
+    "*Preferences*tabWidthPercentage:          0",
+    "*Preferences*tabs.shadowThickness:                2",
+    "*Preferences*tabs.font:   -*-helvetica-bold-r-normal--14-*-*-*-*-*-*-*",
+
+    /* --------------------------------------------------------------------- *
+     * anything below this point is only defined when we are not running CDE *
+     * --------------------------------------------------------------------- */
+
+    /* Do not define default colors when running under CDE
+     * (e.g. VUE on HPUX). The result is that you don't look
+     * like a normal desktop application
+     */
+    "?background:                      gray75",
+    "?screen.background:               wheat",
+    "?highlightColor:                  red",
+    "?Preferences*options.background:  gray90",
+};
+
+#if defined(__STDC__)
+static String  *get_fallback_rsrcs( String name )
+#else
+static String  *get_fallback_rsrcs( name )
+       String  name;
+#endif
+{
+    String     *copy = (String *) malloc( (1+XtNumber(fallback_rsrcs))*sizeof(String) );
+    int                i, running_cde;
+    Display    *d;
+
+    /* connect to server and see if the CDE atoms are present */
+    d = XOpenDisplay(0);
+    running_cde = is_cde( d );
+    XCloseDisplay(d);
+
+    for ( i=0; i<XtNumber(fallback_rsrcs); i++ ) {
+
+       /* stop here if running CDE */
+       if ( fallback_rsrcs[i][0] == '?' ) {
+           if ( running_cde ) break;
+           fallback_rsrcs[i] = strdup(fallback_rsrcs[i]);
+           fallback_rsrcs[i][0] = '*';
+       }
+
+       copy[i] = malloc( strlen(name) + strlen(fallback_rsrcs[i]) + 1 );
+       strcpy( copy[i], name );
+       strcat( copy[i], fallback_rsrcs[i] );
+    }
+
+    copy[i] = NULL;
+    return copy;
+}
+
+\f
+/* create the shell widgetry */
+
+#if defined(__STDC__)
+static void    create_top_level_shell( int *argc, char **argv )
+#else
+static void    create_top_level_shell( argc, argv )
+       int     *argc;
+       char    **argv;
+#endif
+{
+    char       *ptr;
+    Widget     main_w, editor;
+    Display    *display;
+
+    /* X gets quite upset if the program name is not simple */
+    if (( ptr = strrchr( argv[0], '/' )) != NULL ) argv[0] = ++ptr;
+    vi_progname = argv[0];
+
+    /* create a top-level shell for the window manager */
+    top_level = XtVaAppInitialize( &ctx,
+                                  vi_progname,
+                                  NULL, 0,     /* options */
+                                  (ArgcType) argc,
+                                  argv,        /* might get modified */
+                                  get_fallback_rsrcs( argv[0] ),
+                                  NULL
+                                  );
+    display = XtDisplay(top_level);
+
+    /* might need to go technicolor... */
+    XutInstallColormap( argv[0], top_level );
+
+    /* create our icon
+     * do this *before* realizing the shell widget in case the -iconic
+     * option was specified.
+     */
+    {
+#if defined(ColorIcon)
+    int                        nvi_width, nvi_height;
+    XpmAttributes      attr;
+
+    attr.valuemask = 0;
+    XpmCreatePixmapFromData( display,
+                            DefaultRootWindow(display),
+                            nvi_xpm,
+                            &icon_pm,
+                            NULL,
+                            &attr
+                            );
+    nvi_width = attr.width;
+    nvi_height = attr.height;
+#else
+    /* check the resource database for interesting resources */
+    __XutConvertResources( top_level,
+                        vi_progname,
+                        resource,
+                        XtNumber(resource)
+                        );
+
+    icon_pm = XCreatePixmapFromBitmapData(
+                       display,
+                       DefaultRootWindow(display),
+                       (char *) nvi_bits,
+                       nvi_width,
+                       nvi_height,
+                       icon_fg,
+                       icon_bg,
+                       DefaultDepth( display, DefaultScreen(display) )
+                       );
+#endif
+    XutSetIcon( top_level, nvi_height, nvi_width, icon_pm );
+    }
+
+    /* in the shell, we will stack a menubar an editor */
+    main_w = XtVaCreateManagedWidget( "main",
+                                     xmMainWindowWidgetClass,
+                                     top_level,
+                                     NULL
+                                     );
+
+    /* create the menubar */
+    XtManageChild( (Widget) vi_create_menubar( main_w ) );
+
+    /* add the VI widget from the library */
+    editor = vi_create_editor( "editor", main_w, onexit );
+
+    /* put it up */
+    XtRealizeWidget( top_level );
+
+    /* We *may* want all keyboard events to go to the editing screen.
+     * If the editor is the only widget in the shell that accepts
+     * keyboard input, then the user will expect that he can type when
+     * the pointer is over the scrollbar (for example).  This call
+     * causes that to happen.
+     */
+    XtSetKeyboardFocus( top_level, XtNameToWidget( editor, "*screen" ) );
+}
+
+\f
+int
+main(int argc, char **argv)
+{
+       IPVI* ipvi;
+       /*
+        * Initialize the X widgetry.  We must do this before picking off
+        * arguments as well-behaved X programs have common argument lists
+        * (e.g. -rv for reverse video).
+        */
+       create_top_level_shell(&argc, argv);
+
+       /* We need to know if the child process goes away. */
+       (void)signal(SIGCHLD, onchld);
+
+       vi_create(&ipvi, 0);
+       (void)ipvi->run(ipvi, argc, argv);
+       ipvi->new_window(ipvi,&ipvi_motif,-1);
+       ipvi_motif->set_ops(ipvi_motif, &ipsi_ops_motif);
+       /* Run vi: the parent returns, the child is the vi process. */
+       vi_ifd = ipvi_motif->ifd;
+       vi_ofd = ipvi_motif->ofd;
+       pid = ipvi->pid;
+
+       /* Tell X that we are interested in input on the pipe. */
+       XtAppAddInput(ctx, vi_ifd,
+           (XtPointer)XtInputReadMask, vi_input_func, NULL);
+
+       /* Main loop. */
+       XtAppMainLoop(ctx);
+
+       /* NOTREACHED */
+       abort();
+}
+
+static void
+XutSetIcon(Widget wid, int height, int width, Pixmap p)
+{
+    Display    *display = XtDisplay(wid);
+    Window     win;
+
+    /* best bet is to set the icon window */
+    XtVaGetValues( wid, XtNiconWindow, &win, 0 );
+
+    if ( win == None ) {
+       win = XCreateSimpleWindow( display,
+                                  RootWindow( display,
+                                  DefaultScreen( display ) ),
+                                  0, 0,
+                                  width, height,
+                                  0,
+                                  CopyFromParent,
+                                  CopyFromParent
+                                  );
+    }
+
+    if ( win != None ) {
+       XtVaSetValues( wid, XtNiconWindow, win, 0 );
+       XSetWindowBackgroundPixmap( display, win, p );
+    }
+
+    else {
+       /* do it the old fashioned way */
+       XtVaSetValues( wid, XtNiconPixmap, p, 0 );
+    }
+}
+
+/* Support for multiple colormaps
+ *
+ * XutInstallColormap( String name, Widget wid )
+ *     The first time called, this routine checks to see if the
+ *     resource "name*installColormap" is "True".  If so, the
+ *     widget is assigned a newly allocated colormap.
+ *
+ *     Subsequent calls ignore the "name" parameter and use the
+ *     same colormap.
+ *
+ *     Future versions of this routine may handle multiple colormaps
+ *     by name.
+ */
+static enum { cmap_look, cmap_use, cmap_ignore } cmap_state = cmap_look;
+
+static Boolean use_colormap = False;
+
+static XutResource     colormap_resources[] = {
+    { "installColormap",       XutRKboolean,   &use_colormap   }
+};
+
+static void
+XutInstallColormap(String name, Widget wid)
+{
+    static Colormap cmap = 0;
+    static Display  *cmap_display = 0;
+    Display    *display = XtDisplay(wid);
+
+    /* what is the current finite state? */
+    if ( cmap_state == cmap_look ) {
+
+       /* what does the resource say? */
+       __XutConvertResources( wid,
+                            name,
+                            colormap_resources,
+                            XtNumber(colormap_resources)
+                            );
+
+       /* was the result "True"? */
+       if ( ! use_colormap ) {
+           cmap_state = cmap_ignore;
+           return;
+       }
+
+       /* yes it was */
+       cmap_state = cmap_use;
+       cmap_display = display;
+       cmap = XCopyColormapAndFree( display,
+                                    DefaultColormap( display,
+                                                     DefaultScreen( display )
+                                                     )
+                                    );
+    }
+
+    /* use the private colormap? */
+    if ( cmap_state == cmap_use ) {
+       XtVaSetValues( wid, XtNcolormap, cmap, 0 );
+    }
+}
+
+/*
+ * onchld --
+ *     Handle SIGCHLD.
+ */
+static void
+onchld(int signo)
+{
+       /* If the vi process goes away, we exit as well. */
+       if (kill(pid, 0))
+               vi_fatal_message(top_level, "The vi process died.  Exiting.");
+}
+
+/*
+ * onexit --
+ *     Function called when the editor "quits".
+ */
+static void
+onexit(void)
+{
+       exit (0);
+}
diff --git a/dist/nvi/motif/nvi.xbm b/dist/nvi/motif/nvi.xbm
new file mode 100644 (file)
index 0000000..a9d4e23
--- /dev/null
@@ -0,0 +1,27 @@
+#define nvi_width 48
+#define nvi_height 48
+static unsigned char nvi_bits[] = {
+   0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab,
+   0x55, 0x55, 0x55, 0x55, 0x15, 0x56, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0xac,
+   0x55, 0x55, 0x55, 0x55, 0x05, 0x5c, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0xac,
+   0x55, 0x55, 0x55, 0x55, 0x05, 0x5c, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0xac,
+   0x55, 0x55, 0x55, 0x55, 0x15, 0x57, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0xab,
+   0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+   0xff, 0x57, 0x55, 0xff, 0xfd, 0x5f, 0x82, 0xab, 0xaa, 0xea, 0x2a, 0xae,
+   0x85, 0x55, 0x55, 0x65, 0x15, 0x56, 0x82, 0xab, 0xaa, 0xf2, 0x2a, 0xae,
+   0x05, 0x57, 0x55, 0x75, 0x15, 0x56, 0x0a, 0xab, 0xaa, 0xb2, 0x2a, 0xae,
+   0x05, 0x57, 0x55, 0x79, 0x15, 0x56, 0x0a, 0xae, 0xaa, 0xba, 0x2a, 0xae,
+   0x15, 0x56, 0x55, 0x59, 0x15, 0x56, 0x0a, 0xae, 0xaa, 0xbc, 0x2a, 0xae,
+   0x15, 0x5c, 0x55, 0x5d, 0x15, 0x56, 0x2a, 0xac, 0xaa, 0xac, 0x2a, 0xae,
+   0x15, 0x5c, 0x55, 0x5e, 0x15, 0x56, 0x2a, 0xb8, 0xaa, 0xae, 0x2a, 0xae,
+   0x55, 0x58, 0x55, 0x56, 0x15, 0x56, 0x2a, 0xb8, 0x2a, 0xaf, 0x2a, 0xae,
+   0x55, 0x70, 0x55, 0x57, 0x15, 0x56, 0xaa, 0xb0, 0x2a, 0xab, 0x2a, 0xae,
+   0x55, 0x70, 0x95, 0x57, 0x15, 0x56, 0xaa, 0xe0, 0xaa, 0xab, 0x2a, 0xae,
+   0x55, 0x61, 0x95, 0x55, 0x15, 0x56, 0xaa, 0xe0, 0xca, 0xab, 0x2a, 0xae,
+   0x55, 0xc1, 0xd5, 0x55, 0x15, 0x56, 0xaa, 0xc2, 0xca, 0xaa, 0x2a, 0xae,
+   0x55, 0xc1, 0xe5, 0x55, 0x15, 0x56, 0xaa, 0x82, 0xeb, 0xaa, 0x2a, 0xae,
+   0x55, 0x85, 0x65, 0x55, 0x15, 0x56, 0xaa, 0x82, 0xf3, 0xaa, 0x2a, 0xae,
+   0x55, 0x05, 0x77, 0x55, 0x15, 0x56, 0xaa, 0x0a, 0xb3, 0xaa, 0x2a, 0xae,
+   0x55, 0x05, 0x79, 0x55, 0x15, 0x56, 0xaa, 0x0a, 0xba, 0xaa, 0x2a, 0xae,
+   0x55, 0x15, 0x58, 0x55, 0x15, 0x56, 0xaa, 0x0a, 0xac, 0xaa, 0x2a, 0xae,
+   0x55, 0xf5, 0x5f, 0x55, 0xfd, 0x5f, 0xaa, 0xea, 0xaf, 0xaa, 0xfa, 0xaf};
diff --git a/dist/nvi/motif/nvi.xpm b/dist/nvi/motif/nvi.xpm
new file mode 100644 (file)
index 0000000..b891cac
--- /dev/null
@@ -0,0 +1,56 @@
+/* XPM */
+static char * nvi_xpm[] = {
+"48 48 5 1",
+"      c #000000000000",
+".     c #FFFF00000000",
+"X     c #FFFFFFFF0000",
+"o     c #00000000FFFF",
+"O     c #FFFFFFFFFFFF",
+"               ....XXXXoXXXXXXXXXXXXXXXXXXXXXXXX",
+"               ...XXXooXXXXXXXXXXXXXXXXXoXXXXXXX",
+"              ....XXXooXXXoo.ooooXXXXXXXXoXXXXXX",
+"              ...XXXo. oooo..oooooooXXXXXooXXXXX",
+"             ....XXXo.. o....o.. . ooXXXXooXXXXX",
+"             ...XXXXo. o..OO...OO . ooXXo..oXXXX",
+"            ....XXXXo ...OOO.oOOOO...ooo. .oXXXX",
+"            ...XXXXXXo...  O.O  OOo... . . oXXXX",
+"           ....XXXXXXXo. O O. O  Oo . . . oXXXXX",
+"           ...XXXXXXXXX. O Oo O  Oo. . . oXXXXXX",
+"          ....XXXXXXXXXoo  o.o   Oo . . oXXXXXXX",
+"          ...XX XXXXXXo..oo..o  Oo.. . oXXXXXXXX",
+"         ....XXX   XXo.. o....ooo . . oXXXXXXXXX",
+"         ...XXXXX   Xo. .o.. o ... . .oXXXXXXXXX",
+"        ....XXXXXXX  Xo. .ooo ... . .ooXXXXXXXXX",
+"        ...XX     XX XXoo .. . o . .ooXXXXXXXXXX",
+"       ....XXXX O XX XXXoo  .oo . .ooXXXXXXXXXXX",
+"       ...XXXXX      XXXXXooo. . ooXXXXXXXXXXXXX",
+"      ....XXXXXXXXX    ooXXXooooooXXXXXXXXXXXXXX",
+"      ...XXX  X XXX X   ..oo. . ..ooXXXXXXXXXXXX",
+"     ....XXXX   XX  XXXo.. ..... .oooXXXXXXXXXXX",
+"     ...XXXXXXX    XXXXo o. ooo .o.ooXXXXXXXXXXX",
+"    ....XXXXXXXXXXXXXXXo.. .o..ooo oooXXXXXXXXXX",
+"    ...XXXXXXXXXXXXXXXXXo .o.o. . ..ooXXXXXXXXXX",
+"   ....XXXXXXXXXXXXXXXXXXooo.. . . .ooXXXXXXXXXX",
+"   ...XXXXXXXXXXXXXXXXXXXXo . . . .oooXXXXXXXXXX",
+"  ....XXXXXXXXXXXXXXXXXXXXoooo . .o.oXXXXXXXXXXX",
+"  ...XXXXXXXXXXXXXXXXXXXXXo.. oooo. ooXXXXXXXXXX",
+" ....XXXXXXXXXXXXXXXXXXXXXo... . . .ooXXXXXXXXXX",
+" ...XXXXXXXXXXXXXXXXXXXXXXo...... . . oXXXXXXXXX",
+".....XXXXXXXXXXXXXXXXXXXXXXo . . . . .ooXXXXXXXX",
+" ......XXXXXXXXXXXXXXXXXXXXo. . . . . oooXXXXXXX",
+"   ......XXXXXXXXXXXXXXXXXXo   o   o o ooooXXXXX",
+"     ......XXXXXXXXXXXXXX   .O..O.O.. o . ooXXXX",
+"       ......XXXXXXXXXXooO O    .... OoX o oooXX",
+"         ......XXXXXXXo O O  O O .. ..oXXXo .ooX",
+"           ......XXXXXoO O  O O    O ooXXXXX .o ",
+"             ......XXXXooooo O O OOooXXXXXXXX o ",
+"               ......XXXXXXXoooooooXXXXXoXXXXX.o",
+"                 ......XXXXXXXXXXXXXXooooXXXXXo.",
+"                   ......XXXXXXXXXXoo...oXXXoo. ",
+"                     ......XXXXX o.o o o.ooo . o",
+"                       ......XXXXXXXXXooooo o oX",
+"                         ......XXXXXXXXXXXXXXXXX",
+"                           ......XXXXXXXXXXXXXXX",
+"                             ......XXXXXXXXXXXXX",
+"                               ......XXXXXXXXXXX",
+"                                 ......XXXXXXXXX"};
diff --git a/dist/nvi/motif_l/TODO b/dist/nvi/motif_l/TODO
new file mode 100644 (file)
index 0000000..0dcd60a
--- /dev/null
@@ -0,0 +1,90 @@
+Top priority would be the mouse.  We need to get cut&paste working.
+(Including extend beyond the visible screen.  I believe I'm sending
+the correct mouse events for that, but I haven't tested it.)
+
+=-=-=-=
+Find a tool to convert the reference doc to html, and just point a
+browser at it for the help screen.  Have "novice", "fast lookup"
+and an "everything" version.
+
+=-=-=-=
+Disassociate scrollbar actions from the cursor, i.e. when you
+scroll the screen moves but the cursor doesn't.
+
+>> However, it seems to me that the cursor should disappear from
+>> the screen as soon as it's no longer positioned on a line that's
+>> on the screen.  Does that make sense?  And, if so, how do we
+>> make that happen?
+>
+> I'd add a message:
+>       IPO_DISPLAY_CARET( boolean )
+> since the caret is also used for the current drawing position, we
+> really can't move it 'off the screen'.
+
+=-=-=-=
+>> BTW, this may be a bug, I can't seem to erase characters in the 
+>> colon command line. 
+>  
+> It's a bug that I reported earlier.  Core is not (correctly) reading the
+> tty options for the terminal.  Since we have not bound magic 
+> characters (VI_BACKSPACE) to BackSpace and Delete keys, the 
+> editing here is counter-intuitive.  I'd guess that you use 
+> Delete for Tty Erase.  Try ^H in the colon line and see what happens.
+
+=-=-=-=
+Implement a "word search" button for the search dialog -- it's not
+trivial, the ex/ex_subst.c/re_compile() routine is going to have to
+allocate memory for the pattern which isn't going to make it happy.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/* TODO List:
+ *     scrollbars      Need protocol messages that tell us what to display
+ *                     in the scrollbars.  Suggestion:
+ *                             scrollbar( bottom, lines, home )
+ *                             bottom is $
+ *                             lines is lines shown in the window
+ *                                     (takes wrap into account)
+ *                             home is the line number ot the top visible line
+ *
+ *                     On the way back send scroll( top )
+ *
+ *                     User should be able to enable/disable bar display
+ *
+ *                     <yuch!> horizontal scrollbar
+ *
+ *     expose_func
+ *     insert/delete   When we have a partially obscured window, we only
+ *                     refresh a single line after scrolling.  I believe this
+ *                     is due to the exposure events all showing up after
+ *                     the scrolling is completed (pipe_input_func does all
+ *                     of the scrolling and then we get back to XtMainLoop)
+ *
+ *     split           Ought to be able to put a title on each pane
+ *                     Need protocol messages to shift focus
+ *
+ *     bell            user settable visible bell
+ *
+ *     busy            don't understand the protocol
+ *
+ *     mouse           need to send IPO_MOVE_CARET( row, column )
+ *                     (note that screen code does not know about tabs or
+ *                     line wraps)
+ *                     Connect to window manager cut buffer
+ *                     need to send IPO_EXTEND_SELECT( r1, c1, r2, c1 )
+ *                     otherwise core and screen duplicate selection logic
+ *                     Need to determine correct screen for event.  Not
+ *                     needed until split is implemented.
+ *
+ *     arrow keys      need to define a protocol.  I can easily send
+ *                     the vt100 sequences (and currently do).
+ *                     In general, we need to define what special keys
+ *                     do (for example PageUp) and what happens when we
+ *                     are in Insert mode.
+ *
+ *                     Suggestion: IPO_COMMAND( string ).  vi core can
+ *                     take it as a command even when in insert mode.
+ *
+ *     icon            Is currently B&W.  To get a color icon, would
+ *                     require a lot of work or that bostic pick up
+ *                     the xpm library.
+ */
diff --git a/dist/nvi/motif_l/extern.h b/dist/nvi/motif_l/extern.h
new file mode 100644 (file)
index 0000000..fd7b157
--- /dev/null
@@ -0,0 +1,31 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:33 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+void __vi_InitCopyPaste
+   __P((int (*)(), int (*)(), int (*)(), int (*)())); 
+void   __vi_AcquirePrimary __P((Widget));
+void   __vi_PasteFromClipboard __P((Widget));
+void __vi_send_command_string __P((String));
+void __vi_cancel_cb __P((Widget, XtPointer, XtPointer));
+void __vi_modal_dialog __P((Widget));
+Widget vi_create_menubar __P((Widget));
+int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
+void __vi_show_options_dialog __P((Widget, String));
+int __vi_toggle __P((char *));
+Widget __vi_create_search_toggles __P((Widget, optData[]));
+void __vi_set_text_ruler __P((int, int));
+void __vi_search __P((Widget));
+void __XutConvertResources __P((Widget, String, XutResource *, int));
+void __vi_set_scroll_block __P((void));
+void __vi_clear_scroll_block __P((void));
+void vi_input_func __P((XtPointer, int *, XtInputId *));
+void   __vi_draw_text __P((xvi_screen *, int, int, int));
+void   __vi_expose_func __P((Widget, XtPointer, XtPointer));
+Widget vi_create_editor __P((String, Widget, void (*)(void)));
+void __vi_set_cursor __P((xvi_screen *, int));
+void __vi_set_word_at_caret __P((xvi_screen *));
+void draw_caret __P((xvi_screen *));
+void __vi_erase_caret __P((xvi_screen *));
+void   __vi_move_caret __P((xvi_screen *, int, int));
+Widget __vi_CreateTabbedFolder
+    __P((String, Widget, String, int, void (*)(Widget, int)));
diff --git a/dist/nvi/motif_l/m_copypaste.c b/dist/nvi/motif_l/m_copypaste.c
new file mode 100644 (file)
index 0000000..b740914
--- /dev/null
@@ -0,0 +1,246 @@
+/*     $NetBSD: m_copypaste.c,v 1.1.1.2 2008/05/18 14:31:26 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_copypaste.c,v 8.10 2003/11/05 17:09:59 skimo Exp (Berkeley) Date: 2003/11/05 17:09:59";
+#endif /* not lint */
+
+/* ICCCM Cut and paste Utilities: */
+
+#include       <sys/types.h>
+#include       <sys/queue.h>
+
+#include       <X11/X.h>
+#include       <X11/Intrinsic.h>
+#include       <X11/Xatom.h>
+
+#include       <bitstring.h>
+#include       <stdio.h>
+
+#undef LOCK_SUCCESS
+#include       "../common/common.h"
+#include       "../ipc/ip.h"
+#include       "m_motif.h"
+
+typedef        int     (*PFI)();
+
+static PFI     icccm_paste,
+               icccm_copy,
+               icccm_clear,
+               icccm_error;
+
+/*
+ * InitCopyPaste --
+ *
+ * PUBLIC: void __vi_InitCopyPaste
+ * PUBLIC:    __P((int (*)(), int (*)(), int (*)(), int (*)())); 
+ */
+void
+__vi_InitCopyPaste(PFI f_copy, PFI f_paste, PFI f_clear, PFI f_error)
+{
+    icccm_paste        = f_paste;
+    icccm_clear        = f_clear;
+    icccm_copy = f_copy;
+    icccm_error        = f_error;
+}
+
+
+#if defined(__STDC__)
+static void    peekProc( Widget widget,
+                         void *data,
+                         Atom *selection,
+                         Atom *type,
+                         void *value,
+                         unsigned long *length,
+                         int *format
+                         )
+#else
+static void    peekProc( widget, data, selection, type, value, length, format )
+       Widget  widget;
+       void    *data;
+       Atom    *selection, *type;
+       void    *value;
+       unsigned long *length;
+       int     *format;
+#endif
+{
+    if ( *type == 0 )
+       (*icccm_error)( stderr, "Nothing in the primary selection buffer");
+    else if ( *type != XA_STRING )
+       (*icccm_error)( stderr, "Unknown type return from selection");
+    else
+       XtFree( value );
+}
+
+
+#if 0
+#if defined(__STDC__)
+void   _vi_AcquireClipboard( Widget wid )
+#else
+void   _vi_AcquireClipboard( wid )
+Widget wid;
+#endif
+{
+    XtGetSelectionValue( wid,
+                        XA_PRIMARY,
+                        XA_STRING,
+                        (XtSelectionCallbackProc) peekProc,
+                        NULL,
+                        XtLastTimestampProcessed( XtDisplay(wid) )
+                        );
+}
+#endif
+
+
+#if defined(__STDC__)
+static void    loseProc( Widget widget )
+#else
+static void    loseProc( widget )
+       Widget  widget;
+#endif
+{
+    /* we have lost ownership of the selection.  clear it */
+    (*icccm_clear)( widget );
+
+    /* also participate in the protocols */
+    XtDisownSelection( widget,
+                       XA_PRIMARY,
+                       XtLastTimestampProcessed( XtDisplay(widget) )
+                       );
+}
+
+
+#if defined(__STDC__)
+static int convertProc( Widget widget,
+                    Atom *selection,
+                    Atom *target,
+                    Atom *type,
+                    void **value,
+                    int *length,
+                    int *format
+                    )
+#else
+static int convertProc( widget, selection, target, type, value, length, format )
+Widget widget;
+Atom   *selection, *target, *type;
+void   **value;
+int    *length;
+int    *format;
+#endif
+{
+    String     buffer;
+    int                len;
+
+    /* someone wants a copy of the selection.  is there one? */
+    (*icccm_copy)( &buffer, &len );
+    if ( len == 0 ) return False;
+
+    /* do they want the string? */
+    if ( *target == XA_STRING ) {
+       *length = len;
+       *value  = (void *) XtMalloc( len );
+       *type   = XA_STRING;
+       *format = 8;
+       memcpy( (char *) *value, buffer, *length );
+       return True;
+       }
+
+    /* do they want the length? */
+    if ( *target == XInternAtom( XtDisplay(widget), "LENGTH", FALSE) ) {
+       *length = 1;
+       *value  = (void *) XtMalloc( sizeof(int) );
+       *type   = *target;
+       *format = 32;
+       * ((int *) *value) = len;
+       return True;
+       }
+
+    /* we lose */
+    return False;
+}
+
+/*
+ * __vi_AcquirePrimary --
+ *
+ * PUBLIC: void        __vi_AcquirePrimary __P((Widget));
+ */
+void 
+__vi_AcquirePrimary(Widget widget)
+{
+    /* assert we own the primary selection */
+    XtOwnSelection( widget,
+                   XA_PRIMARY,
+                   XtLastTimestampProcessed( XtDisplay(widget) ),
+                   (XtConvertSelectionProc) convertProc,
+                   (XtLoseSelectionProc) loseProc,
+                   NULL
+                   );
+
+#if defined(OPENLOOK)
+    /* assert we also own the clipboard */
+    XtOwnSelection( widget,
+                   XA_CLIPBOARD( XtDisplay(widget) ),
+                   XtLastTimestampProcessed( XtDisplay(widget) ),
+                   convertProc,
+                   loseProc,
+                   NULL
+                   );
+#endif
+}
+
+
+#if defined(__STDC__)
+static void    gotProc( Widget widget,
+                        void *data,
+                        Atom *selection,
+                        Atom *type,
+                        void *value,
+                        unsigned long *length,
+                        int *format
+                        )
+#else
+static void    gotProc( widget, data, selection, type, value, length, format )
+       Widget  widget;
+       void    *data;
+       Atom    *selection, *type;
+       void    *value;
+       unsigned long *length;
+       int     *format;
+#endif
+{
+    if ( *type == 0 )
+       (*icccm_error)( stderr, "Nothing in the primary selection buffer");
+    else if ( *type != XA_STRING )
+       (*icccm_error)( stderr, "Unknown type return from selection");
+    else {
+       (*icccm_paste)( widget, value, *length );
+       XtFree( value );
+    }
+}
+
+/*
+ * __vi_PasteFromClipboard --
+ *
+ * PUBLIC: void        __vi_PasteFromClipboard __P((Widget));
+ */
+void
+__vi_PasteFromClipboard(Widget widget)
+{
+    XtGetSelectionValue( widget,
+                        XA_PRIMARY,
+                        XA_STRING,
+                        (XtSelectionCallbackProc) gotProc,
+                        NULL,
+                        XtLastTimestampProcessed( XtDisplay(widget) )
+                        );
+}
diff --git a/dist/nvi/motif_l/m_func.c b/dist/nvi/motif_l/m_func.c
new file mode 100644 (file)
index 0000000..64cc0aa
--- /dev/null
@@ -0,0 +1,381 @@
+/*     $NetBSD: m_func.c,v 1.1.1.2 2008/05/18 14:31:26 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_func.c,v 8.28 2003/11/05 17:09:59 skimo Exp (Berkeley) Date: 2003/11/05 17:09:59";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <Xm/PanedW.h>
+#include <Xm/ScrollBar.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+
+\f
+static int
+vi_addstr(int ipvi, char *str1, u_int32_t len1)
+{
+#ifdef TRACE
+       vtrace("addstr() {%.*s}\n", ipbp->len1, ipbp->str1);
+#endif
+       /* Add to backing store. */
+       memcpy(CharAt(__vi_screen, __vi_screen->cury, __vi_screen->curx),
+           str1, len1);
+       memset(FlagAt(__vi_screen, __vi_screen->cury, __vi_screen->curx),
+           __vi_screen->color, len1);
+
+       /* Draw from backing store. */
+       __vi_draw_text(__vi_screen,
+           __vi_screen->cury, __vi_screen->curx, len1);
+
+       /* Advance the caret. */
+       __vi_move_caret(__vi_screen,
+           __vi_screen->cury, __vi_screen->curx + len1);
+       return (0);
+}
+
+static int
+vi_attribute(int ipvi, u_int32_t val1, u_int32_t val2)
+{
+       switch (val1) {
+       case SA_ALTERNATE:
+               /* XXX: Nothing. */
+               break;
+       case SA_INVERSE:
+               __vi_screen->color = val2;
+               break;
+       }
+       return (0);
+}
+
+static int
+vi_bell(int ipvi)
+{
+       /*
+        * XXX
+        * Future... implement visible bell.
+        */
+       XBell(XtDisplay(__vi_screen->area), 0);
+       return (0);
+}
+
+static int
+vi_busyon(int ipvi, char *str1, u_int32_t len1)
+{
+       __vi_set_cursor(__vi_screen, 1);
+       return (0);
+}
+
+static int
+vi_busyoff(int ipvi)
+{
+       __vi_set_cursor(__vi_screen, 0);
+       return (0);
+}
+
+static int
+vi_clrtoeol(int ipvi)
+{
+       int len;
+       char *ptr;
+
+       len = __vi_screen->cols - __vi_screen->curx;
+       ptr = CharAt(__vi_screen, __vi_screen->cury, __vi_screen->curx);
+       
+       /* Clear backing store. */
+       memset(ptr, ' ', len);
+       memset(FlagAt(__vi_screen, __vi_screen->cury, __vi_screen->curx),
+           COLOR_STANDARD, len);
+
+       /* Draw from backing store. */
+       __vi_draw_text(__vi_screen, __vi_screen->cury, __vi_screen->curx, len);
+
+       return (0);
+}
+
+static int
+vi_deleteln(int ipvi)
+{
+       int y, rows, len, height, width;
+
+       y = __vi_screen->cury;
+       rows = __vi_screen->rows - (y+1);
+       len = __vi_screen->cols * rows;
+
+       /* Don't want to copy the caret! */
+       __vi_erase_caret(__vi_screen);
+
+       /* Adjust backing store and the flags. */
+       memmove(CharAt(__vi_screen, y, 0), CharAt(__vi_screen, y+1, 0), len);
+       memmove(FlagAt(__vi_screen, y, 0), FlagAt(__vi_screen, y+1, 0), len);
+
+       /* Move the bits on the screen. */
+       width = __vi_screen->ch_width * __vi_screen->cols;
+       height = __vi_screen->ch_height * rows;
+       XCopyArea(XtDisplay(__vi_screen->area),         /* display */
+                 XtWindow(__vi_screen->area),          /* src */
+                 XtWindow(__vi_screen->area),          /* dest */
+                 __vi_copy_gc,                         /* context */
+                 0, YTOP(__vi_screen, y+1),            /* srcx, srcy */
+                 width, height,
+                 0, YTOP(__vi_screen, y)               /* dstx, dsty */
+                 );
+       /* Need to let X take over. */
+       XmUpdateDisplay(__vi_screen->area);
+
+       return (0);
+}
+
+static int
+vi_discard(int ipvi)
+{
+       /* XXX: Nothing. */
+       return (0);
+}
+
+static int
+vi_insertln(int ipvi)
+{
+       int y, rows, height, width;
+       char *from, *to;
+
+       y = __vi_screen->cury;
+       rows = __vi_screen->rows - (1+y);
+       from = CharAt(__vi_screen, y, 0),
+       to = CharAt(__vi_screen, y+1, 0);
+
+       /* Don't want to copy the caret! */
+       __vi_erase_caret(__vi_screen);
+
+       /* Adjust backing store. */
+       memmove(to, from, __vi_screen->cols * rows);
+       memset(from, ' ', __vi_screen->cols);
+
+       /* And the backing store. */
+       from = FlagAt(__vi_screen, y, 0),
+       to = FlagAt(__vi_screen, y+1, 0);
+       memmove(to, from, __vi_screen->cols * rows);
+       memset(from, COLOR_STANDARD, __vi_screen->cols);
+
+       /* Move the bits on the screen. */
+       width = __vi_screen->ch_width * __vi_screen->cols;
+       height = __vi_screen->ch_height * rows;
+
+       XCopyArea(XtDisplay(__vi_screen->area),         /* display */
+                 XtWindow(__vi_screen->area),          /* src */
+                 XtWindow(__vi_screen->area),          /* dest */
+                 __vi_copy_gc,                         /* context */
+                 0, YTOP(__vi_screen, y),              /* srcx, srcy */
+                 width, height,
+                 0, YTOP(__vi_screen, y+1)             /* dstx, dsty */
+                 );
+
+       /* clear out the new space */
+       XClearArea(XtDisplay(__vi_screen->area),        /* display */
+                  XtWindow(__vi_screen->area),         /* window */
+                  0, YTOP(__vi_screen, y),             /* srcx, srcy */
+                  0, __vi_screen->ch_height,           /* w=full, height */
+                  True                                 /* no exposures */
+                  );
+
+       /* Need to let X take over. */
+       XmUpdateDisplay(__vi_screen->area);
+
+       return (0);
+}
+
+static int
+vi_move(int ipvi, u_int32_t val1, u_int32_t val2)
+{
+       __vi_move_caret(__vi_screen, val1, val2);
+       return (0);
+}
+
+static int
+vi_redraw(int ipvi)
+{
+       __vi_expose_func(0, __vi_screen, 0);
+       return (0);
+}
+
+static int
+vi_refresh(int ipvi)
+{
+       /* probably ok to scroll again */
+       __vi_clear_scroll_block();
+
+       /* if the tag stack widget is active, set the text field there
+        * to agree with the current caret position.
+        * Note that this really ought to be done by core due to wrapping issues
+        */
+       __vi_set_word_at_caret( __vi_screen );
+
+       /* similarly, the text ruler... */
+       __vi_set_text_ruler( __vi_screen->cury, __vi_screen->curx );
+
+       return (0);
+}
+
+static int
+vi_quit(int ipvi)
+{
+       if (__vi_exitp != NULL)
+               __vi_exitp();
+
+       return (0);
+}
+
+static int
+vi_rename(int ipvi, char *str1, u_int32_t len1)
+{
+       Widget shell;
+       size_t len;
+       const char *tail, *p;
+
+       /* For the icon, use the tail. */
+       for (p = str1, len = len1; len > 1; ++p, --len)
+               if (p[0] == '/')
+                       tail = p + 1;
+       /*
+        * XXX
+        * Future:  Attach a title to each screen.  For now, we change
+        * the title of the shell.
+        */
+       shell = __vi_screen->area;
+       while ( ! XtIsShell(shell) ) shell = XtParent(shell);
+       XtVaSetValues(shell,
+                     XmNiconName,      tail,
+                     XmNtitle,         str1,
+                     0
+                     );
+       return (0);
+}
+
+static int
+vi_rewrite(int ipvi, u_int32_t val1)
+{
+       /* XXX: Nothing. */
+       return (0);
+}
+
+
+static int
+vi_scrollbar(int ipvi, u_int32_t val1, u_int32_t val2, u_int32_t val3)
+{
+       int top, size, maximum, old_max;
+
+       /* in the buffer,
+        *      val1 contains the top visible line number
+        *      val2 contains the number of visible lines
+        *      val3 contains the number of lines in the file
+        */
+       top     = val1;
+       size    = val2;
+       maximum = val3;
+
+#if 0
+       fprintf( stderr, "Setting scrollbar\n" );
+       fprintf( stderr, "\tvalue\t\t%d\n",     top );
+       fprintf( stderr, "\tsize\t\t%d\n",      size );
+       fprintf( stderr, "\tmaximum\t\t%d\n",   maximum );
+#endif
+
+       /* armor plating.  core thinks there are no lines in an
+        * empty file, but says we are on line 1
+        */
+       if ( top >= maximum ) {
+#if 0
+           fprintf( stderr, "Correcting for top >= maximum\n" );
+#endif
+           maximum     = top + 1;
+           size        = 1;
+       }
+
+       /* armor plating.  core may think there are more
+        * lines visible than remain in the file
+        */
+       if ( top+size >= maximum ) {
+#if 0
+           fprintf( stderr, "Correcting for top+size >= maximum\n" );
+#endif
+           size        = maximum - top;
+       }
+
+       /* need to increase the maximum before changing the values */
+       XtVaGetValues( __vi_screen->scroll, XmNmaximum, &old_max, 0 );
+       if ( maximum > old_max )
+           XtVaSetValues( __vi_screen->scroll, XmNmaximum, maximum, 0 );
+
+       /* change the rest of the values without generating a callback */
+       XmScrollBarSetValues( __vi_screen->scroll,
+                             top,
+                             size,
+                             1,        /* increment */
+                             size,     /* page_increment */
+                             False     /* do not notify me */
+                             );
+
+       /* need to decrease the maximum after changing the values */
+       if ( maximum < old_max )
+           XtVaSetValues( __vi_screen->scroll, XmNmaximum, maximum, 0 );
+
+       /* done */
+       return (0);
+}
+
+static int
+vi_select(int ipvi, char *str1, u_int32_t len1)
+{
+       /* XXX: Nothing. */
+       return (0);
+}
+
+static int
+vi_split(int ipvi)
+{
+       /* XXX: Nothing. */
+       return (0);
+}
+
+IPSIOPS ipsi_ops_motif = {
+       vi_addstr,
+       vi_attribute,
+       vi_bell,
+       vi_busyoff,
+       vi_busyon,
+       vi_clrtoeol,
+       vi_deleteln,
+       vi_discard,
+       __vi_editopt,
+       vi_insertln,
+       vi_move,
+       vi_quit,
+       vi_redraw,
+       vi_refresh,
+       vi_rename,
+       vi_rewrite,
+       vi_scrollbar,
+       vi_select,
+       vi_split,
+       vi_addstr,
+};
diff --git a/dist/nvi/motif_l/m_menu.c b/dist/nvi/motif_l/m_menu.c
new file mode 100644 (file)
index 0000000..d5d4580
--- /dev/null
@@ -0,0 +1,541 @@
+/*     $NetBSD: m_menu.c,v 1.1.1.2 2008/05/18 14:31:27 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_menu.c,v 8.26 2003/11/05 17:09:59 skimo Exp (Berkeley) Date: 2003/11/05 17:09:59";
+#endif /* not lint */
+
+#include <sys/queue.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <Xm/PushB.h>
+#include <Xm/CascadeB.h>
+#include <Xm/RowColumn.h>
+#include <Xm/Separator.h>
+#include <Xm/FileSB.h>
+#include <Xm/SelectioB.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+
+extern int vi_ofd;
+
+/* save this for creation of children */
+static Widget  main_widget = NULL;
+
+/* This module defines the menu structure for vi.  Each menu
+ * item has an action routine associated with it.  For the most
+ * part, those actions will simply call vi_send with vi commands.
+ * others will pop up file selection dialogs and use them for
+ * vi commands, and other will have to have special actions.
+ *
+ * Future:
+ *     vi core will have to let us know when to be sensitive
+ *     change VI_STRING to VI_COMMAND so that menu actions cannot
+ *             be confusing when in insert mode
+ *     need VI_CUT, VI_COPY, and VI_PASTE to perform the appropriate
+ *             operations on the visible text of yank buffer.  VI_COPY
+ *             is likely a NOP, but it will make users happy
+ *     add mnemonics
+ *     add accelerators
+ *     implement file selection dialog boxes
+ *     implement string prompt dialog boxes (e.g. for 'find')
+ *
+ * Interface:
+ *     Widget  create_menubar( Widget parent ) creates and returns the
+ *             X menu structure.  The caller can place this
+ *             anywhere in the widget heirarchy.
+ */
+
+#define        BufferSize      1024
+
+/*
+ * __vi_send_command_string --
+ *     Utility:  Send a menu command to vi
+ *
+ * Future:
+ * Change VI_STRING to VI_COMMAND so that menu actions cannot be confusing
+ * when in insert mode.
+ *
+ * XXX
+ * THIS SHOULD GO AWAY -- WE SHOULDN'T SEND UNINTERPRETED STRINGS TO THE
+ * CORE.
+ *
+ * PUBLIC: void __vi_send_command_string __P((String));
+ */
+void
+__vi_send_command_string(String str)
+{
+    IP_BUF     ipb;
+    char       buffer[BufferSize];
+
+    /* Future:  Need VI_COMMAND so vi knows this is not text to insert
+     * At that point, appending a cr/lf will not be necessary.  For now,
+     * append iff we are a colon or slash command.  Of course, if we are in
+     * insert mode, all bets are off.
+     */
+    strcpy( buffer, str );
+    switch ( *str ) {
+       case ':':
+       case '/':
+           strcat( buffer, "\n" );
+           break;
+    }
+
+    ipb.code = VI_STRING;
+    ipb.str1 = buffer;
+    ipb.len1 = strlen(buffer);
+    vi_send(vi_ofd, "a", &ipb);
+}
+
+\f
+/* Utility:  beep for unimplemented command */
+
+#if defined(__STDC__)
+static void    send_beep( Widget w )
+#else
+static void    send_beep( w )
+       Widget  w;
+#endif
+{
+    XBell( XtDisplay(w), 0 );
+}
+
+\f
+/*
+ * __vi_cancel_cb --
+ *     Utility:  make a dialog box go Modal
+ *
+ * PUBLIC: void __vi_cancel_cb __P((Widget, XtPointer, XtPointer));
+ */
+static Bool    have_answer;
+void
+__vi_cancel_cb(Widget w, XtPointer client_data, XtPointer call_data)
+{
+       have_answer = True;
+}
+
+/*
+ * PUBLIC: void __vi_modal_dialog __P((Widget));
+ */
+void
+__vi_modal_dialog(Widget db)
+{
+    XtAppContext       ctx;
+
+    /* post the dialog */
+    XtManageChild( db );
+    XtPopup( XtParent(db), XtGrabExclusive );
+
+    /* wait for a response */
+    ctx = XtWidgetToApplicationContext(db);
+    XtAddGrab( XtParent(db), TRUE, FALSE );
+    for ( have_answer = False; ! have_answer; )
+       XtAppProcessEvent( ctx, XtIMAll );
+
+    /* done with db */
+    XtPopdown( XtParent(db) );
+    XtRemoveGrab( XtParent(db) );
+}
+
+\f
+/* Utility:  Get a file (using standard File Selection Dialog Box) */
+
+static String  file_name;
+
+
+#if defined(__STDC__)
+static void            ok_file_name( Widget w,
+                                     XtPointer client_data,
+                                     XtPointer call_data
+                                     )
+#else
+static void            ok_file_name( w, client_data, call_data )
+       Widget          w;
+       XtPointer       client_data;
+       XtPointer       call_data;
+#endif
+{
+    XmFileSelectionBoxCallbackStruct   *cbs;
+
+    cbs = (XmFileSelectionBoxCallbackStruct *) call_data;
+    XmStringGetLtoR( cbs->value, XmSTRING_DEFAULT_CHARSET, &file_name );
+
+    have_answer = True;
+}
+
+
+#if defined(__STDC__)
+static String  get_file( Widget w, String prompt )
+#else
+static String  get_file( w, prompt )
+       Widget  w;
+       String  prompt;
+#endif
+{
+    /* make it static so we can reuse it */
+    static     Widget  db;
+
+    /* our return parameter */
+    if ( file_name != NULL ) {
+       XtFree( file_name );
+       file_name = NULL;
+    }
+
+    /* create one? */
+    if ( db == NULL ){ 
+       db = XmCreateFileSelectionDialog( main_widget, "file", NULL, 0 );
+       XtAddCallback( db, XmNokCallback, ok_file_name, NULL );
+       XtAddCallback( db, XmNcancelCallback, __vi_cancel_cb, NULL );
+    }
+
+    /* use the title as a prompt */
+    XtVaSetValues( XtParent(db), XmNtitle, prompt, 0 );
+
+    /* wait for a response */
+    __vi_modal_dialog( db );
+
+    /* done */
+    return file_name;
+}
+
+\f
+/*
+ * file_command --
+ *     Get a file name and send it with the command to the core.
+ */
+static void
+file_command(Widget w, int code, String prompt)
+{
+       IP_BUF ipb;
+       char *file;
+
+       if ((file = get_file(w, prompt)) != NULL) {
+               ipb.code = code;
+               ipb.str1 = file;
+               ipb.len1 = strlen(file);
+               vi_send(vi_ofd, "a", &ipb);
+       }
+}
+
+\f
+/*
+ * Menu action routines (one per menu entry)
+ *
+ * These are in the order in which they appear in the menu structure.
+ */
+static void
+ma_edit_file(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       file_command(w, VI_EDIT, "Edit");
+}
+
+static void
+ma_split(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       file_command(w, VI_EDITSPLIT, "Edit");
+}
+
+static void
+ma_save(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       IP_BUF ipb;
+
+       ipb.code = VI_WRITE;
+       (void)vi_send(vi_ofd, NULL, &ipb);
+}
+
+static void
+ma_save_as(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       file_command(w, VI_WRITEAS, "Save As");
+}
+
+static void
+ma_wq(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       IP_BUF ipb;
+
+       ipb.code = VI_WQ;
+       (void)vi_send(vi_ofd, NULL, &ipb);
+}
+
+static void
+ma_quit(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       IP_BUF ipb;
+
+       ipb.code = VI_QUIT;
+       (void)vi_send(vi_ofd, NULL, &ipb);
+}
+
+static void
+ma_undo(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       IP_BUF ipb;
+
+       ipb.code = VI_UNDO;
+       (void)vi_send(vi_ofd, NULL, &ipb);
+}
+
+#if defined(__STDC__)
+static void    ma_cut( Widget w,
+                       XtPointer call_data,
+                       XtPointer client_data
+                       )
+#else
+static void            ma_cut( w, call_data, client_data )
+       Widget          w;
+       XtPointer       call_data;
+       XtPointer       client_data;
+#endif
+{
+    /* future */
+    send_beep( w );
+}
+
+
+#if defined(__STDC__)
+static void    ma_copy(        Widget w,
+                               XtPointer call_data,
+                               XtPointer client_data
+                               )
+#else
+static void            ma_copy( w, call_data, client_data )
+       Widget          w;
+       XtPointer       call_data;
+       XtPointer       client_data;
+#endif
+{
+    /* future */
+    send_beep( w );
+}
+
+
+#if defined(__STDC__)
+static void    ma_paste(       Widget w,
+                               XtPointer call_data,
+                               XtPointer client_data
+                               )
+#else
+static void            ma_paste( w, call_data, client_data )
+       Widget          w;
+       XtPointer       call_data;
+       XtPointer       client_data;
+#endif
+{
+    /* future */
+    send_beep( w );
+}
+
+static void
+ma_find(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       __vi_show_search_dialog( main_widget, "Find" );
+}
+
+static void
+ma_find_next(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       __vi_search( w );
+}
+
+static void
+ma_tags(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       __vi_show_tags_dialog( main_widget, "Tag Stack" );
+}
+
+static void
+ma_tagpop(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       __vi_send_command_string( "\024" );
+}
+
+static void
+ma_tagtop(Widget w, XtPointer call_data, XtPointer client_data)
+{
+       __vi_send_command_string( ":tagtop" );
+}
+
+#if defined(__STDC__)
+static void    ma_preferences( Widget w,
+                               XtPointer call_data,
+                               XtPointer client_data
+                               )
+#else
+static void            ma_preferences( w, call_data, client_data )
+       Widget          w;
+       XtPointer       call_data;
+       XtPointer       client_data;
+#endif
+{
+       __vi_show_options_dialog( main_widget, "Preferences" );
+}
+
+\f
+/* Menu construction routines */
+
+typedef        struct {
+    String     title;
+    void       (*action)();
+    String     accel;          /* for Motif */
+    String     accel_text;     /* for the user */
+} pull_down;
+
+typedef        struct {
+    char       mnemonic;
+    String     title;
+    pull_down  *actions;
+} menu_bar;
+
+static pull_down       file_menu[] = {
+    { "Edit File...",          ma_edit_file,   "Alt<Key>e",    "Alt+E" },
+    { "",                      NULL,           NULL,   NULL    },
+    { "Split Window...",       ma_split,       NULL,   NULL    },
+    { "",                      NULL,           NULL,   NULL    },
+    { "Save ",                 ma_save,        "Alt<Key>s",    "Alt+S" },
+    { "Save As...",            ma_save_as,     "Shift Alt<Key>s",      "Shift+Alt+S"   },
+    { "",                      NULL,           NULL,   NULL    },
+    { "Write and Quit",                ma_wq,          "Shift Alt<Key>q",      "Shift+Alt+Q"   },
+    { "Quit",                  ma_quit,        "Alt<Key>q",    "Alt+Q" },
+    { NULL,                    NULL,           NULL,   NULL    },
+};
+
+static pull_down       edit_menu[] = {
+    { "Undo",                  ma_undo,        NULL,   NULL    },
+    { "",                      NULL,           NULL,   NULL    },
+    { "Cut",                   ma_cut,         "Alt<Key>x",    "Alt+X" },
+    { "Copy",                  ma_copy,        "Alt<Key>c",    "Alt+C" },
+    { "Paste",                 ma_paste,       "Alt<Key>v",    "Alt+V" },
+    { "",                      NULL,           NULL,   NULL    },
+    { "Find",                  ma_find,        "Alt<Key>f",    "Alt+F" },
+    { "Find Next",             ma_find_next,   "Alt<Key>g",    "Alt+G" },
+    { NULL,                    NULL,           NULL,   NULL    },
+};
+
+static pull_down       options_menu[] = {
+    { "Preferences",           ma_preferences, NULL,   NULL    },
+    { "Command Mode Maps",     NULL,           NULL,   NULL    },
+    { "Insert Mode Maps",      NULL,           NULL,   NULL    },
+    { NULL,                    NULL,           NULL,   NULL    },
+};
+
+static pull_down       tag_menu[] = {
+    { "Show Tag Stack",                ma_tags,        "Alt<Key>t",    "Alt+T" },
+    { "",                      NULL,           NULL,   NULL    },
+    { "Pop Tag",               ma_tagpop,      NULL,   NULL    },
+    { "Clear Stack",           ma_tagtop,      NULL,   NULL    },
+    { NULL,                    NULL,           NULL,   NULL    },
+};
+
+static pull_down       help_menu[] = {
+    { NULL,                    NULL,           NULL,   NULL    },
+};
+
+static menu_bar        main_menu[] = {
+    { 'F',     "File",         file_menu       },
+    { 'E',     "Edit",         edit_menu       },
+    { 'O',     "Options",      options_menu    },
+    { 'T',     "Tag",          tag_menu        },
+    { 'H',     "Help",         help_menu       },
+    { 0,       NULL,           NULL            },
+};
+
+
+#if defined(__STDC__)
+static void    add_entries( Widget parent, pull_down *actions )
+#else
+static void            add_entries( parent, actions )
+       Widget          parent;
+       pull_down       *actions;
+#endif
+{
+    Widget     w;
+    XmString   str;
+
+    for ( ; actions->title != NULL; actions++ ) {
+
+       /* a separator? */
+       if ( *actions->title != '\0' ) {
+           w = XmCreatePushButton( parent, actions->title, NULL, 0 );
+           if ( actions->action == NULL )
+               XtSetSensitive( w, False );
+           else
+               XtAddCallback(  w,
+                               XmNactivateCallback,
+                               (XtCallbackProc) actions->action,
+                               actions
+                               );
+           if ( actions->accel != NULL ) {
+               str = XmStringCreateSimple( actions->accel_text );
+               XtVaSetValues(  w,
+                               XmNaccelerator,         actions->accel,
+                               XmNacceleratorText,     str,
+                               0
+                               );
+               XmStringFree( str );
+           }
+       }
+       else {
+           w = XmCreateSeparator( parent, "separator", NULL, 0 );
+       }
+
+       XtManageChild( w );
+
+    }
+}
+
+/*
+ * vi_create_menubar --
+ *
+ * PUBLIC: Widget vi_create_menubar __P((Widget));
+ */
+Widget
+vi_create_menubar(Widget parent)
+{
+    Widget     menu, pull, button;
+    menu_bar   *ptr;
+
+    /* save this for creation of children */
+    main_widget = parent;
+
+    menu = XmCreateMenuBar( parent, "Menu", NULL, 0 );
+
+    for ( ptr=main_menu; ptr->title != NULL; ptr++ ) {
+
+       pull = XmCreatePulldownMenu( menu, "pull", NULL, 0 );
+       add_entries( pull, ptr->actions );
+       button = XmCreateCascadeButton( menu, ptr->title, NULL, 0 );
+       XtVaSetValues( button, XmNsubMenuId, pull, 0 );
+
+       if ( strcmp( ptr->title, "Help" ) == 0 )
+           XtVaSetValues( menu, XmNmenuHelpWidget, button, 0 );
+
+#if 0
+       /* These screw up accelerator processing.  Punt for now */
+       if ( ptr->mnemonic )
+           XtVaSetValues( button, XmNmnemonic, ptr->mnemonic, 0 );
+#endif
+
+       XtManageChild( button );
+    }
+
+    return menu;
+}
diff --git a/dist/nvi/motif_l/m_motif.h b/dist/nvi/motif_l/m_motif.h
new file mode 100644 (file)
index 0000000..d919552
--- /dev/null
@@ -0,0 +1,126 @@
+/*     $NetBSD: m_motif.h,v 1.1.1.2 2008/05/18 14:31:26 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     "Id: m_motif.h,v 8.11 1996/12/20 10:26:59 bostic Exp (Berkeley) Date: 1996/12/20 10:26:59";
+ */
+
+/*
+ * Color support
+ */
+#define        COLOR_INVALID   0xff    /* force color change */
+
+/*
+ * These are color indices.  When vi passes color info, we can do 2..0x3f
+ * in the 8 bits I've allocated.
+ */
+#define        COLOR_STANDARD  0x00    /* standard video */
+#define        COLOR_INVERSE   0x01    /* reverse video */
+
+/* These are flag bits, they override the above colors. */
+#define        COLOR_CARET     0x80    /* draw the caret */
+#define        COLOR_SELECT    0x40    /* draw the selection */
+
+#define        ToRowCol( scr, lin, r, c )      \
+           r = (lin) / scr->cols;      \
+           c = ((lin) - r * (scr->cols)) % scr->cols;
+#define        Linear( scr, y, x )     \
+           ( (y) * scr->cols + (x) )
+#define        CharAt( scr, y, x )     \
+           ( scr->characters + Linear( scr, y, x ) )
+#define        FlagAt( scr, y, x )     \
+           ( scr->flags + Linear( scr, y, x ) )
+
+#define        XPOS( scr, x )  \
+       scr->ch_width * (x)
+#define        YTOP( scr, y )  \
+       scr->ch_height * (y)
+#define        YPOS( scr, y )  \
+       YTOP( scr, ((y)+1) ) - scr->ch_descent
+
+#define        ROW( scr, y )   \
+       ( (y) / scr->ch_height )
+
+#define        COLUMN( scr, x )        \
+       ( (x) / scr->ch_width )
+
+/* Describes a single 'screen' implemented in X widgetry. */
+typedef        struct {
+    Widget     parent,         /* the pane */
+               area,           /* text goes here */
+               form,           /* holds text and scrollbar */
+               scroll;         /* not connected yet */
+    Region     clip;
+    int                color;
+    int                rows,
+               cols;
+    int                ch_width,
+               ch_height,
+               ch_descent;
+    int                curx, cury;
+    char       *characters;
+    char       *flags;
+    Boolean    init;
+} xvi_screen;
+
+/* Option type. */
+typedef enum {
+       optToggle,
+       optInteger,
+       optString,
+       optFile,
+       optTerminator
+} optKind;
+
+/* Option entry. */
+typedef struct {
+       optKind kind;                           /* Option type. */
+       String  name;                           /* Option name. */
+       void    *value;                         /* Current option value. */
+       u_int   flags;                          /* Associated flags. */
+} optData;
+
+/* Option page. */
+typedef        struct {
+       String  name;
+       String  description;
+       Widget  holder;
+       optData *toggles;
+       optData *ints;
+       optData *others;
+} optSheet;
+
+/* Utilities for converting X resources...
+ *
+ * __XutConvertResources( Widget, String root, XutResource *, int count )
+ *     The resource block is loaded with converted values
+ *     If the X resource does not exist, no change is made to the value
+ *     'root' should be the application name.
+ */
+typedef        enum {
+    XutRKinteger,
+    XutRKboolean,
+    XutRKpixel,
+    XutRKpixelBackup,  /* if XutRKpixel fails */
+    XutRKfont,
+    XutRKcursor
+} XutResourceKind;
+
+typedef struct {
+    String             name;
+    XutResourceKind    kind;
+    void               *value;
+} XutResource;
+
+/* Internal use: */
+extern GC         __vi_copy_gc;
+extern void     (*__vi_exitp) __P((void));
+extern xvi_screen *__vi_screen;
+
+#include "extern.h"
diff --git a/dist/nvi/motif_l/m_options.c b/dist/nvi/motif_l/m_options.c
new file mode 100644 (file)
index 0000000..7ab6845
--- /dev/null
@@ -0,0 +1,768 @@
+/*     $NetBSD: m_options.c,v 1.1.1.2 2008/05/18 14:31:27 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_options.c,v 8.22 2003/11/05 17:09:59 skimo Exp (Berkeley) Date: 2003/11/05 17:09:59";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/X.h>
+#include <X11/Intrinsic.h>
+#include <Xm/DialogS.h>
+#include <Xm/Form.h>
+#include <Xm/Frame.h>
+#include <Xm/LabelG.h>
+#include <Xm/PushBG.h>
+#include <Xm/TextF.h>
+#include <Xm/ToggleBG.h>
+#include <Xm/RowColumn.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+
+extern int vi_ofd;
+
+static void set_opt __P((Widget, XtPointer, XtPointer));
+
+\f
+/* constants */
+
+#if defined(SelfTest)
+
+/* in production, get these from the resource list */
+
+#define        toggleColumns   6
+
+#endif
+
+\f
+/*
+ * global data
+ */
+
+static Widget  preferences = NULL;
+
+static optData display[] = {
+       { optToggle,    "comment",      },
+       { optToggle,    "flash",        },
+       { optToggle,    "leftright",    },
+       { optToggle,    "list",         },
+       { optToggle,    "number",       },
+       { optToggle,    "octal",        },
+       { optToggle,    "ruler",        },
+       { optToggle,    "showmode",     },
+       { optToggle,    "slowopen",     },
+       { optToggle,    "verbose",      },
+       { optToggle,    "windowname",   },
+       { optTerminator,                },
+}, display_int[] = {
+       { optInteger,   "report",       },
+       { optInteger,   "scroll",       },
+       { optInteger,   "shiftwidth",   },
+       { optInteger,   "sidescroll",   },
+       { optInteger,   "tabstop",      },
+       { optInteger,   "window",       },
+       { optTerminator,                },
+}, display_str[] = {
+       { optString,    "noprint",      },
+       { optString,    "print",        },
+       { optTerminator,                },
+}, files[] = {
+       { optToggle,    "autowrite",    },
+       { optToggle,    "lock",         },
+       { optToggle,    "readonly",     },
+       { optToggle,    "writeany",     },
+       { optTerminator,                },
+}, files_str[] = {
+       { optString,    "backup",       },
+       { optString,    "path",         },
+       { optTerminator,                },
+}, general[] = {
+       { optToggle,    "exrc",         },
+       { optToggle,    "lisp",         },
+       { optToggle,    "modeline",     },
+       { optToggle,    "sourceany",    },
+       { optToggle,    "tildeop",      },
+       { optTerminator,                },
+}, general_int[] = {
+       { optInteger,   "taglength",    },
+       { optTerminator,                },
+}, general_str[] = {
+       { optString,    "cdpath",       },
+       { optString,    "directory",    },
+       { optString,    "msgcat",       },
+       { optString,    "recdir",       },
+       { optString,    "shell",        },
+       { optString,    "shellmeta",    },
+       { optString,    "tags",         },
+       { optTerminator,                },
+}, input[] = {
+       { optToggle,    "altwerase",    },
+       { optToggle,    "autoindent",   },
+       { optToggle,    "remap",        },
+       { optToggle,    "showmatch",    },
+       { optToggle,    "ttywerase",    },
+       { optTerminator,                },
+}, input_int[] = {
+       { optInteger,   "escapetime",   },
+       { optInteger,   "keytime",      },
+       { optInteger,   "matchtime",    },
+       { optInteger,   "timeout",      },
+       { optInteger,   "wraplen",      },
+       { optInteger,   "wrapmargin",   },
+       { optTerminator,                },
+}, input_str[] = {
+       { optString,    "cedit",        },
+       { optString,    "filec",        },
+       { optTerminator,                },
+}, search[] = {
+       { optToggle,    "extended",     },
+       { optToggle,    "iclower",      },
+       { optToggle,    "ignorecase",   },
+       { optToggle,    "magic",        },
+       { optToggle,    "searchincr",   },
+       { optToggle,    "wrapscan",     },
+       { optTerminator,                },
+}, search_str[] = {
+       { optString,    "paragraphs",   },
+       { optString,    "sections",     },
+       { optTerminator,                },
+};
+
+/* ********* NOTE ***********
+ * Sheet 0 will always be shown first.  It does not matter to the Xt code
+ * which sheet that is, so it ought to be the one users interact with most.
+ * Best guess is that's general editor options, but it might be Search/re.
+ * ********* NOTE ***********
+ */
+static optSheet sheets[] = {
+       {       "Display",
+               "These options control how text is displayed on the screen",
+               NULL,
+               display,
+               display_int,
+               display_str,
+       },
+       {       "Files",
+               "These options control how the editor handles files",
+               NULL,
+               files,
+               NULL,
+               files_str,
+       },
+       {       "Input",
+               "These options control text input behavior",
+               NULL,
+               input,
+               input_int,
+               input_str,
+       },
+       {       "Search/RE",
+       "These options control searching and Regular Expression behavior",
+               NULL,
+               search,
+               NULL,
+               search_str,
+       },
+       {       "Editor",
+               "These options control general editor configuration",
+               NULL,
+               general,
+               general_int,
+               general_str,
+       },
+};
+
+\f
+/* callbacks */
+
+#if defined(SelfTest)
+void __vi_cancel_cb()
+{
+    puts( "cancelled" );
+}
+#endif
+
+
+static void destroyed(void)
+{
+    int i;
+
+    puts( "destroyed" );
+
+    /* some window managers destroy us upon popdown */
+    for (i=0; i<XtNumber(sheets); i++) {
+       sheets[i].holder = NULL;
+    }
+    preferences = NULL;
+}
+
+
+static void    window_unmapped(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
+{
+    if ( ev->type == UnmapNotify ) {
+#if defined(SelfTest)
+       puts( "unmapped" );
+#endif
+       XtPopdown( XtParent( preferences ) );
+    }
+}
+
+/*
+ * __vi_editopt --
+ *     Set an edit option based on a core message.
+ *
+ * PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
+ */
+int
+__vi_editopt(IPVI *ipvi, const char *str1, u_int32_t len1, const char *str2, u_int32_t len2, u_int32_t val1)
+{
+       optData *opt;
+
+#undef NSEARCH
+#define        NSEARCH(list) {                                                 \
+       for (opt = list; opt->kind != optTerminator; ++opt)             \
+               if (!strcmp(opt->name, str1))                   \
+                       goto found;                                     \
+}
+
+       NSEARCH(display);
+       NSEARCH(display_int);
+       NSEARCH(display_str);
+       NSEARCH(files);
+       NSEARCH(files_str);
+       NSEARCH(general);
+       NSEARCH(general_int);
+       NSEARCH(general_str);
+       NSEARCH(input);
+       NSEARCH(input_int);
+       NSEARCH(input_str);
+       NSEARCH(search);
+       NSEARCH(search_str);
+
+       return (0);
+
+found: switch (opt->kind) {
+       case optToggle:
+               opt->value = (void *)val1;
+               break;
+       case optInteger:
+               if (opt->value != NULL)
+                       free(opt->value);
+               if ((opt->value = malloc(8)) != NULL)
+                       (void)snprintf(opt->value,
+                           8, "%lu", (u_long)val1);
+               break;
+       case optString:
+       case optFile:
+               if (opt->value != NULL)
+                       free(opt->value);
+               if ((opt->value = malloc(len2)) != NULL)
+                       memcpy(opt->value, str2, len2);
+               break;
+       case optTerminator:
+               abort();
+       }
+       return (0);
+}
+
+/*
+ * set_opt --
+ *     Send a set-edit-option message to core.
+ */
+static void
+set_opt(Widget w, XtPointer closure, XtPointer call_data)
+{
+       optData *opt;
+       Boolean set;
+       IP_BUF ipb;
+       String str;
+       extern IPVI ipvi_motif;
+
+       opt = closure;
+
+       ipb.code = VI_EDITOPT;
+       ipb.str1 = opt->name;
+       ipb.len1 = strlen(opt->name);
+
+       switch (opt->kind) {
+       case optToggle:
+               XtVaGetValues(w, XmNset, &set, 0);
+               ipb.val1 = set;
+               ipb.len2 = 0;
+
+               vi_wsend(&ipvi_motif, "ab1", &ipb);
+               if (ipb.val1) {
+                       opt->value = (void *)!set;
+                       /*
+                        * RAZ:
+                        * How do we turn off the button?  We don't want to
+                        * go recursive where we set it and it calls set_opt
+                        * to tell the core.  Is that possible?
+                        */
+                       XtVaSetValues(w, XmNset, &set, 0);
+                       break;
+               }
+
+               if (strcmp(opt->name, "ruler") == 0)
+                       if (set)
+                               __vi_show_text_ruler_dialog(
+                                   __vi_screen->area, "Ruler");
+                       else
+                               __vi_clear_text_ruler_dialog();
+               break;
+       case optInteger:
+               str = XmTextFieldGetString(w);
+               ipb.val1 = atoi(str);
+               ipb.len2 = 0;
+               vi_send(vi_ofd, "ab1", &ipb);
+               break;
+       case optFile:
+       case optString:
+               ipb.str2 = XmTextFieldGetString(w);
+               ipb.len2 = strlen(ipb.str2);
+               vi_send(vi_ofd, "ab1", &ipb);
+               break;
+       case optTerminator:
+               abort();
+       }
+}
+
+\f
+/* add toggles to the property sheet */
+
+#if defined(__STDC__)
+static void    add_toggle( Widget parent, optData *option )
+#else
+static void    add_toggle( parent, option )
+       Widget  parent;
+       optData *option;
+#endif
+{
+    Widget     w;
+
+    w = XtVaCreateManagedWidget( option->name,
+                                xmToggleButtonGadgetClass,
+                                parent,
+                                XmNset,        (Boolean) option->value,
+                                0
+                                );
+    XtAddCallback( w, XmNvalueChangedCallback, set_opt, option );
+}
+
+
+static Widget  create_toggles(Widget outer, optData *toggles)
+{
+    Widget     inner;
+    int                i;
+
+    inner = XtVaCreateWidget( "toggleOptions",
+                             xmRowColumnWidgetClass,
+                             outer,
+                             XmNpacking,               XmPACK_COLUMN,
+                             XmNnumColumns,            4,
+                             XmNtopAttachment,         XmATTACH_FORM,
+                             XmNrightAttachment,       XmATTACH_FORM,
+                             XmNleftAttachment,        XmATTACH_FORM,
+                             0
+                             );
+
+    /* first the booleans */
+    for (i=0; toggles[i].kind != optTerminator; i++) {
+       add_toggle( inner, &toggles[i] );
+    }
+    XtManageChild( inner );
+
+    return inner;
+}
+
+\f
+/* draw text fields and their labels */
+
+#if defined(__STDC__)
+static void    add_string_options( Widget parent,
+                                   optData *options
+                                   )
+#else
+static void    add_string_options( parent, options )
+       Widget  parent;
+       optData *options;
+#endif
+{
+    int                i;
+    Widget     f, w;
+
+    for ( i=0; options[i].kind != optTerminator; i++ ) {
+
+       f = XtVaCreateWidget( "form",
+                             xmFormWidgetClass,
+                             parent,
+                             0
+                             );
+
+       XtVaCreateManagedWidget( options[i].name,
+                                xmLabelGadgetClass,
+                                f,
+                                XmNtopAttachment,      XmATTACH_FORM,
+                                XmNbottomAttachment,   XmATTACH_FORM,
+                                XmNleftAttachment,     XmATTACH_FORM,
+                                XmNrightAttachment,    XmATTACH_POSITION,
+                                XmNrightPosition,      20,
+                                XmNalignment,          XmALIGNMENT_END,
+                                0
+                                );
+
+       w = XtVaCreateManagedWidget( "text",
+                                    xmTextFieldWidgetClass,
+                                    f,
+                                    XmNtopAttachment,          XmATTACH_FORM,
+                                    XmNbottomAttachment,       XmATTACH_FORM,
+                                    XmNrightAttachment,        XmATTACH_FORM,
+                                    XmNleftAttachment,         XmATTACH_POSITION,
+                                    XmNleftPosition,           20,
+                                    0
+                                    );
+
+       XmTextFieldSetString( w, (char *) options[i].value );
+       XtAddCallback( w, XmNactivateCallback, set_opt, &options[i] );
+       XtManageChild( f );
+    }
+}
+
+\f
+/* draw and display a single page of properties */
+
+#if defined(__STDC__)
+static Widget          create_sheet( Widget parent, optSheet *sheet )
+#else
+static Widget          create_sheet( parent, sheet )
+       Widget          parent;
+       optSheet        *sheet;
+#endif
+{
+    Widget     outer, inner, frame;
+    Dimension  height;
+    XmString   str;
+
+    outer = XtVaCreateWidget( sheet->name,
+                             xmFormWidgetClass,
+                             parent,
+                             XmNtopAttachment,         XmATTACH_FORM,
+                             XmNrightAttachment,       XmATTACH_FORM,
+                             XmNbottomAttachment,      XmATTACH_FORM,
+                             XmNleftAttachment,        XmATTACH_FORM,
+                             XmNshadowType,            XmSHADOW_ETCHED_IN,
+                             XmNshadowThickness,       2,
+                             XmNverticalSpacing,       4,
+                             XmNhorizontalSpacing,     4,
+                             0
+                             );
+
+    /* add descriptive text */
+    frame = XtVaCreateManagedWidget( "frame",
+                                   xmFrameWidgetClass,
+                                   outer,
+                                   XmNtopAttachment,           XmATTACH_FORM,
+                                   XmNrightAttachment,         XmATTACH_FORM,
+                                   XmNleftAttachment,          XmATTACH_FORM,
+                                   0
+                                   );
+    str = XmStringCreateLtoR( sheet->description, XmSTRING_DEFAULT_CHARSET );
+    XtVaCreateManagedWidget( "description",
+                            xmLabelGadgetClass,
+                            frame,
+                            XmNlabelString,            str,
+                            0
+                            );
+    XmStringFree( str );
+
+    /* Add the toggles. */
+    inner = create_toggles( outer, sheet->toggles );
+    XtVaSetValues( inner,
+                  XmNtopAttachment,    XmATTACH_WIDGET,
+                  XmNtopWidget,        frame,
+                  0
+                  );
+
+    /* the string options go here */
+    inner = XtVaCreateWidget( "otherOptions",
+                             xmRowColumnWidgetClass,
+                             outer,
+                             XmNpacking,               XmPACK_COLUMN,
+                             XmNtopAttachment,         XmATTACH_WIDGET,
+                             XmNtopWidget,             inner,
+                             XmNrightAttachment,       XmATTACH_FORM,
+                             XmNbottomAttachment,      XmATTACH_FORM,
+                             XmNleftAttachment,        XmATTACH_FORM,
+                             0
+                             );
+
+    /* Optionally, the ints. */
+    if ( sheet->ints != NULL )
+       add_string_options( inner, sheet->ints );
+
+     /* Optionally, the rest. */
+    if ( sheet->others != NULL )
+       add_string_options( inner, sheet->others );
+
+    XtManageChild( inner );
+
+    /* finally, force resize of the parent */
+    XtVaGetValues( outer, XmNheight, &height, 0 );
+    XtVaSetValues( parent, XmNheight, height, 0 );
+
+    return outer;
+}
+
+\f
+/* change preferences to another sheet */
+
+static void    change_sheet(Widget parent, int current)
+{
+    static int         current_sheet = -1;
+
+    /* create a new one? */
+    if ( sheets[current].holder == NULL )
+       sheets[current].holder = create_sheet( parent, &sheets[current] );
+
+    /* done with the old one? */
+    if ( current_sheet != -1 && sheets[current_sheet].holder != NULL )
+       XtUnmanageChild( sheets[current_sheet].holder );
+
+    current_sheet = current;
+    XtManageChild( sheets[current].holder );
+    XtManageChild( parent );
+}
+
+\f
+/* Draw and display a dialog the describes vi options */
+
+#if defined(__STDC__)
+static Widget  create_options_dialog( Widget parent, String title )
+#else
+static Widget  create_options_dialog( parent, title )
+       Widget  parent;
+       String  title;
+#endif
+{
+    Widget     box, form, inner;
+    int                i;
+    char       buffer[1024];
+
+    /* already built? */
+    if ( preferences != NULL ) return preferences;
+
+    box = XtVaCreatePopupShell( title,
+                               xmDialogShellWidgetClass,
+                               parent,
+                               XmNtitle,               title,
+                               XmNallowShellResize,    False,
+                               0
+                               );
+    XtAddCallback( box, XmNpopdownCallback, __vi_cancel_cb, 0 );
+    XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
+    XtAddEventHandler( box,
+                      SubstructureNotifyMask,
+                      False,
+                      window_unmapped,
+                      NULL
+                      );
+
+    form = XtVaCreateWidget( "options", 
+                            xmFormWidgetClass,
+                            box,
+                            0
+                            );
+
+    /* copy the pointers to the sheet names */
+    *buffer = '\0';
+    for (i=0; i<XtNumber(sheets); i++) {
+       strcat( buffer, "|" );
+       strcat( buffer, sheets[i].name );
+    }
+
+    inner = __vi_CreateTabbedFolder( "tabs",
+                                   form,
+                                   buffer,
+                                   XtNumber(sheets),
+                                   change_sheet
+                                   );
+
+    /* build the property sheets early */
+    for ( i=0; i<XtNumber(sheets); i++ )
+       change_sheet( inner, i );
+
+    /* manage all of the sheets right now */
+    for ( i=0; i<XtNumber(sheets); i++ )
+       XtManageChild( sheets[i].holder );
+    XtManageChild( form );
+
+    /* remove all but the first one */
+    for ( i=0; i<XtNumber(sheets); i++ )
+       XtUnmanageChild( sheets[i].holder );
+    change_sheet( inner, 0 );  /* show first sheet first */
+
+    /* keep this global, we might destroy it later */
+    preferences = form;
+
+    /* done */
+    return form;
+}
+
+
+\f
+/*
+ * module entry point
+ *
+ * __vi_show_options_dialog --
+ *
+ *
+ * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
+ */
+void
+__vi_show_options_dialog(Widget parent, String title)
+{
+    Widget     db = create_options_dialog( parent, title );
+#if defined(SelfTest)
+    Widget     shell = XtParent( db );
+#endif
+
+    XtManageChild( db );
+
+#if defined(SelfTest)
+    /* wait until it goes away */
+    XtPopup( shell, XtGrabNone );
+#else
+    /* wait until it goes away */
+    __vi_modal_dialog( db );
+#endif
+}
+
+
+\f
+/* module entry point
+ * Utilities for the search dialog
+ *
+ * __vi_toggle --
+ *     Returns the current value of a toggle.
+ *
+ * PUBLIC: int __vi_toggle __P((char *));
+ */
+int
+__vi_toggle(char *name)
+{
+       optData *opt;
+
+#undef NSEARCH
+#define        NSEARCH(list) {                                                 \
+       for (opt = list; opt->kind != optTerminator; ++opt)             \
+               if (!strcmp(opt->name, name))                           \
+                       return ((int)opt->value);                       \
+}
+       NSEARCH(display);
+       NSEARCH(files);
+       NSEARCH(general);
+       NSEARCH(input);
+       NSEARCH(search);
+
+       return (0);
+}
+
+/*
+ * __vi_create_search_toggles --
+ *     Creates the search toggles.  This is so the options and search widgets
+ *     share their appearance.
+ *
+ * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
+ */
+Widget
+__vi_create_search_toggles(Widget parent, optData *list)
+{
+       optData *opt;
+
+       /*
+        * Copy current options information into the search table.
+        *
+        * XXX
+        * This is an O(M*N) loop, but I don't think it matters.
+        */
+       for (opt = list; opt->kind != optTerminator; ++opt)
+               opt->value = (void *)__vi_toggle(opt->name);
+
+       return (create_toggles(parent, list));
+}
+
+\f
+#if defined(SelfTest)
+
+#if defined(__STDC__)
+static void show_options( Widget w, XtPointer data, XtPointer cbs )
+#else
+static void show_options( w, data, cbs )
+Widget w;
+XtPointer      data;
+XtPointer      cbs;
+#endif
+{
+    __vi_show_options_dialog( data, "Preferences" );
+}
+
+main( int argc, char *argv[] )
+{
+    XtAppContext       ctx;
+    Widget             top_level, rc, button;
+    extern             exit();
+
+    /* create a top-level shell for the window manager */
+    top_level = XtVaAppInitialize( &ctx,
+                                  argv[0],
+                                  NULL, 0,     /* options */
+                                  (ArgcType) &argc,
+                                  argv,        /* might get modified */
+                                  NULL,
+                                  NULL
+                                  );
+
+    rc = XtVaCreateManagedWidget( "rc",
+                                 xmRowColumnWidgetClass,
+                                 top_level,
+                                 0
+                                 );
+
+    button = XtVaCreateManagedWidget( "Pop up options dialog",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, show_options, rc );
+
+    button = XtVaCreateManagedWidget( "Quit",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, exit, 0 );
+
+    XtRealizeWidget(top_level);
+    XtAppMainLoop(ctx);
+}
+#endif
diff --git a/dist/nvi/motif_l/m_prompt.c b/dist/nvi/motif_l/m_prompt.c
new file mode 100644 (file)
index 0000000..ab05959
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $NetBSD: m_prompt.c,v 1.1.1.2 2008/05/18 14:31:27 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_prompt.c,v 8.8 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/X.h>
+#include <X11/Intrinsic.h>
+#include <Xm/MessageB.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+
+\f
+void   vi_fatal_message(Widget parent, String str)
+{
+    Widget     db = XmCreateErrorDialog( parent, "Fatal", NULL, 0 );
+    XmString   msg = XmStringCreateSimple( str );
+
+    XtVaSetValues( XtParent(db),
+                  XmNtitle,            "Fatal",
+                  0
+                  );
+    XtVaSetValues( db,
+                  XmNmessageString,    msg,
+                  0
+                  );
+    XtAddCallback( XtParent(db), XmNpopdownCallback, __vi_cancel_cb, 0 );
+
+    XtUnmanageChild( XmMessageBoxGetChild( db, XmDIALOG_CANCEL_BUTTON ) );
+    XtUnmanageChild( XmMessageBoxGetChild( db, XmDIALOG_HELP_BUTTON ) );
+
+    __vi_modal_dialog( db );
+
+    exit(0);
+}
+
+\f
+void   vi_info_message(Widget parent, String str)
+{
+    static     Widget  db = NULL;
+    XmString   msg = XmStringCreateSimple( str );
+
+    if ( db == NULL )
+       db = XmCreateInformationDialog( parent, "Information", NULL, 0 );
+
+    XtVaSetValues( XtParent(db),
+                  XmNtitle,            "Information",
+                  0
+                  );
+    XtVaSetValues( db,
+                  XmNmessageString,    msg,
+                  0
+                  );
+    XtAddCallback( XtParent(db), XmNpopdownCallback, __vi_cancel_cb, 0 );
+
+    XtUnmanageChild( XmMessageBoxGetChild( db, XmDIALOG_CANCEL_BUTTON ) );
+    XtUnmanageChild( XmMessageBoxGetChild( db, XmDIALOG_HELP_BUTTON ) );
+
+    __vi_modal_dialog( db );
+}
diff --git a/dist/nvi/motif_l/m_ruler.c b/dist/nvi/motif_l/m_ruler.c
new file mode 100644 (file)
index 0000000..5179d0c
--- /dev/null
@@ -0,0 +1,355 @@
+/*     $NetBSD: m_ruler.c,v 1.1.1.2 2008/05/18 14:31:28 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_ruler.c,v 8.6 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00";
+#endif /* not lint */
+
+/* This module implements a dialog for the text ruler
+ *
+ * Interface:
+ * void        __vi_show_text_ruler_dialog( Widget parent, String title )
+ *     Pops up a text ruler dialog.
+ *     We allow one per session.  It is not modal.
+ *
+ * void        __vi_clear_text_ruler_dialog( Widget parent, String title )
+ *     Pops down the text ruler dialog.
+ *
+ * void        __vi_set_text_ruler( int row, int col )
+ *     Changes the displayed position
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/X.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+#include <Xm/DrawingA.h>
+#include <Xm/RowColumn.h>
+#include <Xm/PushBG.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+#include "vi_mextern.h"
+
+\f
+/* globals */
+
+static Widget          db_ruler = NULL;
+
+static Boolean         active = False;
+
+static int             ruler_border = 5,
+                       ruler_asc;
+
+static GC              gc_ruler;
+
+static XFontStruct     *ruler_font;
+
+static char            text[256];
+
+#if ! defined(SelfTest)
+static  XutResource resource[] = {
+    {  "rulerFont",    XutRKfont,      &ruler_font     },
+    {  "rulerBorder",  XutRKinteger,   &ruler_border   },
+};
+#endif
+
+\f
+/* change the displayed position */
+
+static void
+set_ruler_text(int row, int col, int *h, int *w, int *asc)
+{
+    int                dir, des;
+    XCharStruct        over;
+
+    /* format the data */
+    sprintf( text, "%9.d,%-9.d", row+1, col+1 );
+
+    /* how big will it be? */
+    XTextExtents( ruler_font, text, strlen(text), &dir, asc, &des, &over );
+
+    /* how big a window will we need? */
+    *h = 2*ruler_border + over.ascent + over.descent;
+    *w = 2*ruler_border + over.width;
+}
+
+
+static void
+redraw_text(void)
+{
+    XClearArea( XtDisplay(db_ruler), XtWindow(db_ruler), 0, 0, 0, 0, False );
+    XDrawString( XtDisplay(db_ruler),
+                XtWindow(db_ruler),
+                gc_ruler,
+                ruler_border, ruler_border + ruler_asc,
+                text,
+                strlen(text)
+                );
+}
+
+
+/*
+ * PUBLIC: void __vi_set_text_ruler __P((int, int));
+ */
+void
+__vi_set_text_ruler(int row, int col)
+{
+    int h, w;
+
+    if ( ! active ) return;
+
+    set_ruler_text( row, col, &h, &w, &ruler_asc );
+
+    redraw_text();
+}
+
+\f
+/* callbacks */
+
+static void
+cancel_cb(void)
+{
+#if defined(SelfTest)
+    puts( "cancelled" );
+#endif
+    active = False;
+}
+
+
+static void destroyed(void)
+{
+#if defined(SelfTest)
+    puts( "destroyed" );
+#endif
+
+    /* some window managers destroy us upon popdown */
+    db_ruler = NULL;
+    active   = False;
+}
+
+
+\f
+/* Draw and display a dialog the describes nvi options */
+
+#if defined(__STDC__)
+static Widget  create_text_ruler_dialog( Widget parent, String title )
+#else
+static Widget  create_text_ruler_dialog( parent, title )
+       Widget  parent;
+       String  title;
+#endif
+{
+    Widget     box;
+    int                h, w, asc;
+    Pixel      fg, bg;
+
+    /* already built? */
+    if ( db_ruler != NULL ) return db_ruler;
+
+#if defined(SelfTest)
+    ruler_font = XLoadQueryFont( XtDisplay(parent), "9x15" );
+#else
+    /* check the resource database for interesting resources */
+    __XutConvertResources( parent,
+                        vi_progname,
+                        resource,
+                        XtNumber(resource)
+                        );
+#endif
+
+    gc_ruler = XCreateGC( XtDisplay(parent), XtWindow(parent), 0, NULL );
+    XSetFont( XtDisplay(parent), gc_ruler, ruler_font->fid );
+
+    box = XtVaCreatePopupShell( title,
+                               transientShellWidgetClass,
+                               parent,
+                               XmNallowShellResize,    False,
+                               0
+                               );
+    XtAddCallback( box, XmNpopdownCallback, cancel_cb, 0 );
+    XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
+
+    /* should be ok to use the font now */
+    active = True;
+
+    /* how big a window? */
+    set_ruler_text( 0, 0, &h, &w, &asc );
+
+    /* keep this global, we might destroy it later */
+    db_ruler = XtVaCreateManagedWidget( "Ruler", 
+                                       xmDrawingAreaWidgetClass,
+                                       box,
+                                       XmNheight,      h,
+                                       XmNwidth,       w,
+                                       0
+                                       );
+    /* this callback is for when the drawing area is exposed */
+    XtAddCallback( db_ruler,
+                  XmNexposeCallback,
+                  redraw_text,
+                  0
+                  );
+
+    /* what colors are selected for the drawing area? */
+    XtVaGetValues( db_ruler,
+                  XmNbackground,               &bg,
+                  XmNforeground,               &fg,
+                  0
+                  );
+    XSetForeground( XtDisplay(db_ruler), gc_ruler, fg );
+    XSetBackground( XtDisplay(db_ruler), gc_ruler, bg );
+
+    /* done */
+    return db_ruler;
+}
+
+
+\f
+/* module entry point
+ *     __vi_show_text_ruler_dialog( parent, title )
+ *     __vi_clear_text_ruler_dialog( parent, title )
+ */
+
+#if defined(__STDC__)
+void   __vi_show_text_ruler_dialog( Widget parent, String title )
+#else
+void   __vi_show_text_ruler_dialog( parent, title )
+Widget parent;
+String title;
+#endif
+{
+    Widget     db = create_text_ruler_dialog( parent, title ),
+               shell = XtParent(db);
+    Dimension  height, width;
+
+    /* this guy does not resize */
+    XtVaGetValues( db,
+                  XmNheight,   &height,
+                  XmNwidth,    &width,
+                  0
+                  );
+    XtVaSetValues( shell,
+                  XmNmaxWidth,         width,
+                  XmNminWidth,         width,
+                  XmNmaxHeight,        height,
+                  XmNminHeight,        height,
+                  0
+                  );
+
+    XtManageChild( db );
+
+    /* leave this guy up */
+    XtPopup( shell, XtGrabNone );
+
+    active = True;
+
+    /* ask vi core for the current r,c now */
+#if ! defined(SelfTest)
+    __vi_set_text_ruler( __vi_screen->cury, __vi_screen->curx );
+#else
+    __vi_set_text_ruler( rand(), rand() );
+#endif
+}
+
+
+#if defined(__STDC__)
+void   __vi_clear_text_ruler_dialog()
+#else
+void   __vi_clear_text_ruler_dialog(void)
+#endif
+{
+    if ( active )
+       XtPopdown( XtParent(db_ruler) );
+}
+
+\f
+#if defined(SelfTest)
+
+#if XtSpecificationRelease == 4
+#define        ArgcType        Cardinal *
+#else
+#define        ArgcType        int *
+#endif
+
+static void    change_pos( Widget w )
+{
+    __vi_set_text_ruler( rand(), rand() );
+}
+
+#if defined(__STDC__)
+static void show_text_ruler( Widget w, XtPointer data, XtPointer cbs )
+#else
+static void show_text_ruler( w, data, cbs )
+Widget w;
+XtPointer      data;
+XtPointer      cbs;
+#endif
+{
+    __vi_show_text_ruler_dialog( data, "Ruler" );
+}
+
+main( int argc, char *argv[] )
+{
+    XtAppContext       ctx;
+    Widget             top_level, rc, button;
+    extern             exit();
+
+    /* create a top-level shell for the window manager */
+    top_level = XtVaAppInitialize( &ctx,
+                                  argv[0],
+                                  NULL, 0,     /* options */
+                                  (ArgcType) &argc,
+                                  argv,        /* might get modified */
+                                  NULL,
+                                  NULL
+                                  );
+
+    rc = XtVaCreateManagedWidget( "rc",
+                                 xmRowColumnWidgetClass,
+                                 top_level,
+                                 0
+                                 );
+
+    button = XtVaCreateManagedWidget( "Pop up text ruler dialog",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, show_text_ruler, rc );
+
+    button = XtVaCreateManagedWidget( "Change Position",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, change_pos, rc );
+
+    button = XtVaCreateManagedWidget( "Quit",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, exit, 0 );
+
+    XtRealizeWidget(top_level);
+    XtAppMainLoop(ctx);
+}
+#endif
diff --git a/dist/nvi/motif_l/m_search.c b/dist/nvi/motif_l/m_search.c
new file mode 100644 (file)
index 0000000..fc5083d
--- /dev/null
@@ -0,0 +1,577 @@
+/*     $NetBSD: m_search.c,v 1.1.1.2 2008/05/18 14:31:28 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_search.c,v 8.14 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00";
+#endif /* not lint */
+
+#include <sys/queue.h>
+
+/* context */
+#include <X11/X.h>
+#include <X11/Intrinsic.h>
+#include <Xm/DialogS.h>
+#include <Xm/Form.h>
+#include <Xm/Label.h>
+#include <Xm/PushBG.h>
+#include <Xm/TextF.h>
+#include <Xm/ToggleB.h>
+#include <Xm/RowColumn.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+
+extern int vi_ofd;
+
+\f
+/* types */
+
+typedef struct sds {
+    struct sds *next;
+    Widget     shell;
+} save_dialog;
+
+static save_dialog     *dialogs = NULL;
+
+typedef struct {
+    String     name;
+    void       (*cb)();
+} ButtonData;
+
+\f
+/* globals and constants */
+
+static String  PatternWidget = "text";
+static String  pattern = NULL;
+
+static optData  search_toggles[] = {
+       { optToggle,    "extended",     NULL,   VI_SEARCH_EXT   },
+       { optToggle,    "iclower",      NULL,   VI_SEARCH_ICL   },
+       { optToggle,    "ignorecase",   NULL,   VI_SEARCH_IC    },
+       { optToggle,    "literal",      NULL,   VI_SEARCH_LIT   },
+       { optToggle,    "searchincr",   NULL,   VI_SEARCH_INCR  },
+       { optToggle,    "wrapscan",     NULL,   VI_SEARCH_WR    },
+       { optTerminator,                },
+};
+
+static void done_func __P((Widget));
+static void next_func __P((Widget));
+static void prev_func __P((Widget));
+static void search __P((Widget, int));
+
+static ButtonData button_data[] = {
+    { "Next",          next_func       },
+    { "Previous",      prev_func       },
+    { "Cancel",        done_func       }       /* always last */
+};
+
+\f
+/* Xt utilities */
+
+#if defined(__STDC__)
+static Widget  get_child_widget( Widget parent, String name )
+#else
+static Widget  get_child_widget( parent, name )
+       Widget  parent;
+       String  name;
+#endif
+{
+    char buffer[1024];
+
+    strcpy( buffer, "*" );
+    strcat( buffer, name );
+    return XtNameToWidget( parent, buffer );
+}
+
+\f
+/* sync the global state */
+
+#if defined(__STDC__)
+static void    get_state( Widget w )
+#else
+static void    get_state( w )
+       Widget  w;
+#endif
+{
+#if defined(SelfTest)
+    int                i;
+#endif
+    Widget     shell = w;
+
+    /* get all the data from the root of the widget tree */
+    while ( ! XtIsShell(shell) ) shell = XtParent(shell);
+
+#if defined(SelfTest)
+    /* which flags? */
+    for (i=0; i<XtNumber(toggle_data); i++) {
+       if (( w = get_child_widget( shell, toggle_data[i].name )) != NULL ) {
+           XtVaGetValues( w, XmNset, &toggle_data[i].value, 0 );
+       }
+    }
+#endif
+
+    /* what's the pattern? */
+    if (( w = get_child_widget( shell, PatternWidget )) != NULL ) {
+       if ( pattern != NULL ) XtFree( pattern );
+       pattern = XmTextFieldGetString( w );
+    }
+}
+
+\f
+/* Translate the user's actions into nvi commands */
+/*
+ * next_func --
+ *     Action for next button.
+ */
+static void
+next_func(Widget w)
+{
+       search(w, 0);
+}
+
+/*
+ * prev_func --
+ *     Action for previous button.
+ */
+static void
+prev_func(Widget w)
+{
+       search(w, VI_SEARCH_REV);
+}
+
+/*
+ * search --
+ *     Perform the search.
+ */
+static void
+search(Widget w, int flags)
+{
+       IP_BUF ipb;
+       optData *opt;
+       Widget shell;
+
+       shell = w;
+       while ( ! XtIsShell(shell) ) shell = XtParent(shell);
+
+       /* Get current data from the root of the widget tree?
+        * Do it if we are a child of a dialog shell (assume we
+        * are a 'Find' dialog).  Otherwise don't (we are the child
+        * of a menu and being invoked via accelerator)
+        */
+       if (XmIsDialogShell(shell))
+               get_state(w);
+
+       /* no pattern? probably, we haven't posted a search dialog yet.
+        * there ought to be a better thing to do here.
+        */
+       if ( pattern == NULL ) {
+           vi_info_message( w, "No previous string specified" );
+           return;
+       }
+
+       ipb.str1 = pattern;
+       ipb.len1 = strlen(pattern);
+
+       /* Initialize the search flags based on the buttons. */
+       ipb.val1 = flags;
+       for (opt = search_toggles; opt->kind != optTerminator; ++opt)
+               if (opt->value != NULL)
+                       ipb.val1 |= opt->flags;
+
+       ipb.code = VI_C_SEARCH;
+       vi_send(vi_ofd, "a1", &ipb);
+}
+
+#if defined(__STDC__)
+static void    done_func( Widget w )
+#else
+static void    done_func( w )
+       Widget  w;
+#endif
+{
+    save_dialog        *ptr;
+
+#if defined(SelfTest)
+    puts( XtName(w) );
+#endif
+
+    while ( ! XtIsShell(w) ) w = XtParent(w);
+    XtPopdown( w );
+
+    /* save it for later */
+    ptr                = (save_dialog *) malloc( sizeof(save_dialog) );
+    ptr->next  = dialogs;
+    ptr->shell = w;
+    dialogs    = ptr;
+}
+
+\f
+/* create a set of push buttons */
+
+#define        SpacingRatio    4       /* 3:1 button to spaces */
+
+#if defined(__STDC__)
+static Widget  create_push_buttons( Widget parent,
+                                    ButtonData *data,
+                                    int count
+                                   )
+#else
+static Widget  create_push_buttons( parent, data, count )
+    Widget     parent;
+    ButtonData *data;
+    int                count;
+#endif
+{
+    Widget     w, form;
+    int                pos = 1, base;
+
+    base = SpacingRatio*count + 1;
+    form = XtVaCreateManagedWidget( "buttons", 
+                                   xmFormWidgetClass,
+                                   parent,
+                                   XmNleftAttachment,  XmATTACH_FORM,
+                                   XmNrightAttachment, XmATTACH_FORM,
+                                   XmNfractionBase,    base,
+                                   XmNshadowType,      XmSHADOW_ETCHED_IN,
+                                   XmNshadowThickness, 2,
+                                   XmNverticalSpacing, 4,
+                                   0
+                                   );
+
+    while ( count-- > 0 ) {
+       w = XtVaCreateManagedWidget(data->name,
+                                   xmPushButtonGadgetClass,
+                                   form,
+                                   XmNtopAttachment,   XmATTACH_FORM,
+                                   XmNbottomAttachment,XmATTACH_FORM,
+                                   XmNleftAttachment,  XmATTACH_POSITION,
+                                   XmNleftPosition,    pos,
+                                   XmNshowAsDefault,   False,
+                                   XmNrightAttachment, XmATTACH_POSITION,
+                                   XmNrightPosition,   pos+SpacingRatio-1,
+                                   0
+                                   );
+       XtAddCallback( w, XmNactivateCallback, data->cb, 0 );
+       pos += SpacingRatio;
+       data++;
+    }
+
+    /* last button is 'cancel' */
+    XtVaSetValues( XtParent(form), XmNcancelButton, w, 0 );
+
+    return form;
+}
+
+\f
+/* create a set of check boxes */
+
+#if defined(SelfTest)
+
+#if defined(__STDC__)
+static Widget  create_check_boxes( Widget parent,
+                                   ToggleData *toggles,
+                                   int count
+                                   )
+#else
+static Widget  create_check_boxes( parent, toggles, count )
+       Widget  parent;
+       ToggleData *toggles;
+       int     count;
+#endif
+{
+    Widget     form;
+    int                pos = 1, base;
+
+    base = SpacingRatio*count +1;
+    form = XtVaCreateManagedWidget( "toggles", 
+                                   xmFormWidgetClass,
+                                   parent,
+                                   XmNleftAttachment,  XmATTACH_FORM,
+                                   XmNrightAttachment, XmATTACH_FORM,
+                                   XmNfractionBase,    base,
+                                   XmNverticalSpacing, 4,
+                                   0
+                                   );
+
+    while ( count-- > 0 ) {
+       XtVaCreateManagedWidget(toggles->name,
+                               xmToggleButtonWidgetClass,
+                               form,
+                               XmNtopAttachment,       XmATTACH_FORM,
+                               XmNbottomAttachment,    XmATTACH_FORM,
+                               XmNleftAttachment,      XmATTACH_POSITION,
+                               XmNleftPosition,        pos,
+                               XmNrightAttachment,     XmATTACH_POSITION,
+                               XmNrightPosition,       pos+SpacingRatio-1,
+                               0
+                               );
+       pos += SpacingRatio;
+       ++toggles;
+    }
+
+    return form;
+}
+
+#endif
+
+\f
+/* Routines to handle the text field widget */
+
+/* when the user hits 'CR' in a text widget, fire the default pushbutton */
+#if defined(__STDC__)
+static void    text_cr( Widget w, void *ptr, void *ptr2 )
+#else
+static void    text_cr( w, ptr, ptr2 )
+       Widget  w;
+       void    *ptr;
+       void    *ptr2;
+#endif
+{
+    next_func( w );
+}
+
+
+#ifdef notdef
+/*
+ * when the user hits any other character, if we are doing incremental
+ * search, send the updated string to nvi
+ *
+ * XXX
+ * I don't currently see any way to make this work -- incremental search
+ * is going to be really nasty.  What makes it worse is that the dialog
+ * box almost certainly obscured a chunk of the text file, so there's no
+ * way to use it even if it works.  
+ */
+#if defined(__STDC__)
+static void    value_changed( Widget w, void *ptr, void *ptr2 )
+#else
+static void    value_changed( w, ptr, ptr2 )
+       Widget  w;
+       void    *ptr;
+       void    *ptr2;
+#endif
+{
+    /* get all the data from the root of the widget tree */
+    get_state( w );
+
+    /* send it along? */
+#if defined(SelfTest)
+    if ( incremental_search ) send_command( w );
+#else
+    if ( __vi_incremental_search() ) send_command( w );
+#endif
+}
+#endif /* notdef */
+
+\f
+/* Draw and display a dialog the describes nvi search capability */
+
+#if defined(__STDC__)
+static Widget  create_search_dialog( Widget parent, String title )
+#else
+static Widget  create_search_dialog( parent, title )
+       Widget  parent;
+       String  title;
+#endif
+{
+    Widget     box, form, label, text, checks, buttons, form2;
+    save_dialog        *ptr;
+
+    /* use an existing one? */
+    if ( dialogs != NULL ) {
+       box = dialogs->shell;
+       ptr = dialogs->next;
+       free( dialogs );
+       dialogs = ptr;
+       return box;
+    }
+
+    box = XtVaCreatePopupShell( title,
+                               xmDialogShellWidgetClass,
+                               parent,
+                               XmNtitle,               title,
+                               XmNallowShellResize,    False,
+                               0
+                               );
+
+    form = XtVaCreateWidget( "form", 
+                               xmFormWidgetClass,
+                               box,
+                               XmNverticalSpacing,     4,
+                               XmNhorizontalSpacing,   4,
+                               0
+                               );
+
+    form2 = XtVaCreateManagedWidget( "form", 
+                               xmFormWidgetClass,
+                               form,
+                               XmNtopAttachment,       XmATTACH_FORM,
+                               XmNleftAttachment,      XmATTACH_FORM,
+                               XmNrightAttachment,     XmATTACH_FORM,
+                               0
+                               );
+
+    label = XtVaCreateManagedWidget( "Pattern:", 
+                                   xmLabelWidgetClass,
+                                   form2,
+                                   XmNtopAttachment,   XmATTACH_FORM,
+                                   XmNbottomAttachment,XmATTACH_FORM,
+                                   XmNleftAttachment,  XmATTACH_FORM,
+                                   0
+                                   );
+
+    text = XtVaCreateManagedWidget( PatternWidget, 
+                                   xmTextFieldWidgetClass,
+                                   form2,
+                                   XmNtopAttachment,   XmATTACH_FORM,
+                                   XmNbottomAttachment,XmATTACH_FORM,
+                                   XmNleftAttachment,  XmATTACH_WIDGET,
+                                   XmNleftWidget,      label,
+                                   XmNrightAttachment, XmATTACH_FORM,
+                                   0
+                                   );
+#ifdef notdef
+    XtAddCallback( text, XmNvalueChangedCallback, value_changed, 0 );
+#endif
+    XtAddCallback( text, XmNactivateCallback, text_cr, 0 );
+
+    buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
+    XtVaSetValues( buttons,
+                  XmNbottomAttachment, XmATTACH_FORM,
+                  0
+                  );
+
+#if defined(SelfTest)
+    checks = create_check_boxes( form, toggle_data, XtNumber(toggle_data) );
+#else
+    checks = (Widget) __vi_create_search_toggles( form, search_toggles );
+#endif
+    XtVaSetValues( checks,
+                  XmNtopAttachment,    XmATTACH_WIDGET,
+                  XmNtopWidget,        form2,
+                  XmNbottomAttachment, XmATTACH_WIDGET,
+                  XmNbottomWidget,     buttons,
+                  0
+                  );
+
+    XtManageChild( form );
+    return box;
+}
+
+\f
+/* Module interface to the outside world
+ *
+ *     xip_show_search_dialog( parent, title )
+ *     pops up a search dialog
+ *
+ *     xip_next_search()
+ *     simulates a 'next' assuming that a search has been done
+ */
+
+#if defined(__STDC__)
+void   __vi_show_search_dialog( Widget parent, String title )
+#else
+void   __vi_show_search_dialog( parent, data, cbs )
+Widget parent;
+String title;
+#endif
+{
+    Widget     db = create_search_dialog( parent, title );
+    Dimension  height;
+
+    /* we can handle getting taller and wider or narrower, but not shorter */
+    XtVaGetValues( db, XmNheight, &height, 0 );
+    XtVaSetValues( db, XmNmaxHeight, height, XmNminHeight, height, 0 );
+
+    /* post the dialog */
+    XtPopup( db, XtGrabNone );
+
+    /* request initial focus to the text widget */
+    XmProcessTraversal( get_child_widget( db, PatternWidget ),
+                       XmTRAVERSE_CURRENT
+                       );
+}
+
+
+/*
+ * __vi_search --
+ *
+ * PUBLIC: void __vi_search __P((Widget));
+ */
+void
+__vi_search(Widget w)
+{
+    next_func( w );
+}
+
+\f
+#if defined(SelfTest)
+
+#if defined(__STDC__)
+static void show_search( Widget w, XtPointer data, XtPointer cbs )
+#else
+static void show_search( w, data, cbs )
+Widget w;
+XtPointer      data;
+XtPointer      cbs;
+#endif
+{
+    __vi_show_search_dialog( data, "Search" );
+}
+
+main( int argc, char *argv[] )
+{
+    XtAppContext       ctx;
+    Widget             top_level, rc, button;
+    extern             exit();
+
+    /* create a top-level shell for the window manager */
+    top_level = XtVaAppInitialize( &ctx,
+                                  argv[0],
+                                  NULL, 0,     /* options */
+                                  (ArgcType) &argc,
+                                  argv,        /* might get modified */
+                                  NULL,
+                                  NULL
+                                  );
+
+    rc = XtVaCreateManagedWidget( "rc",
+                                 xmRowColumnWidgetClass,
+                                 top_level,
+                                 0
+                                 );
+
+    button = XtVaCreateManagedWidget( "Pop up search dialog",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, show_search, rc );
+
+    button = XtVaCreateManagedWidget( "Quit",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, exit, 0 );
+
+    XtRealizeWidget(top_level);
+    XtAppMainLoop(ctx);
+}
+#endif
diff --git a/dist/nvi/motif_l/m_tags.c b/dist/nvi/motif_l/m_tags.c
new file mode 100644 (file)
index 0000000..41442ae
--- /dev/null
@@ -0,0 +1,538 @@
+/*     $NetBSD: m_tags.c,v 1.1.1.2 2008/05/18 14:31:28 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_tags.c,v 8.9 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00";
+#endif /* not lint */
+
+/*
+ * This module implements a dialog for navigating the tag stack
+ *
+ * Interface:
+ * void        __vi_show_tags_dialog( Widget parent, String title )
+ *     Pops up a Tags dialog.  We allow one per session.  It is not modal.
+ *
+ * void __vi_push_tag( String text )
+ * void __vi_pop_tag()
+ * void __vi_clear_tag()
+ *     When core changes the tag stack we will change our representation
+ *     of it.  When this dialog appears, we need core to send a slew of
+ *     messages so we can display the current tag stack.
+ *
+ * void __vi_set_tag_text( String text )
+ *     the text field in the dialog is set to the string.  ideally,
+ *     this should be kept in sync with the word following the caret
+ *     in the current editor window
+ *
+ * To Do:
+ *     The push-buttons should activate and deactivate according to
+ *     the state of the tag stack and the text field.
+ *
+ *     Need to send VI commands rather than strings
+ *
+ *     Need IPO command to start/stop asking for the current tag stack
+ */
+
+\f
+/* context */
+#include <X11/X.h>
+#include <X11/Intrinsic.h>
+#include <Xm/DialogS.h>
+#include <Xm/Form.h>
+#include <Xm/LabelG.h>
+#include <Xm/TextF.h>
+#include <Xm/List.h>
+#include <Xm/RowColumn.h>
+#include <Xm/PushBG.h>
+
+#if ! defined(SelfTest)
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+#endif
+
+extern int vi_ofd;
+
+\f
+/* globals */
+
+static Widget  db_tabs = NULL,
+               db_text,
+               db_list;
+
+static Boolean active = False;
+
+typedef struct {
+    String     name;
+    Boolean    is_default;
+    void       (*cb)();
+} ButtonData;
+
+static void go_to_tag(Widget w);
+static void split_to_tag(Widget w);
+static void pop_tag(Widget w);
+
+static ButtonData button_data[] = {
+    { "Go To Tag",     True,   go_to_tag       },
+    { "Split To Tag",  False,  split_to_tag    },
+    { "Pop Tag",       False,  pop_tag         },
+};
+
+\f
+/* manage the tags stack list */
+
+void   __vi_pop_tag(void)
+{
+    if ( ! active ) return;
+
+    XmListDeletePos( db_list, 1 );
+}
+
+
+void   __vi_clear_tag(void)
+{
+    if ( ! active ) return;
+
+    XmListDeleteAllItems( db_list );
+}
+
+
+void   __vi_push_tag(String text)
+{
+    XmString   str;
+
+    if ( ! active ) return;
+
+    str = XmStringCreateSimple( text );
+    XmListAddItem( db_list, str, 1 );
+    XmStringFree( str );
+}
+
+\f
+/* create a set of push buttons */
+
+#define        SpacingRatio    4       /* 3:1 button to spaces */
+
+#if defined(__STDC__)
+static Widget  create_push_buttons( Widget parent,
+                                    ButtonData *data,
+                                    int count
+                                   )
+#else
+static Widget  create_push_buttons( parent, data, count )
+    Widget     parent;
+    ButtonData *data;
+    int                count;
+#endif
+{
+    Widget     w, form;
+    int                pos = 1, base;
+
+    base = SpacingRatio*count + 1;
+    form = XtVaCreateManagedWidget( "buttons", 
+                                   xmFormWidgetClass,
+                                   parent,
+                                   XmNleftAttachment,  XmATTACH_FORM,
+                                   XmNrightAttachment, XmATTACH_FORM,
+                                   XmNfractionBase,    base,
+                                   XmNshadowType,      XmSHADOW_ETCHED_IN,
+                                   XmNshadowThickness, 2,
+                                   XmNverticalSpacing, 4,
+                                   0
+                                   );
+
+    while ( count-- > 0 ) {
+       w = XtVaCreateManagedWidget(data->name,
+                                   xmPushButtonGadgetClass,
+                                   form,
+                                   XmNtopAttachment,   XmATTACH_FORM,
+                                   XmNbottomAttachment,XmATTACH_FORM,
+                                   XmNleftAttachment,  XmATTACH_POSITION,
+                                   XmNleftPosition,    pos,
+                                   XmNshowAsDefault,   data->is_default,
+                                   XmNdefaultButtonShadowThickness,    data->is_default,
+                                   XmNrightAttachment, XmATTACH_POSITION,
+                                   XmNrightPosition,   pos+SpacingRatio-1,
+                                   0
+                                   );
+       if ( data->is_default )
+           XtVaSetValues( form, XmNdefaultButton, w, 0 );
+       XtAddCallback( w, XmNactivateCallback, data->cb, 0 );
+       pos += SpacingRatio;
+       data++;
+    }
+
+    return form;
+}
+
+\f
+/* callbacks */
+
+static void
+cancel_cb(void)
+{
+#if defined(SelfTest)
+    puts( "cancelled" );
+#endif
+    active = False;
+}
+
+
+static void            set_text_field(Widget w, XtPointer ptr, XmListCallbackStruct *cbs)
+{
+    String str;
+
+    XmStringGetLtoR( cbs->item, XmSTRING_DEFAULT_CHARSET, &str );
+    XmTextFieldSetString( db_text, str );
+    XtFree( str );
+}
+
+
+void   __vi_set_tag_text(String text)
+{
+    if ( active ) XmTextFieldSetString( db_text, text );
+}
+
+
+static void destroyed(void)
+{
+#if defined(SelfTest)
+    puts( "destroyed" );
+#endif
+
+    /* some window managers destroy us upon popdown */
+    db_tabs = NULL;
+    active  = False;
+}
+
+
+#if defined(__STDC__)
+static void    pop_tag( Widget w )
+#else
+static void    pop_tag( w )
+       Widget  w;
+#endif
+{
+    static String buffer = ":tagpop";
+
+#if defined(SelfTest)
+    printf( "sending command <<%s>>\n", buffer );
+    __vi_pop_tag();
+#else
+    __vi_send_command_string( buffer );
+#endif
+}
+
+
+#if defined(__STDC__)
+static void    split_to_tag( Widget w )
+#else
+static void    split_to_tag( w )
+       Widget  w;
+#endif
+{
+    IP_BUF     ipb;
+    String     str;
+
+    str = XmTextFieldGetString( db_text );
+
+#if defined(SelfTest)
+    printf( "sending command <<:Tag %s>>\n", str );
+#else
+    /*
+     * XXX
+     * This is REALLY sleazy.  We pass the nul along with the
+     * string so that the core editor doesn't have to copy the
+     * string to get a nul termination.  This should be fixed
+     * as part of making the editor fully 8-bit clean.
+     */
+    ipb.code = VI_TAGSPLIT;
+    ipb.str1 = str;
+    ipb.len1 = strlen(str) + 1;
+    vi_send(vi_ofd, "a", &ipb);
+#endif
+
+    XtFree( str );
+}
+
+
+#if defined(__STDC__)
+static void    go_to_tag( Widget w )
+#else
+static void    go_to_tag( w )
+       Widget  w;
+#endif
+{
+    IP_BUF     ipb;
+    String     str;
+
+    str = XmTextFieldGetString( db_text );
+
+#if defined(SelfTest)
+    printf( "sending command <<:tag %s>>\n", str );
+#else
+    /*
+     * XXX
+     * This is REALLY sleazy.  We pass the nul along with the
+     * string so that the core editor doesn't have to copy the
+     * string to get a nul termination.  This should be fixed
+     * as part of making the editor fully 8-bit clean.
+     */
+    ipb.code = VI_TAGAS;
+    ipb.str1 = str;
+    ipb.len1 = strlen(str) + 1;
+    vi_send(vi_ofd, "a", &ipb);
+#endif
+
+    XtFree( str );
+}
+
+
+\f
+/* Draw and display a dialog the describes nvi options */
+
+#if defined(__STDC__)
+static Widget  create_tags_dialog( Widget parent, String title )
+#else
+static Widget  create_tags_dialog( parent, title )
+       Widget  parent;
+       String  title;
+#endif
+{
+    Widget     box, form, form2, form3, buttons;
+
+    /* already built? */
+    if ( db_tabs != NULL ) return db_tabs;
+
+    box = XtVaCreatePopupShell( title,
+                               xmDialogShellWidgetClass,
+                               parent,
+                               XmNtitle,               title,
+                               XmNallowShellResize,    False,
+                               0
+                               );
+    XtAddCallback( box, XmNpopdownCallback, cancel_cb, 0 );
+    XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
+
+    form = XtVaCreateWidget( "Tags", 
+                            xmFormWidgetClass,
+                            box,
+                            0
+                            );
+
+    buttons = create_push_buttons( form, button_data, XtNumber(button_data) );
+    XtVaSetValues( buttons,
+                  XmNbottomAttachment, XmATTACH_FORM,
+                  0
+                  );
+
+    form3 = XtVaCreateWidget( "form",
+                             xmFormWidgetClass,
+                             form,
+                             XmNleftAttachment,        XmATTACH_FORM,
+                             XmNrightAttachment,       XmATTACH_FORM,
+                             XmNbottomAttachment,      XmATTACH_WIDGET,
+                             XmNbottomWidget,          buttons,
+                             0
+                             );
+
+    form2 = XtVaCreateWidget( "form",
+                             xmFormWidgetClass,
+                             form,
+                             XmNtopAttachment,         XmATTACH_FORM,
+                             XmNleftAttachment,        XmATTACH_FORM,
+                             XmNrightAttachment,       XmATTACH_FORM,
+                             XmNbottomAttachment,      XmATTACH_WIDGET,
+                             XmNbottomWidget,          form3,
+                             0
+                             );
+
+    db_list = XtVaCreateManagedWidget( "list",
+                               xmListWidgetClass,
+                               form2,
+                               XmNtopAttachment,       XmATTACH_FORM,
+                               XmNleftAttachment,      XmATTACH_POSITION,
+                               XmNleftPosition,        20,
+                               XmNrightAttachment,     XmATTACH_FORM,
+                               XmNbottomAttachment,    XmATTACH_FORM,
+#if defined(SelfTest)
+                               XmNvisibleItemCount,    5,
+#endif
+                               XmNselectionPolicy,     XmSINGLE_SELECT,
+                               0
+                               );
+    XtAddCallback( db_list, XmNsingleSelectionCallback, set_text_field, 0 );
+    XtAddCallback( db_list, XmNdefaultActionCallback, go_to_tag, 0 );
+
+    XtVaCreateManagedWidget( "Tag Stack",
+                            xmLabelGadgetClass,
+                            form2,
+                            XmNtopAttachment,          XmATTACH_FORM,
+                            XmNbottomAttachment,       XmATTACH_FORM,
+                            XmNleftAttachment,         XmATTACH_FORM,
+                            XmNrightAttachment,        XmATTACH_POSITION,
+                            XmNrightPosition,          20,
+                            XmNalignment,              XmALIGNMENT_END,
+                            0
+                            );
+
+    XtVaCreateManagedWidget( "Tag",
+                            xmLabelGadgetClass,
+                            form3,
+                            XmNtopAttachment,          XmATTACH_FORM,
+                            XmNbottomAttachment,       XmATTACH_FORM,
+                            XmNleftAttachment,         XmATTACH_FORM,
+                            XmNrightAttachment,        XmATTACH_POSITION,
+                            XmNrightPosition,          20,
+                            XmNalignment,              XmALIGNMENT_END,
+                            0
+                            );
+
+    db_text = XtVaCreateManagedWidget( "text",
+                           xmTextFieldWidgetClass,
+                           form3,
+                           XmNtopAttachment,           XmATTACH_FORM,
+                           XmNbottomAttachment,        XmATTACH_FORM,
+                           XmNrightAttachment,         XmATTACH_FORM,
+                           XmNleftAttachment,          XmATTACH_POSITION,
+                           XmNleftPosition,            20,
+                           0
+                           );
+    XtAddCallback( db_text, XmNactivateCallback, go_to_tag, 0 );
+
+    /* keep this global, we might destroy it later */
+    db_tabs = form;
+
+    /* done */
+    XtManageChild( form3 );
+    XtManageChild( form2 );
+    return form;
+}
+
+
+\f
+/* module entry point
+ *     __vi_show_tags_dialog( parent, title )
+ */
+
+#if defined(__STDC__)
+void   __vi_show_tags_dialog( Widget parent, String title )
+#else
+void   __vi_show_tags_dialog( parent, title )
+Widget parent;
+String title;
+#endif
+{
+    Widget     db = create_tags_dialog( parent, title ),
+               shell = XtParent(db);
+
+    XtManageChild( db );
+
+    /* get the current window's text */
+    __vi_set_tag_text( (String) __vi_get_word_at_caret( NULL ) );
+
+    /* TODO:  ask vi core for the current tag stack now */
+
+    /* leave this guy up (or just raise it) */
+    XtPopup( shell, XtGrabNone );
+    XMapRaised( XtDisplay( shell ), XtWindow( shell ) );
+
+    active = True;
+}
+
+
+\f
+#if defined(SelfTest)
+
+#if XtSpecificationRelease == 4
+#define        ArgcType        Cardinal *
+#else
+#define        ArgcType        int *
+#endif
+
+static void    add_a_tag( Widget w )
+{
+    static     String  tags[] = { "first", "second", "this is the third" };
+    static     int     i = 0;
+
+    __vi_push_tag( tags[i] );
+    i = (i+1) % XtNumber(tags);
+}
+
+#if defined(__STDC__)
+static void show_tags( Widget w, XtPointer data, XtPointer cbs )
+#else
+static void show_tags( w, data, cbs )
+Widget w;
+XtPointer      data;
+XtPointer      cbs;
+#endif
+{
+    __vi_show_tags_dialog( data, "Tags" );
+}
+
+main( int argc, char *argv[] )
+{
+    XtAppContext       ctx;
+    Widget             top_level, rc, button;
+    extern             exit();
+
+    /* create a top-level shell for the window manager */
+    top_level = XtVaAppInitialize( &ctx,
+                                  argv[0],
+                                  NULL, 0,     /* options */
+                                  (ArgcType) &argc,
+                                  argv,        /* might get modified */
+                                  NULL,
+                                  NULL
+                                  );
+
+    rc = XtVaCreateManagedWidget( "rc",
+                                 xmRowColumnWidgetClass,
+                                 top_level,
+                                 0
+                                 );
+
+    button = XtVaCreateManagedWidget( "Pop up tags dialog",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, show_tags, rc );
+
+    button = XtVaCreateManagedWidget( "Add a tag",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, add_a_tag, rc );
+
+    button = XtVaCreateManagedWidget( "Quit",
+                                     xmPushButtonGadgetClass,
+                                     rc,
+                                     0
+                                     );
+    XtAddCallback( button, XmNactivateCallback, exit, 0 );
+
+    XtRealizeWidget(top_level);
+    XtAppMainLoop(ctx);
+}
+#endif
diff --git a/dist/nvi/motif_l/m_util.c b/dist/nvi/motif_l/m_util.c
new file mode 100644 (file)
index 0000000..1dad783
--- /dev/null
@@ -0,0 +1,158 @@
+/*     $NetBSD: m_util.c,v 1.1.1.2 2008/05/18 14:31:29 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_util.c,v 8.12 2003/11/05 17:10:00 skimo Exp (Berkeley) Date: 2003/11/05 17:10:00";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xatom.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+
+\f
+/* Widget hierarchy routines
+ *
+ * void XutShowWidgetTree( FILE *fp, Widget root, int indent )
+ *     prints the widgets and sub-widgets beneath the named root widget
+ */
+#ifdef DEBUG
+#if defined(__STDC__)
+void   XutShowWidgetTree( FILE *fp, Widget root, int indent )
+#else
+void   XutShowWidgetTree( fp, root, indent )
+FILE   *fp;
+Widget root;
+int    indent;
+#endif
+{
+#if ! defined(DECWINDOWS)
+    WidgetList l, l2;
+    int                i, count = 0;
+
+    /* print where we are right now */
+    fprintf( fp,
+            "%*.*swidget => 0x%x name => \"%s\"\n\r",
+            indent,
+            indent,
+            "",
+            root,
+            XtName(root) );
+
+    /* get the correct widget values */
+    XtVaGetValues( root, XtNchildren, &l, 0 );
+    XtVaGetValues( root, XtNchildren, &l2, 0 );
+    XtVaGetValues( root, XtNnumChildren, &count, 0 );
+
+    /* print the sub-widgets */
+    for ( i=0; i<count; i++ ) {
+       XutShowWidgetTree( fp, l[i], indent+4 );
+    }
+
+    /* tidy up if this thing contained children */
+    if ( count > 0 ) {
+       /* we may or may not have to free the children */
+       if ( l != l2 ) {
+           XtFree( (char *) l );
+           XtFree( (char *) l2 );
+       }
+    }
+#endif
+}
+#endif
+
+\f
+/* Utilities for converting X resources...
+ *
+ * __XutConvertResources( Widget, String root, XutResource *, int count )
+ *     The resource block is loaded with converted values
+ *     If the X resource does not exist, no change is made to the value
+ *     'root' should be the application name.
+ *
+ * PUBLIC: void __XutConvertResources __P((Widget, String, XutResource *, int));
+ */
+void __XutConvertResources(Widget wid, String root, XutResource *resources, int count)
+{
+    int                i;
+    XrmValue   from, to;
+    String     kind;
+    Boolean    success = True;
+
+    /* for each resource */
+    for (i=0; i<count; i++) {
+
+       /* is there a value in the database? */
+       from.addr = XGetDefault( XtDisplay(wid), root, resources[i].name );
+       if ( from.addr == NULL || *from.addr == '\0' )
+           continue;
+
+       /* load common parameters */
+       from.size = strlen( from.addr );
+       to.addr   = resources[i].value;
+
+       /* load type-specific parameters */
+       switch ( resources[i].kind ) {
+           case XutRKinteger:
+               to.size = sizeof(int);
+               kind    = XtRInt;
+               break;
+
+           case XutRKboolean:
+               /* String to Boolean */
+               to.size = sizeof(Boolean);
+               kind    = XtRBoolean;
+               break;
+
+           case XutRKfont:
+               /* String to Font structure */
+               to.size = sizeof(XFontStruct *);
+               kind    = XtRFontStruct;
+               break;
+
+           case XutRKpixelBackup:
+               /* String to Pixel backup algorithm */
+               if ( success ) continue;
+               /* FALL through */
+
+           case XutRKpixel:
+               /* String to Pixel */
+               to.size = sizeof(Pixel);
+               kind    = XtRPixel;
+               break;
+
+           case XutRKcursor:
+               /* String to Cursor */
+               to.size = sizeof(int);
+               kind    = XtRCursor;
+               break;
+
+           default:
+               return;
+       }
+
+       /* call the converter */
+       success = XtConvertAndStore( wid, XtRString, &from, kind, &to );
+    }
+}
diff --git a/dist/nvi/motif_l/m_vi.c b/dist/nvi/motif_l/m_vi.c
new file mode 100644 (file)
index 0000000..e48ea2c
--- /dev/null
@@ -0,0 +1,1443 @@
+/*     $NetBSD: m_vi.c,v 1.2 2011/03/21 14:53:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: m_vi.c,v 8.41 2003/11/05 17:10:01 skimo Exp (Berkeley) Date: 2003/11/05 17:10:01";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/cursorfont.h>
+#include <Xm/PanedW.h>
+#include <Xm/DrawingA.h>
+#include <Xm/Form.h>
+#include <Xm/Frame.h>
+#include <Xm/ScrollBar.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#undef LOCK_SUCCESS
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "m_motif.h"
+#include "vi_mextern.h"
+#include "pathnames.h"
+
+extern int vi_ofd;
+
+static void    f_copy(String *buffer, int *len);
+static void    f_paste(int widget, int buffer, int length);
+static void    f_clear(Widget widget);
+
+\f
+/*
+ * Globals and costants
+ */
+
+#define        BufferSize      1024
+
+static XFontStruct     *font;
+static GC              gc;
+       GC              __vi_copy_gc;
+static XtAppContext    ctx;
+
+       xvi_screen      *__vi_screen = NULL;
+static Cursor          std_cursor;
+static Cursor          busy_cursor;
+static XtTranslations  area_trans;
+static int             multi_click_length;
+
+void (*__vi_exitp)();                          /* Exit function. */
+
+\f
+/* hack for drag scrolling...
+ * I'm not sure why, but the current protocol gets out of sync when
+ * a lot of drag messages get passed around.  Likely, we need to wait
+ * for core to finish repainting the screen before sending more drag
+ * messages.
+ * To that end, we set scroll_block when we receive input from the scrollbar,
+ * and we clear it when we process the IPO_REFRESH message from core.
+ * A specific SCROLL_COMPLETED message would be better, but this seems to work.
+ */
+
+static Boolean scroll_block = False;
+
+/*
+ * PUBLIC: void __vi_set_scroll_block __P((void));
+ */
+void
+__vi_set_scroll_block(void)
+{
+       scroll_block = True;
+}
+
+/*
+ * PUBLIC: void __vi_clear_scroll_block __P((void));
+ */
+void
+__vi_clear_scroll_block(void)
+{
+       scroll_block = False;
+}
+
+\f
+#if defined(__STDC__)
+static void    set_gc_colors( xvi_screen *this_screen, int val )
+#else
+static void    set_gc_colors( this_screen, val )
+xvi_screen     *this_screen;
+int            val;
+#endif
+{
+    static Pixel       fg, bg, hi, shade;
+    static int         prev = COLOR_INVALID;
+
+    /* no change? */
+    if ( prev == val ) return;
+
+    /* init? */
+    if ( gc == NULL ) {
+
+       /* what colors are selected for the drawing area? */
+       XtVaGetValues( this_screen->area,
+                      XtNbackground,           &bg,
+                      XtNforeground,           &fg,
+                      XmNhighlightColor,       &hi,
+                      XmNtopShadowColor,       &shade,
+                      0
+                      );
+
+       gc = XCreateGC( XtDisplay(this_screen->area),
+                       DefaultRootWindow(XtDisplay(this_screen->area)),
+                       0,
+                       0
+                       );
+
+       XSetFont( XtDisplay(this_screen->area), gc, font->fid );
+    }
+
+    /* special colors? */
+    if ( val & COLOR_CARET ) {
+       XSetForeground( XtDisplay(this_screen->area), gc, fg );
+       XSetBackground( XtDisplay(this_screen->area), gc, hi );
+    }
+    else if ( val & COLOR_SELECT ) {
+       XSetForeground( XtDisplay(this_screen->area), gc, fg );
+       XSetBackground( XtDisplay(this_screen->area), gc, shade );
+    }
+    else switch (val) {
+       case COLOR_STANDARD:
+           XSetForeground( XtDisplay(this_screen->area), gc, fg );
+           XSetBackground( XtDisplay(this_screen->area), gc, bg );
+           break;
+       case COLOR_INVERSE:
+           XSetForeground( XtDisplay(this_screen->area), gc, bg );
+           XSetBackground( XtDisplay(this_screen->area), gc, fg );
+           break;
+       default:        /* implement color map later */
+           break;
+    }
+}
+
+\f
+/*
+ * Memory utilities
+ */
+
+#ifdef REALLOC
+#undef REALLOC
+#endif
+
+#define REALLOC( ptr, size )   \
+       ((ptr == NULL) ? malloc(size) : realloc(ptr,size))
+
+\f
+/* X windows routines.
+ * We currently create a single, top-level shell.  In that is a
+ * single drawing area into which we will draw text.  This allows
+ * us to put multi-color (and font, but we'll never build that) text
+ * into the drawing area.  In the future, we'll add scrollbars to the
+ * drawing areas
+ */
+
+void   select_start();
+void   select_extend();
+void   select_paste();
+void   key_press();
+void   insert_string();
+void   beep __P((Widget w));
+void   find();
+void   command();
+
+static XtActionsRec    area_actions[] = {
+    { "select_start",  select_start    },
+    { "select_extend", select_extend   },
+    { "select_paste",  select_paste    },
+    { "key_press",     key_press       },
+    { "insert_string", insert_string   },
+    { "beep",          beep            },
+    { "find",          find            },
+    { "command",       command         },
+};
+
+char   areaTrans[] =
+    "<Btn1Down>:       select_start()          \n\
+     <Btn1Motion>:     select_extend()         \n\
+     <Btn2Down>:       select_paste()          \n\
+     <Btn3Down>:       select_extend()         \n\
+     <Btn3Motion>:     select_extend()         \n\
+     <Key>End:         command(VI_C_BOTTOM)    \n\
+     <Key>Escape:      command(EINSERT)        \n\
+     <Key>Find:                find()                  \n\
+     <Key>Home:                command(VI_C_TOP)       \n\
+     <Key>Next:                command(VI_C_PGDOWN)    \n\
+     <Key>Prior:       command(VI_C_PGUP)      \n\
+     <Key>osfBackSpace:        command(VI_C_LEFT)      \n\
+     <Key>osfBeginLine:        command(VI_C_BOL)       \n\
+     <Key>osfCopy:     beep()                  \n\
+     <Key>osfCut:      beep()                  \n\
+     <Key>osfDelete:   command(VI_C_DEL)       \n\
+     <Key>osfDown:     command(VI_C_DOWN)      \n\
+     <Key>osfEndLine:  command(VI_C_EOL)       \n\
+     <Key>osfInsert:   command(VI_C_INSERT)    \n\
+     <Key>osfLeft:     command(VI_C_LEFT)      \n\
+     <Key>osfPageDown: command(VI_C_PGDOWN)    \n\
+     <Key>osfPageUp:   command(VI_C_PGUP)      \n\
+     <Key>osfPaste:    insert_string(p)        \n\
+     <Key>osfRight:    command(VI_C_RIGHT)     \n\
+     <Key>osfUndo:     command(VI_UNDO)        \n\
+     <Key>osfUp:       command(VI_C_UP)        \n\
+     Ctrl<Key>C:       command(VI_INTERRUPT)   \n\
+     <Key>:            key_press()";
+
+
+static  XutResource resource[] = {
+    { "font",          XutRKfont,      &font           },
+    { "pointerShape",  XutRKcursor,    &std_cursor     },
+    { "busyShape",     XutRKcursor,    &busy_cursor    },
+};
+
+
+/*
+ * vi_input_func --
+ *     We've received input on the pipe from vi.
+ *
+ * PUBLIC: void vi_input_func __P((XtPointer, int *, XtInputId *));
+ */
+void
+vi_input_func(XtPointer client_data, int *source, XtInputId *id)
+{
+       /* Parse and dispatch on commands in the queue. */
+       (void)ipvi_motif->input(ipvi_motif, *source);
+
+#ifdef notdef
+       /* Check the pipe for unused events when not busy. */
+       XtAppAddWorkProc(ctx, process_pipe_input, NULL);
+#endif
+}
+
+
+\f
+/* Send the window size. */
+#if defined(__STDC__)
+static void    send_resize( xvi_screen *this_screen )
+#else
+static void    send_resize( this_screen )
+xvi_screen     *this_screen;
+#endif
+{
+    IP_BUF     ipb;
+
+    ipb.val1 = this_screen->rows;
+    ipb.val2 = this_screen->cols;
+    ipb.code = VI_RESIZE;
+
+#ifdef TRACE
+    vtrace("resize_func ( %d x %d )\n", this_screen->rows, this_screen->cols);
+#endif
+
+    /* send up the pipe */
+    vi_send(vi_ofd, "12", &ipb);
+}
+
+\f
+#if defined(__STDC__)
+static void    resize_backing_store( xvi_screen *this_screen )
+#else
+static void    resize_backing_store( this_screen )
+xvi_screen     *this_screen;
+#endif
+{
+    int        total_chars = this_screen->rows * this_screen->cols;
+
+    this_screen->characters    = REALLOC( this_screen->characters,
+                                          total_chars
+                                          );
+    memset( this_screen->characters, ' ', total_chars );
+
+    this_screen->flags         = REALLOC( this_screen->flags,
+                                          total_chars
+                                          );
+    memset( this_screen->flags, 0, total_chars );
+}
+
+
+\f
+/* X will call this when we are resized */
+#if defined(__STDC__)
+static void    resize_func( Widget wid,
+                            XtPointer client_data,
+                            XtPointer call_data
+                            )
+#else
+static void    resize_func( wid, client_data, call_data )
+Widget         wid;
+XtPointer      client_data;
+XtPointer      call_data;
+#endif
+{
+    xvi_screen                 *this_screen = (xvi_screen *) client_data;
+    Dimension                  height, width;
+
+    XtVaGetValues( wid, XmNheight, &height, XmNwidth, &width, 0 );
+
+    /* generate correct sizes when we have font metrics implemented */
+    this_screen->cols = width / this_screen->ch_width;
+    this_screen->rows = height / this_screen->ch_height;
+
+    resize_backing_store( this_screen );
+    send_resize( this_screen );
+}
+
+
+/*
+ * __vi_draw_text --
+ *     Draw from backing store.
+ *
+ * PUBLIC: void        __vi_draw_text __P((xvi_screen *, int, int, int));
+ */
+void
+__vi_draw_text(xvi_screen *this_screen, int row, int start_col, int len)
+{
+    int                col, color, xpos;
+    char       *start, *end;
+
+    start = CharAt( __vi_screen, row, start_col );
+    color = *FlagAt( __vi_screen, row, start_col );
+    xpos  = XPOS( __vi_screen, start_col );
+
+    /* one column at a time */
+    for ( col=start_col;
+         col<this_screen->cols && col<start_col+len;
+         col++ ) {
+
+       /* has the color changed? */
+       if ( *FlagAt( __vi_screen, row, col ) == color )
+           continue;
+
+       /* is there anything to write? */
+       end  = CharAt( __vi_screen, row, col );
+       if ( end == start )
+           continue;
+
+       /* yes. write in the previous color */
+       set_gc_colors( __vi_screen, color );
+
+       /* add to display */
+       XDrawImageString( XtDisplay(__vi_screen->area),
+                         XtWindow(__vi_screen->area),
+                         gc,
+                         xpos,
+                         YPOS( __vi_screen, row ),
+                         start,
+                         end - start
+                         );
+
+       /* this is the new context */
+       color = *FlagAt( __vi_screen, row, col );
+       xpos  = XPOS( __vi_screen, col );
+       start = end;
+    }
+
+    /* is there anything to write? */
+    end = CharAt( __vi_screen, row, col );
+    if ( end != start ) {
+       /* yes. write in the previous color */
+       set_gc_colors( __vi_screen, color );
+
+       /* add to display */
+       XDrawImageString( XtDisplay(__vi_screen->area),
+                         XtWindow(__vi_screen->area),
+                         gc,
+                         xpos,
+                         YPOS( __vi_screen, row ),
+                         start,
+                         end - start
+                         );
+    }
+}
+
+\f
+/* set clipping rectangles accordingly */
+#if defined(__STDC__)
+static void    add_to_clip( xvi_screen *cur_screen, int x, int y, int width, int height )
+#else
+static void    add_to_clip( cur_screen, x, y, width, height )
+       xvi_screen *cur_screen;
+       int     x;
+       int     y;
+       int     width;
+       int     height;
+#endif
+{
+    XRectangle rect;
+    rect.x     = x;
+    rect.y     = y;
+    rect.height        = height;
+    rect.width = width;
+    if ( cur_screen->clip == NULL )
+       cur_screen->clip = XCreateRegion();
+    XUnionRectWithRegion( &rect, cur_screen->clip, cur_screen->clip );
+}
+
+\f
+/*
+ * __vi_expose_func --
+ *     Redraw the window's contents.
+ *
+ * NOTE: When vi wants to force a redraw, we are called with NULL widget
+ *      and call_data.
+ *
+ * PUBLIC: void        __vi_expose_func __P((Widget, XtPointer, XtPointer));
+ */
+void
+__vi_expose_func(Widget wid, XtPointer client_data, XtPointer call_data)
+{
+    xvi_screen                 *this_screen;
+    XmDrawingAreaCallbackStruct        *cbs;
+    XExposeEvent               *xev;
+    XGraphicsExposeEvent       *gev;
+    int                                row;
+
+    /* convert pointers */
+    this_screen = (xvi_screen *) client_data;
+    cbs                = (XmDrawingAreaCallbackStruct *) call_data;
+
+    /* first exposure? tell vi we are ready... */
+    if ( this_screen->init == False ) {
+
+       /* what does the user want to see? */
+       __vi_set_cursor( __vi_screen, False );
+
+       /* vi wants a resize as the first event */
+       send_resize( __vi_screen );
+
+       /* fine for now.  we'll be back */
+       this_screen->init = True;
+       return;
+    }
+
+    if ( call_data == NULL ) {
+
+       /* vi core calls this when it wants a full refresh */
+#ifdef TRACE
+       vtrace("expose_func:  full refresh\n");
+#endif
+
+       XClearWindow( XtDisplay(this_screen->area),
+                     XtWindow(this_screen->area)
+                     );
+    }
+    else {
+       switch ( cbs->event->type ) {
+
+           case GraphicsExpose:
+               gev = (XGraphicsExposeEvent *) cbs->event;
+
+               /* set clipping rectangles accordingly */
+               add_to_clip( this_screen,
+                            gev->x, gev->y,
+                            gev->width, gev->height
+                            );
+
+               /* X calls here when XCopyArea exposes new bits */
+#ifdef TRACE
+               vtrace("expose_func (X):  (x=%d,y=%d,w=%d,h=%d), count=%d\n",
+                            gev->x, gev->y,
+                            gev->width, gev->height,
+                            gev->count);
+#endif
+
+               /* more coming?  do it then */
+               if ( gev->count > 0 ) return;
+
+               /* set clipping region */
+               XSetRegion( XtDisplay(wid), gc, this_screen->clip );
+               break;
+
+           case Expose:
+               xev = (XExposeEvent *) cbs->event;
+
+               /* set clipping rectangles accordingly */
+               add_to_clip( this_screen,
+                            xev->x, xev->y,
+                            xev->width, xev->height
+                            );
+
+               /* Motif calls here when DrawingArea is exposed */
+#ifdef TRACE
+               vtrace("expose_func (Motif): (x=%d,y=%d,w=%d,h=%d), count=%d\n",
+                            xev->x, xev->y,
+                            xev->width, xev->height,
+                            xev->count);
+#endif
+
+               /* more coming?  do it then */
+               if ( xev->count > 0 ) return;
+
+               /* set clipping region */
+               XSetRegion( XtDisplay(wid), gc, this_screen->clip );
+               break;
+
+           default:
+               /* don't care? */
+               return;
+       }
+    }
+
+    /* one row at a time */
+    for (row=0; row<this_screen->rows; row++) {
+
+       /* draw from the backing store */
+       __vi_draw_text( this_screen, row, 0, this_screen->cols );
+    }
+
+    /* clear clipping region */
+    XSetClipMask( XtDisplay(this_screen->area), gc, None );
+    if ( this_screen->clip != NULL ) {
+       XDestroyRegion( this_screen->clip );
+       this_screen->clip = NULL;
+    }
+
+}
+
+\f
+#if defined(__STDC__)
+static void    xexpose ( Widget w,
+                         XtPointer client_data,
+                         XEvent *ev,
+                         Boolean *cont
+                         )
+#else
+static void    xexpose ( w, client_data, ev, cont )
+Widget         w;
+XtPointer      client_data;
+XEvent         *ev;
+Boolean                *cont;
+#endif
+{
+    XmDrawingAreaCallbackStruct        cbs;
+
+    switch ( ev->type ) {
+       case GraphicsExpose:
+           cbs.event   = ev;
+           cbs.window  = XtWindow(w);
+           cbs.reason  = XmCR_EXPOSE;
+           __vi_expose_func( w, client_data, (XtPointer) &cbs );
+           *cont       = False;        /* we took care of it */
+           break;
+       default:
+           /* don't care */
+           break;
+    }
+}
+
+
+/* unimplemented keystroke or command */
+#if defined(__STDC__)
+static void    beep( Widget w )
+#else
+static void    beep( w )
+Widget w;
+#endif
+{
+    XBell(XtDisplay(w),0);
+}
+
+
+/* give me a search dialog */
+#if defined(__STDC__)
+static void    find( Widget w )
+#else
+static void    find( w )
+Widget w;
+#endif
+{
+    __vi_show_search_dialog( w, "Find" );
+}
+
+/*
+ * command --
+ *     Translate simple keyboard input into vi protocol commands.
+ */
+static void
+command(Widget widget, XKeyEvent *event, String *str, Cardinal *cardinal)
+{
+       static struct {
+               String  name;
+               int     code;
+               int     count;
+       } table[] = {
+               { "VI_C_BOL",           VI_C_BOL,       0 },
+               { "VI_C_BOTTOM",        VI_C_BOTTOM,    0 },
+               { "VI_C_DEL",           VI_C_DEL,       0 },
+               { "VI_C_DOWN",          VI_C_DOWN,      1 },
+               { "VI_C_EOL",           VI_C_EOL,       0 },
+               { "VI_C_INSERT",        VI_C_INSERT,    0 },
+               { "VI_C_LEFT",          VI_C_LEFT,      0 },
+               { "VI_C_PGDOWN",        VI_C_PGDOWN,    1 },
+               { "VI_C_PGUP",          VI_C_PGUP,      1 },
+               { "VI_C_RIGHT",         VI_C_RIGHT,     0 },
+               { "VI_C_TOP",           VI_C_TOP,       0 },
+               { "VI_C_UP",            VI_C_UP,        1 },
+               { "VI_INTERRUPT",       VI_INTERRUPT,   0 },
+       };
+       IP_BUF ipb;
+       int i;
+
+       /*
+        * XXX
+        * Do fast lookup based on character #6 -- sleazy, but I don't
+        * want to do 10 strcmp's per keystroke.
+        */
+       ipb.val1 = 1;
+       for (i = 0; i < XtNumber(table); i++)
+               if (table[i].name[6] == (*str)[6] &&
+                   strcmp(table[i].name, *str) == 0) {
+                       ipb.code = table[i].code;
+                       vi_send(vi_ofd, table[i].count ? "1" : NULL, &ipb);
+                       return;
+               }
+
+       /* oops. */
+       beep(widget);
+}
+
+/* mouse or keyboard input. */
+#if defined(__STDC__)
+static void    insert_string( Widget widget, 
+                              XKeyEvent *event, 
+                              String *str, 
+                              Cardinal *cardinal
+                              )
+#else
+static void    insert_string( widget, event, str, cardinal )
+Widget          widget; 
+XKeyEvent       *event; 
+String          *str;  
+Cardinal        *cardinal;
+#endif
+{
+    IP_BUF     ipb;
+
+    ipb.len1 = strlen( *str );
+    if ( ipb.len1 != 0 ) {
+       ipb.code = VI_STRING;
+       ipb.str1 = *str;
+       vi_send(vi_ofd, "a", &ipb);
+    }
+
+#ifdef TRACE
+    vtrace("insert_string {%.*s}\n", strlen( *str ), *str );
+#endif
+}
+
+
+/* mouse or keyboard input. */
+#if defined(__STDC__)
+static void    key_press( Widget widget, 
+                          XKeyEvent *event, 
+                          String str, 
+                          Cardinal *cardinal
+                          )
+#else
+static void    key_press( widget, event, str, cardinal )
+Widget          widget; 
+XKeyEvent       *event; 
+String          str;  
+Cardinal        *cardinal;
+#endif
+{
+    IP_BUF     ipb;
+    char       bp[BufferSize];
+
+    ipb.len1 = XLookupString( event, bp, BufferSize, NULL, NULL );
+    if ( ipb.len1 != 0 ) {
+       ipb.code = VI_STRING;
+       ipb.str1 = bp;
+#ifdef TRACE
+       vtrace("key_press {%.*s}\n", ipb.len1, bp );
+#endif
+       vi_send(vi_ofd, "a", &ipb);
+    }
+
+}
+
+
+#if defined(__STDC__)
+static void    scrollbar_moved( Widget widget,
+                                XtPointer ptr,
+                                XmScrollBarCallbackStruct *cbs
+                                )
+#else
+static void                            scrollbar_moved( widget, ptr, cbs )
+       Widget                          widget;
+       XtPointer                       ptr;
+       XmScrollBarCallbackStruct       *cbs;
+#endif
+{
+    /* Future:  Need to scroll the correct screen! */
+    xvi_screen *cur_screen = (xvi_screen *) ptr;
+    IP_BUF     ipb;
+
+    /* if we are still processing messages from core, skip this event
+     * (see comments near __vi_set_scroll_block())
+     */
+    if ( scroll_block ) {
+       return;
+    }
+    __vi_set_scroll_block();
+
+#ifdef TRACE
+    switch ( cbs->reason ) {
+       case XmCR_VALUE_CHANGED:
+           vtrace( "scrollbar VALUE_CHANGED %d\n", cbs->value );
+           break;
+       case XmCR_DRAG:
+           vtrace( "scrollbar DRAG %d\n", cbs->value );
+           break;
+       default:
+           vtrace( "scrollbar <default> %d\n", cbs->value );
+           break;
+    }
+    vtrace("scrollto {%d}\n", cbs->value );
+#endif
+
+    /* Send the new cursor position. */
+    ipb.code = VI_C_SETTOP;
+    ipb.val1 = cbs->value;
+    (void)vi_send(vi_ofd, "1", &ipb);
+}
+
+
+#if defined(__STDC__)
+static xvi_screen      *create_screen( Widget parent, int rows, int cols )
+#else
+static xvi_screen      *create_screen( parent, rows, cols )
+       Widget          parent;
+       int             rows, cols;
+#endif
+{
+    xvi_screen *new_screen = (xvi_screen *) calloc( 1, sizeof(xvi_screen) );
+    Widget     frame;
+
+    /* init... */
+    new_screen->color          = COLOR_STANDARD;
+    new_screen->parent         = parent;
+
+    /* figure out the sizes */
+    new_screen->rows           = rows;
+    new_screen->cols           = cols;
+    new_screen->ch_width       = font->max_bounds.width;
+    new_screen->ch_height      = font->descent + font->ascent;
+    new_screen->ch_descent     = font->descent;
+    new_screen->clip           = NULL;
+
+    /* allocate and init the backing stores */
+    resize_backing_store( new_screen );
+
+    /* set up a translation table for the X toolkit */
+    if ( area_trans == NULL ) 
+       area_trans = XtParseTranslationTable(areaTrans);
+
+    /* future, new screen gets inserted into the parent sash
+     * immediately after the current screen.  Default Pane action is
+     * to add it to the end
+     */
+
+    /* use a form to hold the drawing area and the scrollbar */
+    new_screen->form = XtVaCreateManagedWidget( "form",
+           xmFormWidgetClass,
+           parent,
+           XmNpaneMinimum,             2*new_screen->ch_height,
+           XmNallowResize,             True,
+           NULL
+           );
+
+    /* create a scrollbar. */
+    new_screen->scroll = XtVaCreateManagedWidget( "scroll",
+           xmScrollBarWidgetClass,
+           new_screen->form,
+           XmNtopAttachment,           XmATTACH_FORM,
+           XmNbottomAttachment,        XmATTACH_FORM,
+           XmNrightAttachment,         XmATTACH_FORM,
+           XmNminimum,                 1,
+           XmNmaximum,                 2,
+           XmNsliderSize,              1,
+           NULL
+           );
+    XtAddCallback( new_screen->scroll,
+                  XmNvalueChangedCallback,
+                  scrollbar_moved,
+                  new_screen
+                  );
+    XtAddCallback( new_screen->scroll,
+                  XmNdragCallback,
+                  scrollbar_moved,
+                  new_screen
+                  );
+
+    /* create a frame because they look nice */
+    frame = XtVaCreateManagedWidget( "frame",
+           xmFrameWidgetClass,
+           new_screen->form,
+           XmNshadowType,              XmSHADOW_ETCHED_IN,
+           XmNtopAttachment,           XmATTACH_FORM,
+           XmNbottomAttachment,        XmATTACH_FORM,
+           XmNleftAttachment,          XmATTACH_FORM,
+           XmNrightAttachment,         XmATTACH_WIDGET,
+           XmNrightWidget,             new_screen->scroll,
+           NULL
+           );
+
+    /* create a drawing area into which we will put text */
+    new_screen->area = XtVaCreateManagedWidget( "screen",
+           xmDrawingAreaWidgetClass,
+           frame,
+           XmNheight,          new_screen->ch_height * new_screen->rows,
+           XmNwidth,           new_screen->ch_width * new_screen->cols,
+           XmNtranslations,    area_trans,
+           XmNuserData,        new_screen,
+           XmNnavigationType,  XmNONE,
+           XmNtraversalOn,     False,
+           NULL
+           );
+
+    /* this callback is for when the drawing area is resized */
+    XtAddCallback( new_screen->area,
+                  XmNresizeCallback,
+                  resize_func,
+                  new_screen
+                  );
+
+    /* this callback is for when the drawing area is exposed */
+    XtAddCallback( new_screen->area,
+                  XmNexposeCallback,
+                  __vi_expose_func,
+                  new_screen
+                  );
+
+    /* this callback is for when we expose obscured bits 
+     * (e.g. there is a window over part of our drawing area
+     */
+    XtAddEventHandler( new_screen->area,
+                      0,       /* no standard events */
+                      True,    /* we *WANT* GraphicsExpose */
+                      xexpose, /* what to do */
+                      new_screen
+                      );
+
+    return new_screen;
+}
+
+
+static xvi_screen      *split_screen(void)
+{
+    Cardinal   num;
+    WidgetList c;
+    int                rows = __vi_screen->rows / 2;
+    xvi_screen *new_screen;
+
+    /* Note that (global) cur_screen needs to be correctly set so that
+     * insert_here knows which screen to put the new one after
+     */
+    new_screen = create_screen( __vi_screen->parent,
+                               rows,
+                               __vi_screen->cols
+                               );
+
+    /* what are the screens? */
+    XtVaGetValues( __vi_screen->parent,
+                  XmNnumChildren,      &num,
+                  XmNchildren,         &c,
+                  NULL
+                  );
+
+    /* unmanage all children in preparation for resizing */
+    XtUnmanageChildren( c, num );
+
+    /* force resize of the affected screens */
+    XtVaSetValues( new_screen->form,
+                  XmNheight,   new_screen->ch_height * rows,
+                  NULL
+                  );
+    XtVaSetValues( __vi_screen->form,
+                  XmNheight,   __vi_screen->ch_height * rows,
+                  NULL
+                  );
+
+    /* re-manage */
+    XtManageChildren( c, num );
+
+    /* done */
+    return new_screen;
+}
+
+\f
+/* Tell me where to insert the next subpane */
+#if defined(__STDC__)
+static Cardinal        insert_here( Widget wid )
+#else
+static Cardinal        insert_here( wid )
+       Widget          wid;
+#endif
+{
+    Cardinal   i, num;
+    WidgetList c;
+
+    XtVaGetValues( XtParent(wid),
+                  XmNnumChildren,      &num,
+                  XmNchildren,         &c,
+                  NULL
+                  );
+
+    /* The  default  XmNinsertPosition  procedure  for  PanedWindow
+     * causes sashes to be inserted at the end of the list of children
+     * and causes non-sash widgets to be inserted after  other
+     * non-sash children but before any sashes.
+     */
+    if ( ! XmIsForm( wid ) )
+       return num;
+
+    /* We will put the widget after the one with the current screen */
+    for (i=0; i<num && XmIsForm(c[i]); i++) {
+       if ( __vi_screen == NULL || __vi_screen->form == c[i] )
+           return i+1; /* after the i-th */
+    }
+
+    /* could not find it?  this should never happen */
+    return num;
+}
+
+
+/*
+ * vi_create_editor --
+ *     Create the necessary widgetry.
+ *
+ * PUBLIC: Widget vi_create_editor __P((String, Widget, void (*)(void)));
+ */
+Widget
+vi_create_editor(String name, Widget parent, void (*exitp) (void))
+{
+    Widget     pane_w;
+    Display    *display = XtDisplay( parent );
+
+    __vi_exitp = exitp;
+
+    /* first time through? */
+    if ( ctx == NULL ) {
+
+       /* save this for later */
+       ctx = XtWidgetToApplicationContext( parent );
+
+       /* add our own special actions */
+       XtAppAddActions( ctx, area_actions, XtNumber(area_actions) );
+
+       /* how long is double-click? */
+       multi_click_length = XtGetMultiClickTime( display );
+
+       /* check the resource database for interesting resources */
+       __XutConvertResources( parent,
+                            vi_progname,
+                            resource,
+                            XtNumber(resource)
+                            );
+
+       /* we need a context for moving bits around in the windows */
+       __vi_copy_gc = XCreateGC( display,
+                                DefaultRootWindow(display),
+                                0,
+                                0
+                                );
+
+       /* routines for inter client communications conventions */
+       __vi_InitCopyPaste( f_copy, f_paste, f_clear, fprintf );
+    }
+
+    /* create the paned window */
+    pane_w = XtVaCreateManagedWidget( "pane",
+                                     xmPanedWindowWidgetClass,
+                                     parent,
+                                     XmNinsertPosition,        insert_here,
+                                     NULL
+                                     );
+
+    /* allocate our data structure.  in the future we will have several
+     * screens running around at the same time
+     */
+    __vi_screen = create_screen( pane_w, 24, 80 );
+
+    /* force creation of our color text context */
+    set_gc_colors( __vi_screen, COLOR_STANDARD );
+
+    /* done */
+    return pane_w;
+}
+
+\f
+/* These routines deal with the selection buffer */
+
+static int     selection_start, selection_end, selection_anchor;
+static enum    select_enum {
+           select_char, select_word, select_line
+       }       select_type = select_char;
+static int     last_click;
+
+static char    *clipboard = NULL;
+static int     clipboard_size = 0,
+               clipboard_length;
+
+
+#if defined(__STDC__)
+static void    copy_to_clipboard( xvi_screen *cur_screen )
+#else
+static void    copy_to_clipboard( cur_screen )
+xvi_screen     *cur_screen;
+#endif
+{
+    /* for now, copy from the backing store.  in the future,
+     * vi core will tell us exactly what the selection buffer contains
+     */
+    clipboard_length = 1 + selection_end - selection_start;
+
+    if ( clipboard == NULL )
+       clipboard = (char *) malloc( clipboard_length );
+    else if ( clipboard_size < clipboard_length )
+       clipboard = (char *) realloc( clipboard, clipboard_length );
+
+    memcpy( clipboard,
+           cur_screen->characters + selection_start,
+           clipboard_length
+           );
+}
+
+
+#if defined(__STDC__)
+static void    mark_selection( xvi_screen *cur_screen, int start, int end )
+#else
+static void    mark_selection( cur_screen, start, end )
+xvi_screen     *cur_screen;
+int            start;
+int            end;
+#endif
+{
+    int        row, col, i;
+
+    for ( i=start; i<=end; i++ ) {
+       if ( !( cur_screen->flags[i] & COLOR_SELECT ) ) {
+           cur_screen->flags[i] |= COLOR_SELECT;
+           ToRowCol( cur_screen, i, row, col );
+           __vi_draw_text( cur_screen, row, col, 1 );
+       }
+    }
+}
+
+
+#if defined(__STDC__)
+static void    erase_selection( xvi_screen *cur_screen, int start, int end )
+#else
+static void    erase_selection( cur_screen, start, end )
+xvi_screen     *cur_screen;
+int            start;
+int            end;
+#endif
+{
+    int        row, col, i;
+
+    for ( i=start; i<=end; i++ ) {
+       if ( cur_screen->flags[i] & COLOR_SELECT ) {
+           cur_screen->flags[i] &= ~COLOR_SELECT;
+           ToRowCol( cur_screen, i, row, col );
+           __vi_draw_text( cur_screen, row, col, 1 );
+       }
+    }
+}
+
+
+#if defined(__STDC__)
+static void    left_expand_selection( xvi_screen *cur_screen, int *start )
+#else
+static void    left_expand_selection( cur_screen, start )
+xvi_screen     *cur_screen;
+int            *start;
+#endif
+{
+    int row, col;
+
+    switch ( select_type ) {
+       case select_word:
+           if ( *start == 0 || isspace( (unsigned char)cur_screen->characters[*start] ) )
+               return;
+           for (;;) {
+               if ( isspace( (unsigned char)cur_screen->characters[*start-1] ) )
+                   return;
+               if ( --(*start) == 0 )
+                  return;
+           }
+       case select_line:
+           ToRowCol( cur_screen, *start, row, col );
+           col = 0;
+           *start = Linear( cur_screen, row, col );
+           break;
+    }
+}
+
+
+#if defined(__STDC__)
+static void    right_expand_selection( xvi_screen *cur_screen, int *end )
+#else
+static void    right_expand_selection( cur_screen, end )
+xvi_screen     *cur_screen;
+int            *end;
+#endif
+{
+    int row, col, last = cur_screen->cols * cur_screen->rows - 1;
+
+    switch ( select_type ) {
+       case select_word:
+           if ( *end == last || isspace( (unsigned char)cur_screen->characters[*end] ) )
+               return;
+           for (;;) {
+               if ( isspace( (unsigned char)cur_screen->characters[*end+1] ) )
+                   return;
+               if ( ++(*end) == last )
+                  return;
+           }
+       case select_line:
+           ToRowCol( cur_screen, *end, row, col );
+           col = cur_screen->cols -1;
+           *end = Linear( cur_screen, row, col );
+           break;
+    }
+}
+
+
+#if defined(__STDC__)
+static void    select_start( Widget widget, 
+                             XEvent *event,
+                             String str, 
+                             Cardinal *cardinal
+                             )
+#else
+static void    select_start( widget, event, str, cardinal )
+Widget         widget;   
+XEvent         *event;
+String         str; 
+Cardinal        *cardinal;
+#endif
+{
+    IP_BUF             ipb;
+    int                        xpos, ypos;
+    XPointerMovedEvent *ev = (XPointerMovedEvent *) event;
+    static int         last_click;
+
+    /*
+     * NOTE: when multiple panes are implemented, we need to find the correct
+     * screen.  For now, there is only one.
+     */
+    xpos = COLUMN( __vi_screen, ev->x );
+    ypos = ROW( __vi_screen, ev->y );
+
+    /* Remove the old one. */
+    erase_selection( __vi_screen, selection_start, selection_end );
+
+    /* Send the new cursor position. */
+    ipb.code = VI_MOUSE_MOVE;
+    ipb.val1 = ypos;
+    ipb.val2 = xpos;
+    (void)vi_send(vi_ofd, "12", &ipb);
+
+    /* click-click, and we go for words, lines, etc */
+    if ( ev->time - last_click < multi_click_length )
+       select_type = (enum select_enum) ((((int)select_type)+1)%3);
+    else
+       select_type = select_char;
+    last_click = ev->time;
+
+    /* put the selection here */
+    selection_anchor   = Linear( __vi_screen, ypos, xpos );
+    selection_start    = selection_anchor;
+    selection_end      = selection_anchor;
+
+    /* expand to include words, line, etc */
+    left_expand_selection( __vi_screen, &selection_start );
+    right_expand_selection( __vi_screen, &selection_end );
+
+    /* draw the new one */
+    mark_selection( __vi_screen, selection_start, selection_end );
+
+    /* and tell the window manager we own the selection */
+    if ( select_type != select_char ) {
+       __vi_AcquirePrimary( widget );
+       copy_to_clipboard( __vi_screen );
+    }
+}
+
+
+#if defined(__STDC__)
+static void    select_extend( Widget widget, 
+                              XEvent *event,
+                              String str, 
+                              Cardinal *cardinal
+                              )
+#else
+static void    select_extend( widget, event, str, cardinal )
+Widget         widget;   
+XEvent         *event;
+String         str; 
+Cardinal        *cardinal;
+#endif
+{
+    int                        xpos, ypos, pos;
+    XPointerMovedEvent *ev = (XPointerMovedEvent *) event;
+
+    /* NOTE:  when multiple panes are implemented, we need to find
+     * the correct screen.  For now, there is only one.
+     */
+    xpos = COLUMN( __vi_screen, ev->x );
+    ypos = ROW( __vi_screen, ev->y );
+
+    /* deal with words, lines, etc */
+    pos = Linear( __vi_screen, ypos, xpos );
+    if ( pos < selection_anchor )
+       left_expand_selection( __vi_screen, &pos );
+    else
+       right_expand_selection( __vi_screen, &pos );
+
+    /* extend from before the start? */
+    if ( pos < selection_start ) {
+       mark_selection( __vi_screen, pos, selection_start-1 );
+       selection_start = pos;
+    }
+
+    /* extend past the end? */
+    else if ( pos > selection_end ) {
+       mark_selection( __vi_screen, selection_end+1, pos );
+       selection_end = pos;
+    }
+
+    /* between the anchor and the start? */
+    else if ( pos < selection_anchor ) {
+       erase_selection( __vi_screen, selection_start, pos-1 );
+       selection_start = pos;
+    }
+
+    /* between the anchor and the end? */
+    else {
+       erase_selection( __vi_screen, pos+1, selection_end );
+       selection_end = pos;
+    }
+
+    /* and tell the window manager we own the selection */
+    __vi_AcquirePrimary( widget );
+    copy_to_clipboard( __vi_screen );
+}
+
+
+#if defined(__STDC__)
+static void    select_paste( Widget widget, 
+                             XEvent *event,
+                             String str, 
+                             Cardinal *cardinal
+                             )
+#else
+static void    select_paste( widget, event, str, cardinal )
+Widget         widget;   
+XEvent         *event;
+String         str; 
+Cardinal        *cardinal;
+#endif
+{
+    __vi_PasteFromClipboard( widget );
+}
+
+\f
+/* Interface to copy and paste
+ * (a) callbacks from the window manager
+ *     f_copy  -       it wants our buffer
+ *     f_paste -       it wants us to paste some text
+ *     f_clear -       we've lost the selection, clear it
+ */
+
+#if defined(__STDC__)
+static void    f_copy( String *buffer, int *len )
+#else
+static void    f_copy( buffer, len )
+       String  *buffer;
+       int     *len;
+#endif
+{
+#ifdef TRACE
+    vtrace("f_copy() called");
+#endif
+    *buffer    = clipboard;
+    *len       = clipboard_length;
+}
+
+
+
+static void    f_paste(int widget, int buffer, int length)
+{
+    /* NOTE:  when multiple panes are implemented, we need to find
+     * the correct screen.  For now, there is only one.
+     */
+#ifdef TRACE
+    vtrace("f_paste() called with '%*.*s'\n", length, length, buffer);
+#endif
+}
+
+
+#if defined(__STDC__)
+static void    f_clear( Widget widget )
+#else
+static void    f_clear( widget )
+Widget widget;
+#endif
+{
+    xvi_screen *cur_screen;
+
+#ifdef TRACE
+    vtrace("f_clear() called");
+#endif
+
+    XtVaGetValues( widget, XmNuserData, &cur_screen, 0 );
+
+    erase_selection( cur_screen, selection_start, selection_end );
+}
+
+\f
+/*
+ * These routines deal with the cursor.
+ *
+ * PUBLIC: void __vi_set_cursor __P((xvi_screen *, int));
+ */
+void
+__vi_set_cursor(xvi_screen *cur_screen, int is_busy)
+{
+    XDefineCursor( XtDisplay(cur_screen->area),
+                  XtWindow(cur_screen->area),
+                  (is_busy) ? busy_cursor : std_cursor
+                  );
+}
+
+
+\f
+/* hooks for the tags widget */
+
+static String  cur_word = NULL;
+
+/*
+ * PUBLIC: void __vi_set_word_at_caret __P((xvi_screen *));
+ */
+void
+__vi_set_word_at_caret(xvi_screen *this_screen)
+{
+    char       *start, *end, save;
+    int                newx, newy;
+
+    newx = this_screen->curx;
+    newy = this_screen->cury;
+
+    /* Note that this really ought to be done by core due to wrapping issues */
+    for ( end = start = CharAt( this_screen, newy, newx );
+         (isalnum( (unsigned char)*end ) || *end == '_') && (newx < this_screen->cols);
+         end++, newx++
+         );
+    save = *end;
+    *end = '\0';
+    if ( cur_word != NULL ) free( cur_word );
+    cur_word = strdup( start );
+    *end = save;
+
+    /* if the tag stack widget is active, set the text field there
+     * to agree with the current caret position.
+     */
+    __vi_set_tag_text( cur_word );
+}
+
+
+String __vi_get_word_at_caret(xvi_screen *this_screen)
+{
+    return (cur_word) ? cur_word : "";
+}
+
+\f
+/*
+ * These routines deal with the caret.
+ *
+ * PUBLIC: void draw_caret __P((xvi_screen *));
+ */
+static void
+draw_caret(xvi_screen *this_screen)
+{
+    /* draw the caret by drawing the text in highlight color */
+    *FlagAt( this_screen, this_screen->cury, this_screen->curx ) |= COLOR_CARET;
+    __vi_draw_text( this_screen, this_screen->cury, this_screen->curx, 1 );
+}
+
+/*
+ * PUBLIC: void __vi_erase_caret __P((xvi_screen *));
+ */
+void
+__vi_erase_caret(xvi_screen *this_screen)
+{
+    /* erase the caret by drawing the text in normal video */
+    *FlagAt( this_screen, this_screen->cury, this_screen->curx ) &= ~COLOR_CARET;
+    __vi_draw_text( this_screen, this_screen->cury, this_screen->curx, 1 );
+}
+
+/*
+ * PUBLIC: void        __vi_move_caret __P((xvi_screen *, int, int));
+ */
+void
+__vi_move_caret(xvi_screen *this_screen, int newy, int newx)
+{
+    /* remove the old caret */
+    __vi_erase_caret( this_screen );
+
+    /* caret is now here */
+    this_screen->curx = newx;
+    this_screen->cury = newy;
+    draw_caret( this_screen );
+}
diff --git a/dist/nvi/motif_l/vi_mextern.h b/dist/nvi/motif_l/vi_mextern.h
new file mode 100644 (file)
index 0000000..616f348
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: vi_mextern.h,v 1.1.1.2 2008/05/18 14:31:29 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Rob Zimmermann.  All rights reserved.
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     "Id: vi_mextern.h,v 8.6 2000/07/05 11:33:19 skimo Exp (Berkeley) Date: 2000/07/05 11:33:19";
+ */
+
+/*
+ * Globals, the list of names exposed to the outside world by the vi Motif
+ * widget library.
+ *
+ * Applications using the Motif vi widget code will have to initialize these
+ * or the library code will fail.
+ */
+extern char *vi_progname;                      /* Program name. */
+extern int   vi_ofd;                           /* Output file descriptor. */
+extern IPVIWIN *ipvi_motif;
+extern IPSIOPS ipsi_ops_motif;
+
+
+/*
+ * RAZ -- anyway we can get the library to do this setup?
+ */
+#if 0
+#ifdef __STDC__
+Widget vi_create_editor(String, Widget, void (*)(void));
+Widget vi_create_menubar(Widget);  
+void   vi_input_func(XtPointer, int *, XtInputId *);
+int    vi_run(int, char *[], int *, int *, pid_t *);
+int    vi_send(char *, IP_BUF *);
+int    vi_translate(char *, size_t *, IP_BUF *);
+#else
+Widget vi_create_editor();
+Widget vi_create_menubar();
+void   vi_input_func();
+void   vi_run();
+int    vi_send();
+int    vi_translate();
+#endif
+#endif
diff --git a/dist/nvi/motif_l/xtabbed.c b/dist/nvi/motif_l/xtabbed.c
new file mode 100644 (file)
index 0000000..1d27d59
--- /dev/null
@@ -0,0 +1,3157 @@
+/*     $NetBSD: xtabbed.c,v 1.1.1.2 2008/05/18 14:31:33 aymeric Exp $ */
+
+/* ***********************************************************************
+ * This module implements a motif tabbed window widget.
+ * The source is copied from the Free Widget Foundation
+ * This file is divided into thse parts
+ *     o - Conversion routines for the X resource manager
+ *     o - Routines for drawing rotated text
+ *     o - A motif widget for tabbed windows
+ *     o - A driver for the above in the flavor of the xt utilities module
+ * ***********************************************************************
+ */
+
+\f
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Xm/Xm.h>
+#include <Xm/Form.h>
+#include <Xm/RowColumn.h>
+#include <X11/StringDefs.h>
+#include <X11/IntrinsicP.h>
+#if defined(VMS_HOST)
+#include <DECW$INCLUDE/shape.h>
+#else
+#include <X11/extensions/shape.h>
+#endif
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <math.h>
+
+\f
+/* ***********************************************************************
+ * "rotated.h"
+ * ***********************************************************************
+ */
+
+/* ************************************************************************ */
+
+
+/* Header file for the `xvertext 5.0' routines.
+
+   Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma) */
+
+
+/* ************************************************************************ */
+
+#ifndef _XVERTEXT_INCLUDED_ 
+#define _XVERTEXT_INCLUDED_
+
+
+#define XV_VERSION      5.0
+#define XV_COPYRIGHT \
+      "xvertext routines Copyright (c) 1993 Alan Richardson"
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* text alignment */
+
+#define NONE             0
+#define TLEFT            1
+#define TCENTRE          2
+#define TRIGHT           3
+#define MLEFT            4
+#define MCENTRE          5
+#define MRIGHT           6
+#define BLEFT            7
+#define BCENTRE          8
+#define BRIGHT           9
+
+
+/* ---------------------------------------------------------------------- */
+
+/* this shoulf be C++ compliant, thanks to 
+     vlp@latina.inesc.pt (Vasco Lopes Paulo) */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+
+extern "C" {
+static float   XRotVersion(char*, int);
+static void    XRotSetMagnification(float);
+static void    XRotSetBoundingBoxPad(int);
+static int     XRotDrawString(Display*, XFontStruct*, float,
+                       Drawable, GC, int, int, char*);
+static int     XRotDrawImageString(Display*, XFontStruct*, float,
+                            Drawable, GC, int, int, char*);
+static int     XRotDrawAlignedString(Display*, XFontStruct*, float,
+                              Drawable, GC, int, int, char*, int);
+static int     XRotDrawAlignedImageString(Display*, XFontStruct*, float,
+                                   Drawable, GC, int, int, char*, int);
+static XPoint *XRotTextExtents(Display*, XFontStruct*, float,
+                       int, int, char*, int);
+}
+
+#else
+
+static float   XRotVersion(char *str, int n);
+static void    XRotSetMagnification(float m);
+static void    XRotSetBoundingBoxPad(int p);
+static int     XRotDrawString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str);
+static int     XRotDrawImageString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str);
+static int     XRotDrawAlignedString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align);
+static int     XRotDrawAlignedImageString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align);
+static XPoint *XRotTextExtents(Display *dpy, XFontStruct *font, float angle, int x, int y, char *text, int align);
+
+#endif /* __cplusplus */
+
+/* ---------------------------------------------------------------------- */
+
+
+#endif /* _XVERTEXT_INCLUDED_ */
+
+
+
+\f
+/* ***********************************************************************
+ * "strarray.h"
+ * ***********************************************************************
+ */
+
+#ifndef _strarray_h_
+#define _strarray_h_
+/*
+   StringArray
+   ===========
+   The type |StringArray| represents an array of |String|s, with the
+   proviso that by convention the last member of a |StringArray| is
+   always a |NULL| pointer. There is a converter that can construct a
+   |StringArray| from a single string.
+
+
+   cvtStringToStringArray
+   ======================
+   The converter from |String| to |StringArray| makes a copy of the
+   passed string and then replaces all occurences of the delimiter
+   with a nul byte. The |StringArray| is filled with pointers to the
+   parts of the string.
+
+   The delimiter character is the first character in the string.
+
+
+   newStringArray
+   ==============
+   The function |newStringArray| makes a copy of a |StringArray|. It
+   allocates new space for the array itself and for the strings that
+   it contains.
+
+
+   freeStringArray
+   ===============
+   |freeStringArray| deallocates the array and all strings it
+   contains. Note that this works for StringArrays produced with
+   |newStringArray|, but not for those created by
+   |cvtStringToStringArray|!
+
+*/
+
+
+typedef String * StringArray;
+
+static Boolean cvtStringToStringArray(
+#if NeedFunctionPrototypes
+    Display *display,
+    XrmValuePtr args,
+    Cardinal *num_args,
+    XrmValuePtr from,
+    XrmValuePtr to,
+    XtPointer *converter_data
+#endif
+);
+
+
+StringArray newStringArray(
+#if NeedFunctionPrototypes
+    StringArray a
+#endif
+);
+
+
+void freeStringArray(
+#if NeedFunctionPrototypes
+    StringArray a
+#endif
+);
+
+
+#endif /* _strarray_h_ */
+
+\f
+/* ***********************************************************************
+ * "XmTabs.h"
+ * ***********************************************************************
+ */
+
+/* Generated by wbuild from "XmTabs.w"
+** (generator version Revision: 8.5 of Date: 2001/06/25 15:19:28)
+*/
+#ifndef _XmTabs_H_
+#define _XmTabs_H_
+typedef enum {
+           XfwfUpTabs, XfwfDownTabs, XfwfLeftTabs, XfwfRightTabs,
+       } TabsOrientation;
+
+#ifndef XtNorientation
+#define XtNorientation "orientation"
+#endif
+#ifndef XtCOrientation
+#define XtCOrientation "Orientation"
+#endif
+#ifndef XtRTabsOrientation
+#define XtRTabsOrientation "TabsOrientation"
+#endif
+
+#ifndef XtNlefttabs
+#define XtNlefttabs "lefttabs"
+#endif
+#ifndef XtCLefttabs
+#define XtCLefttabs "Lefttabs"
+#endif
+#ifndef XtRInt
+#define XtRInt "Int"
+#endif
+
+#ifndef XtNrighttabs
+#define XtNrighttabs "righttabs"
+#endif
+#ifndef XtCRighttabs
+#define XtCRighttabs "Righttabs"
+#endif
+#ifndef XtRInt
+#define XtRInt "Int"
+#endif
+
+#ifndef XtNlabels
+#define XtNlabels "labels"
+#endif
+#ifndef XtCLabels
+#define XtCLabels "Labels"
+#endif
+#ifndef XtRStringArray
+#define XtRStringArray "StringArray"
+#endif
+
+#ifndef XtNtabWidthPercentage
+#define XtNtabWidthPercentage "tabWidthPercentage"
+#endif
+#ifndef XtCTabWidthPercentage
+#define XtCTabWidthPercentage "TabWidthPercentage"
+#endif
+#ifndef XtRInt
+#define XtRInt "Int"
+#endif
+
+#ifndef XtNcornerwidth
+#define XtNcornerwidth "cornerwidth"
+#endif
+#ifndef XtCCornerwidth
+#define XtCCornerwidth "Cornerwidth"
+#endif
+#ifndef XtRCardinal
+#define XtRCardinal "Cardinal"
+#endif
+
+#ifndef XtNcornerheight
+#define XtNcornerheight "cornerheight"
+#endif
+#ifndef XtCCornerheight
+#define XtCCornerheight "Cornerheight"
+#endif
+#ifndef XtRCardinal
+#define XtRCardinal "Cardinal"
+#endif
+
+#ifndef XtNtextmargin
+#define XtNtextmargin "textmargin"
+#endif
+#ifndef XtCTextmargin
+#define XtCTextmargin "Textmargin"
+#endif
+#ifndef XtRInt
+#define XtRInt "Int"
+#endif
+
+#ifndef XtNtabcolor
+#define XtNtabcolor "tabcolor"
+#endif
+#ifndef XtCTabcolor
+#define XtCTabcolor "Tabcolor"
+#endif
+#ifndef XtRPixel
+#define XtRPixel "Pixel"
+#endif
+
+#ifndef XtNfont
+#define XtNfont "font"
+#endif
+#ifndef XtCFont
+#define XtCFont "Font"
+#endif
+#ifndef XtRFontStruct
+#define XtRFontStruct "FontStruct"
+#endif
+
+#ifndef XtNactivateCallback
+#define XtNactivateCallback "activateCallback"
+#endif
+#ifndef XtCActivateCallback
+#define XtCActivateCallback "ActivateCallback"
+#endif
+#ifndef XtRCallback
+#define XtRCallback "Callback"
+#endif
+
+typedef struct _XmTabsClassRec *XmTabsWidgetClass;
+typedef struct _XmTabsRec *XmTabsWidget;
+#endif /*_XmTabs_H_*/
+
+\f
+/* ***********************************************************************
+ * "XmTabsP.h"
+ * ***********************************************************************
+ */
+
+/* Generated by wbuild from "XmTabs.w"
+** (generator version Revision: 8.5 of Date: 2001/06/25 15:19:28)
+*/
+#ifndef _XmTabsP_H_
+#define _XmTabsP_H_
+
+/* raz modified 22 Jul 96 for bluestone */
+#include <Xm/XmP.h>
+#if ! defined(MGR_ShadowThickness)
+#include <Xm/ManagerP.h>
+#endif
+
+typedef void (*border_highlight_Proc)(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+#define XtInherit_border_highlight ((border_highlight_Proc) _XtInherit)
+typedef void (*border_unhighlight_Proc)(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+#define XtInherit_border_unhighlight ((border_unhighlight_Proc) _XtInherit)
+typedef struct {
+/* Constraint resources */
+/* Private constraint variables */
+int dummy;
+} XmTabsConstraintPart;
+
+typedef struct _XmTabsConstraintRec {
+XmManagerConstraintPart xmManager;
+XmTabsConstraintPart xmTabs;
+} XmTabsConstraintRec;
+
+
+typedef struct {
+/* methods */
+border_highlight_Proc border_highlight;
+border_unhighlight_Proc border_unhighlight;
+/* class variables */
+} XmTabsClassPart;
+
+typedef struct _XmTabsClassRec {
+CoreClassPart core_class;
+CompositeClassPart composite_class;
+ConstraintClassPart constraint_class;
+XmManagerClassPart xmManager_class;
+XmTabsClassPart xmTabs_class;
+} XmTabsClassRec;
+
+typedef struct {
+/* resources */
+TabsOrientation  orientation;
+int  lefttabs;
+int  righttabs;
+StringArray  labels;
+int  tabWidthPercentage;
+Cardinal  cornerwidth;
+Cardinal  cornerheight;
+int  textmargin;
+Pixel  tabcolor;
+XFontStruct * font;
+XtCallbackList  activateCallback;
+/* private state */
+GC  textgc;
+GC  topgc;
+GC  bottomgc;
+GC  backgc;
+GC  fillgc;
+int * tabwidths;
+int * offsets;
+} XmTabsPart;
+
+typedef struct _XmTabsRec {
+CorePart core;
+CompositePart composite;
+ConstraintPart constraint;
+XmManagerPart xmManager;
+XmTabsPart xmTabs;
+} XmTabsRec;
+
+#endif /* _XmTabsP_H_ */
+
+\f
+/* ***********************************************************************
+ * A motif widget for tabbed windows
+ * ***********************************************************************
+ */
+
+static void activate(
+#if NeedFunctionPrototypes
+Widget,XEvent*,String*,Cardinal*
+#endif
+);
+
+static XtActionsRec actionsList[] = {
+{"activate", activate},
+};
+
+static char defaultTranslations[] = "\
+<Btn1Down>,<Btn1Up>: activate() \n\
+";
+static void _resolve_inheritance(
+#if NeedFunctionPrototypes
+WidgetClass
+#endif
+);
+static void class_initialize(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+static void initialize(
+#if NeedFunctionPrototypes
+Widget ,Widget,ArgList ,Cardinal *
+#endif
+);
+static Boolean  set_values(
+#if NeedFunctionPrototypes
+Widget ,Widget ,Widget,ArgList ,Cardinal *
+#endif
+);
+static void realize(
+#if NeedFunctionPrototypes
+Widget,XtValueMask *,XSetWindowAttributes *
+#endif
+);
+static void resize(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void expose(
+#if NeedFunctionPrototypes
+Widget,XEvent *,Region 
+#endif
+);
+static void border_highlight(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+static void border_unhighlight(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+static void destroy(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+#define min(a, b) ((a )<(b )?(a ):(b ))
+
+
+#define abs(x) ((x )<0 ?-(x ):(x ))
+
+
+static void compute_tabsizes(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void comp_hor_tab_shape(
+#if NeedFunctionPrototypes
+Widget,int ,XPoint  p[12],int *,int *,int *
+#endif
+);
+static void comp_ver_tab_shape(
+#if NeedFunctionPrototypes
+Widget,int ,XPoint  p[12],int *,int *,int *
+#endif
+);
+static void draw_border(
+#if NeedFunctionPrototypes
+Widget,XPoint  poly[12]
+#endif
+);
+static void draw_hor_tab(
+#if NeedFunctionPrototypes
+Widget,Region ,int 
+#endif
+);
+static void draw_ver_tab(
+#if NeedFunctionPrototypes
+Widget,Region ,int 
+#endif
+);
+static void create_topgc(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void create_bottomgc(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void create_textgc(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void create_fillgc(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void create_backgc(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+static void copy_bg(
+#if NeedFunctionPrototypes
+Widget,int ,XrmValue *
+#endif
+);
+static void set_shape(
+#if NeedFunctionPrototypes
+Widget
+#endif
+);
+#define done(type, value) do {\
+       if (to->addr != NULL) {\
+           if (to->size < sizeof(type)) {\
+               to->size = sizeof(type);\
+               return False;\
+           }\
+           *(type*)(to->addr) = (value);\
+        } else {\
+           static type static_val;\
+           static_val = (value);\
+           to->addr = (XtPointer)&static_val;\
+        }\
+        to->size = sizeof(type);\
+        return True;\
+    }while (0 )
+
+
+static Boolean  cvtStringToTabsOrientation(
+#if NeedFunctionPrototypes
+Display *,XrmValuePtr ,Cardinal *,XrmValuePtr ,XrmValuePtr ,XtPointer *
+#endif
+);
+static Boolean  cvtTabsOrientationToString(
+#if NeedFunctionPrototypes
+Display *,XrmValuePtr ,Cardinal *,XrmValuePtr ,XrmValuePtr ,XtPointer *
+#endif
+);
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void compute_tabsizes(Widget self)
+#else
+static void compute_tabsizes(self)Widget self;
+#endif
+{
+    int maxwd, basewidth, delta, i, n = ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs + 1;
+    int sum, len, h, length, breadth, shad = ((XmTabsWidget)self)->xmManager.shadow_thickness;
+
+    if (((XmTabsWidget)self)->xmTabs.offsets) XtFree((XtPointer) ((XmTabsWidget)self)->xmTabs.offsets);
+    if (((XmTabsWidget)self)->xmTabs.tabwidths) XtFree((XtPointer) ((XmTabsWidget)self)->xmTabs.tabwidths);
+    ((XmTabsWidget)self)->xmTabs.offsets = (XtPointer) XtMalloc(n * sizeof(*((XmTabsWidget)self)->xmTabs.offsets));
+    ((XmTabsWidget)self)->xmTabs.tabwidths = (XtPointer) XtMalloc(n * sizeof(*((XmTabsWidget)self)->xmTabs.tabwidths));
+
+    if (((XmTabsWidget)self)->xmTabs.orientation == XfwfUpTabs || ((XmTabsWidget)self)->xmTabs.orientation == XfwfDownTabs) {
+       length = ((XmTabsWidget)self)->core.width;
+       breadth = ((XmTabsWidget)self)->core.height;
+    } else {
+       length = ((XmTabsWidget)self)->core.height;
+       breadth = ((XmTabsWidget)self)->core.width;
+    }
+    if (((XmTabsWidget)self)->xmTabs.tabWidthPercentage != 0) {                /* Fixed width tabs */
+       basewidth = ((XmTabsWidget)self)->xmTabs.tabWidthPercentage * length/100;
+       if (n > 1) delta = (length - basewidth)/(((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs);
+       for (i = 0; i < n; i++) {
+           ((XmTabsWidget)self)->xmTabs.tabwidths[i] = basewidth;
+           ((XmTabsWidget)self)->xmTabs.offsets[i] = i * delta;
+       }
+    } else if (((XmTabsWidget)self)->xmTabs.labels == NULL) {          /* Empty tabs */
+       basewidth = length/n;
+       delta = (length - basewidth)/(((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs);
+       for (i = 0; i < n; i++) {
+           ((XmTabsWidget)self)->xmTabs.tabwidths[i] = basewidth;
+           ((XmTabsWidget)self)->xmTabs.offsets[i] = i * delta;
+       }
+    } else {                                   /* Variable width tabs */
+       sum = 0;
+       h = 2 * (((XmTabsWidget)self)->xmTabs.cornerwidth + shad + ((XmTabsWidget)self)->xmTabs.textmargin);
+       maxwd = length - n * (shad + ((XmTabsWidget)self)->xmTabs.textmargin);
+       for (i = 0; i < n; i++) {
+           len = strlen(((XmTabsWidget)self)->xmTabs.labels[i]);
+           ((XmTabsWidget)self)->xmTabs.tabwidths[i] = min(maxwd, XTextWidth(((XmTabsWidget)self)->xmTabs.font,((XmTabsWidget)self)->xmTabs.labels[i],len) + h);
+           sum += ((XmTabsWidget)self)->xmTabs.tabwidths[i];
+       }
+       ((XmTabsWidget)self)->xmTabs.offsets[0] = 0;
+       if (length >= sum)
+           delta = (length - sum)/(n - 1);     /* Between tabs */
+       else
+           delta = -((sum - length + n - 2)/(n - 1)); /* Round down! */
+       for (i = 1; i < n; i++)
+           ((XmTabsWidget)self)->xmTabs.offsets[i] = ((XmTabsWidget)self)->xmTabs.offsets[i-1] + ((XmTabsWidget)self)->xmTabs.tabwidths[i-1] + delta;
+    }
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void comp_hor_tab_shape(Widget self,int  i,XPoint  p[12],int * x0,int * x1,int * midy)
+#else
+static void comp_hor_tab_shape(self,i,p,x0,x1,midy)Widget self;int  i;XPoint  p[12];int * x0;int * x1;int * midy;
+#endif
+{
+    int shad = ((XmTabsWidget)self)->xmManager.shadow_thickness;
+    int k = min(((XmTabsWidget)self)->xmTabs.cornerheight, (((XmTabsWidget)self)->core.height - shad)/2);
+    /*
+     *                4 o-------------o 5
+     *                 /               \
+     *              3 o                 o 6
+     *                |                 |
+     *              2 o                 o 7
+     *             1 /                   \ 8
+     *   0 o--------o                     o--------o 9
+     *  11 o---------------------------------------o 10
+     *
+     *  11 o---------------------------------------o 10
+     *   0 o--------o                     o--------o 9
+     *             1 \                   / 8
+     *              2 o                 o 7
+     *                |                 |
+     *              3 o                 o 6
+     *                 \               /
+     *                4 o-------------o 5
+     */
+    p[0].x = 0;
+    p[1].x = ((XmTabsWidget)self)->xmTabs.offsets[i];
+    p[2].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[3].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[4].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + 2 * ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[5].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i] - 2 * ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[6].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i] - ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[7].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i] - ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[8].x = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i];
+    p[9].x = ((XmTabsWidget)self)->core.width;
+    p[10].x = ((XmTabsWidget)self)->core.width;
+    p[11].x = 0;
+
+    if (((XmTabsWidget)self)->xmTabs.orientation == XfwfUpTabs) {
+       p[0].y = ((XmTabsWidget)self)->core.height - shad;
+       p[1].y = ((XmTabsWidget)self)->core.height - shad;
+       p[2].y = ((XmTabsWidget)self)->core.height - shad - k;
+       p[3].y = k;
+       p[4].y = 0;
+       p[5].y = 0;
+       p[6].y = k;
+       p[7].y = ((XmTabsWidget)self)->core.height - shad - k;
+       p[8].y = ((XmTabsWidget)self)->core.height - shad;
+       p[9].y = ((XmTabsWidget)self)->core.height - shad;
+       p[10].y = ((XmTabsWidget)self)->core.height;
+       p[11].y = ((XmTabsWidget)self)->core.height;
+    } else {
+       p[0].y = shad;
+       p[1].y = shad;
+       p[2].y = shad + k;
+       p[3].y = ((XmTabsWidget)self)->core.height - k;
+       p[4].y = ((XmTabsWidget)self)->core.height;
+       p[5].y = ((XmTabsWidget)self)->core.height;
+       p[6].y = ((XmTabsWidget)self)->core.height - k;
+       p[7].y = shad + k;
+       p[8].y = shad;
+       p[9].y = shad;
+       p[10].y = 0;
+       p[11].y = 0;
+    }
+    *x0 = p[4].x;
+    *x1 = p[5].x;
+    *midy = (p[1].y + p[4].y)/2;
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void comp_ver_tab_shape(Widget self,int  i,XPoint  p[12],int * y0,int * y1,int * midx)
+#else
+static void comp_ver_tab_shape(self,i,p,y0,y1,midx)Widget self;int  i;XPoint  p[12];int * y0;int * y1;int * midx;
+#endif
+{
+    int shad = ((XmTabsWidget)self)->xmManager.shadow_thickness;
+    int k = min(((XmTabsWidget)self)->xmTabs.cornerheight, (((XmTabsWidget)self)->core.width - shad)/2);
+    /*
+     *       0 o_o 11  11 o_o 0
+     *         | |        | |
+     *       1 o |        | o 1
+     *     3 2/  |        |  \2 3
+     *     o-o   |        |   o-o
+     *    /      |        |      \
+     * 4 o       |        |       o 4
+     *   |       |        |       |
+     * 5 o       |        |       o 5
+     *    \      |        |      /
+     *     o-o   |        |   o-o
+     *     6 7\  |        |  /7 6  
+     *       8 o |        | o 8
+     *         | |        | |
+     *       9 o_o 10  10 o_o 9
+     */
+    if (((XmTabsWidget)self)->xmTabs.orientation == XfwfLeftTabs) {
+       p[0].x = ((XmTabsWidget)self)->core.width - shad;
+       p[1].x = ((XmTabsWidget)self)->core.width - shad;
+       p[2].x = ((XmTabsWidget)self)->core.width - shad - k;
+       p[3].x = k;
+       p[4].x = 0;
+       p[5].x = 0;
+       p[6].x = k;
+       p[7].x = ((XmTabsWidget)self)->core.width - shad - k;
+       p[8].x = ((XmTabsWidget)self)->core.width - shad;
+       p[9].x = ((XmTabsWidget)self)->core.width - shad;
+       p[10].x = ((XmTabsWidget)self)->core.width;
+       p[11].x = ((XmTabsWidget)self)->core.width;
+    } else {
+       p[0].x = shad;
+       p[1].x = shad;
+       p[2].x = shad + k;
+       p[3].x = ((XmTabsWidget)self)->core.width - k;
+       p[4].x = ((XmTabsWidget)self)->core.width;
+       p[5].x = ((XmTabsWidget)self)->core.width;
+       p[6].x = ((XmTabsWidget)self)->core.width - k;
+       p[7].x = shad + k;
+       p[8].x = shad;
+       p[9].x = shad;
+       p[10].x = 0;
+       p[11].x = 0;
+    }
+    p[0].y = 0;
+    p[1].y = ((XmTabsWidget)self)->xmTabs.offsets[i];
+    p[2].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[3].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[4].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + 2 * ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[5].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i] - 2 * ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[6].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i] - ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[7].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i] - ((XmTabsWidget)self)->xmTabs.cornerwidth;
+    p[8].y = ((XmTabsWidget)self)->xmTabs.offsets[i] + ((XmTabsWidget)self)->xmTabs.tabwidths[i];
+    p[9].y = ((XmTabsWidget)self)->core.height;
+    p[10].y = ((XmTabsWidget)self)->core.height;
+    p[11].y = 0;
+    *y0 = p[4].y;
+    *y1 = p[5].y;
+    *midx = (p[1].x + p[4].x)/2;
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void draw_border(Widget self,XPoint  poly[12])
+#else
+static void draw_border(self,poly)Widget self;XPoint  poly[12];
+#endif
+{
+    Display *dpy = XtDisplay(self);
+    Window win = XtWindow(self);
+
+    if (((XmTabsWidget)self)->xmTabs.orientation == XfwfUpTabs) {
+       XDrawLines(dpy, win, ((XmTabsWidget)self)->xmTabs.topgc, poly, 6, CoordModeOrigin);
+       XDrawLines(dpy, win, ((XmTabsWidget)self)->xmTabs.bottomgc, poly + 5, 4, CoordModeOrigin);
+       XDrawLines(dpy, win, ((XmTabsWidget)self)->xmTabs.topgc, poly + 8, 2, CoordModeOrigin);
+    } else {
+       XDrawLines(dpy, win, ((XmTabsWidget)self)->xmTabs.bottomgc, poly, 2, CoordModeOrigin);
+       XDrawLines(dpy, win, ((XmTabsWidget)self)->xmTabs.topgc, poly + 1, 4, CoordModeOrigin);
+       XDrawLines(dpy, win, ((XmTabsWidget)self)->xmTabs.bottomgc, poly + 4, 6, CoordModeOrigin);
+    }
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void draw_hor_tab(Widget self,Region  region,int  i)
+#else
+static void draw_hor_tab(self,region,i)Widget self;Region  region;int  i;
+#endif
+{
+    XPoint p[12];
+    Display *dpy = XtDisplay(self);
+    Window win = XtWindow(self);
+    Region clip;
+    int x0, x1, midy;
+
+    comp_hor_tab_shape(self, i, p, &x0, &x1, &midy);
+    clip = XPolygonRegion(p, XtNumber(p), WindingRule);
+    if (region) XIntersectRegion(clip, region, clip);
+    if (XEmptyRegion(clip)) return;
+
+    XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.textgc, clip);
+    XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.topgc, clip);
+    XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.bottomgc, clip);
+    if (i == ((XmTabsWidget)self)->xmTabs.lefttabs) {
+       XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.backgc, clip);
+       XFillPolygon(dpy, win, ((XmTabsWidget)self)->xmTabs.backgc,
+                    p, XtNumber(p), Convex, CoordModeOrigin);
+    } else {
+       XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.fillgc, clip);
+       XFillPolygon(dpy, win, ((XmTabsWidget)self)->xmTabs.fillgc,
+                    p, XtNumber(p), Convex, CoordModeOrigin);
+    }
+    if (((XmTabsWidget)self)->xmTabs.labels) {
+       int w, y, x, len = strlen(((XmTabsWidget)self)->xmTabs.labels[i]);
+       y = midy - (((XmTabsWidget)self)->xmTabs.font->ascent + ((XmTabsWidget)self)->xmTabs.font->descent)/2 + ((XmTabsWidget)self)->xmTabs.font->ascent;
+       w = XTextWidth(((XmTabsWidget)self)->xmTabs.font, ((XmTabsWidget)self)->xmTabs.labels[i], len);
+       if (i == ((XmTabsWidget)self)->xmTabs.lefttabs
+           || ((XmTabsWidget)self)->xmTabs.tabWidthPercentage <= 100/(((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs + 1))
+           x = (x0 + x1 - w)/2;                /* Centered text */
+       else if (i < ((XmTabsWidget)self)->xmTabs.lefttabs)
+           x = x0 + ((XmTabsWidget)self)->xmTabs.textmargin;           /* Left aligned text */
+       else
+           x = x1 - ((XmTabsWidget)self)->xmTabs.textmargin - w;               /* Right aligned text */
+       XDrawString(dpy, win, ((XmTabsWidget)self)->xmTabs.textgc, x, y, ((XmTabsWidget)self)->xmTabs.labels[i], len);
+    }
+    draw_border(self, p);
+    XDestroyRegion(clip);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void draw_ver_tab(Widget self,Region  region,int  i)
+#else
+static void draw_ver_tab(self,region,i)Widget self;Region  region;int  i;
+#endif
+{
+    Display *dpy = XtDisplay(self);
+    Window win = XtWindow(self);
+    XPoint p[12];
+    Region clip;
+    int y0, y1, midx;
+
+    comp_ver_tab_shape(self, i, p, &y0, &y1, &midx);
+    clip = XPolygonRegion(p, XtNumber(p), WindingRule);
+    if (region) XIntersectRegion(clip, region, clip);
+    if (XEmptyRegion(clip)) return;
+
+    XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.textgc, clip);
+    XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.topgc, clip);
+    XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.bottomgc, clip);
+    if (i == ((XmTabsWidget)self)->xmTabs.lefttabs) {
+       XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.backgc, clip);
+       XFillPolygon(dpy, win, ((XmTabsWidget)self)->xmTabs.backgc,
+                    p, XtNumber(p), Convex, CoordModeOrigin);
+    } else {
+       XSetRegion(dpy, ((XmTabsWidget)self)->xmTabs.fillgc, clip);
+       XFillPolygon(dpy, win, ((XmTabsWidget)self)->xmTabs.fillgc,
+                    p, XtNumber(p), Convex, CoordModeOrigin);
+    }
+    if (((XmTabsWidget)self)->xmTabs.labels) {
+       int y, align;
+       float angle = ((XmTabsWidget)self)->xmTabs.orientation == XfwfLeftTabs ? 90.0 : -90.0;
+       if (i == ((XmTabsWidget)self)->xmTabs.lefttabs
+           || ((XmTabsWidget)self)->xmTabs.tabWidthPercentage <= 100/(((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs + 1)) {
+           y = (y0 + y1)/2;
+           align = MCENTRE;
+       } else if (i < ((XmTabsWidget)self)->xmTabs.lefttabs) {
+           y = y0 + ((XmTabsWidget)self)->xmTabs.textmargin;
+           align = ((XmTabsWidget)self)->xmTabs.orientation == XfwfLeftTabs ? MRIGHT : MLEFT;
+       } else {
+           y = y1 - ((XmTabsWidget)self)->xmTabs.textmargin;
+           align = ((XmTabsWidget)self)->xmTabs.orientation == XfwfLeftTabs ? MLEFT : MRIGHT;
+       }
+       XRotDrawAlignedString
+           (dpy, ((XmTabsWidget)self)->xmTabs.font, angle, win, ((XmTabsWidget)self)->xmTabs.textgc, midx, y, ((XmTabsWidget)self)->xmTabs.labels[i], align);
+    }
+    draw_border(self, p);
+    XDestroyRegion(clip);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void create_topgc(Widget self)
+#else
+static void create_topgc(self)Widget self;
+#endif
+{
+    XtGCMask mask = GCForeground | GCLineWidth;
+    XGCValues values;
+
+    if (((XmTabsWidget)self)->xmTabs.topgc != NULL) XFreeGC(XtDisplay(self), ((XmTabsWidget)self)->xmTabs.topgc);
+    values.foreground = ((XmTabsWidget)self)->xmManager.top_shadow_color;
+    values.line_width = 2 * ((XmTabsWidget)self)->xmManager.shadow_thickness;
+    ((XmTabsWidget)self)->xmTabs.topgc = XCreateGC(XtDisplay(self), RootWindowOfScreen(XtScreen(self)),
+                      mask, &values);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void create_bottomgc(Widget self)
+#else
+static void create_bottomgc(self)Widget self;
+#endif
+{
+    XtGCMask mask = GCForeground | GCLineWidth;
+    XGCValues values;
+
+    if (((XmTabsWidget)self)->xmTabs.bottomgc != NULL) XFreeGC(XtDisplay(self), ((XmTabsWidget)self)->xmTabs.bottomgc);
+    values.foreground = ((XmTabsWidget)self)->xmManager.bottom_shadow_color;
+    values.line_width = 2 * ((XmTabsWidget)self)->xmManager.shadow_thickness;
+    ((XmTabsWidget)self)->xmTabs.bottomgc = XCreateGC(XtDisplay(self), RootWindowOfScreen(XtScreen(self)),
+                         mask, &values);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void create_textgc(Widget self)
+#else
+static void create_textgc(self)Widget self;
+#endif
+{
+    XtGCMask mask = GCForeground | GCFont;
+    XGCValues values;
+
+    if (((XmTabsWidget)self)->xmTabs.textgc != NULL) XFreeGC(XtDisplay(self), ((XmTabsWidget)self)->xmTabs.textgc);
+    values.foreground = ((XmTabsWidget)self)->xmManager.foreground;
+    values.font = ((XmTabsWidget)self)->xmTabs.font->fid;
+    ((XmTabsWidget)self)->xmTabs.textgc = XCreateGC(XtDisplay(self), RootWindowOfScreen(XtScreen(self)),
+                       mask, &values);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void create_fillgc(Widget self)
+#else
+static void create_fillgc(self)Widget self;
+#endif
+{
+    XtGCMask mask = GCForeground;
+    XGCValues values;
+
+    if (((XmTabsWidget)self)->xmTabs.fillgc != NULL) XFreeGC(XtDisplay(self), ((XmTabsWidget)self)->xmTabs.fillgc);
+    values.foreground = ((XmTabsWidget)self)->xmTabs.tabcolor;
+    ((XmTabsWidget)self)->xmTabs.fillgc = XCreateGC(XtDisplay(self), RootWindowOfScreen(XtScreen(self)),
+                       mask, &values);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void create_backgc(Widget self)
+#else
+static void create_backgc(self)Widget self;
+#endif
+{
+    XtGCMask mask = GCForeground;
+    XGCValues values;
+
+    if (((XmTabsWidget)self)->xmTabs.backgc != NULL) XFreeGC(XtDisplay(self), ((XmTabsWidget)self)->xmTabs.backgc);
+    values.foreground = ((XmTabsWidget)self)->core.background_pixel;
+    ((XmTabsWidget)self)->xmTabs.backgc = XCreateGC(XtDisplay(self), RootWindowOfScreen(XtScreen(self)),
+                       mask, &values);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void copy_bg(Widget self,int  offset,XrmValue * value)
+#else
+static void copy_bg(self,offset,value)Widget self;int  offset;XrmValue * value;
+#endif
+{
+    value->addr = (XtPointer) &((XmTabsWidget)self)->core.background_pixel;
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void set_shape(Widget self)
+#else
+static void set_shape(self)Widget self;
+#endif
+{
+    int x0, x1, midy, y0, y1, midx, i;
+    Region region, clip;
+    XPoint poly[12];
+
+    if (! XtIsRealized(self)) return;
+
+    region = XCreateRegion();
+
+    switch (((XmTabsWidget)self)->xmTabs.orientation) {
+    case XfwfUpTabs:
+    case XfwfDownTabs:
+       for (i = 0; i <= ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i++) {
+           comp_hor_tab_shape(self, i, poly, &x0, &x1, &midy);
+           clip = XPolygonRegion(poly, XtNumber(poly), WindingRule);
+           XUnionRegion(region, clip, region);
+           XDestroyRegion(clip);
+       }
+       break;
+    case XfwfLeftTabs:
+    case XfwfRightTabs:
+       for (i = 0; i <= ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i++) {
+           comp_ver_tab_shape(self, i, poly, &y0, &y1, &midx);
+           clip = XPolygonRegion(poly, XtNumber(poly), WindingRule);
+           XUnionRegion(region, clip, region);
+           XDestroyRegion(clip);
+       }
+       break;
+    }
+    XShapeCombineRegion(XtDisplay(self), XtWindow(self), ShapeBounding,
+                       0, 0, region, ShapeSet);
+    XDestroyRegion(region);
+}
+
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static Boolean  cvtStringToTabsOrientation(Display * display,XrmValuePtr  args,Cardinal * num_args,XrmValuePtr  from,XrmValuePtr  to,XtPointer * converter_data)
+#else
+static Boolean  cvtStringToTabsOrientation(display,args,num_args,from,to,converter_data)Display * display;XrmValuePtr  args;Cardinal * num_args;XrmValuePtr  from;XrmValuePtr  to;XtPointer * converter_data;
+#endif
+{
+    TabsOrientation a = XfwfUpTabs;
+    char *s = (char*) from->addr;
+    static struct {
+       char *name;
+       TabsOrientation orient;
+    } strings[] = {
+       { "up",  XfwfUpTabs },
+       { "uptabs",  XfwfUpTabs },
+       { "down",  XfwfDownTabs },
+       { "downtabs",  XfwfDownTabs },
+       { "left",  XfwfLeftTabs },
+       { "lefttabs",  XfwfLeftTabs },
+       { "right",  XfwfRightTabs },
+       { "righttabs",  XfwfRightTabs },
+    };
+    int i;
+
+    if (*num_args != 0)
+       XtAppErrorMsg
+           (XtDisplayToApplicationContext(display),
+            "cvtStringToTabsOrientation", "wrongParameters", "XtToolkitError",
+            "String to TabsOrientation conversion needs no arguments",
+            (String*) NULL, (Cardinal*) NULL);
+
+    for (i=0; i<XtNumber(strings); i++)
+       if ( strcmp( s, strings[i].name ) == 0 ) {
+           a |= strings[i].orient;
+           break;
+    }
+
+    if ( i >= XtNumber(strings) )
+       XtDisplayStringConversionWarning(display, s, "TabsOrientation");
+    done(TabsOrientation, a);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static Boolean  cvtTabsOrientationToString(Display * display,XrmValuePtr  args,Cardinal * num_args,XrmValuePtr  from,XrmValuePtr  to,XtPointer * converter_data)
+#else
+static Boolean  cvtTabsOrientationToString(display,args,num_args,from,to,converter_data)Display * display;XrmValuePtr  args;Cardinal * num_args;XrmValuePtr  from;XrmValuePtr  to;XtPointer * converter_data;
+#endif
+{
+    TabsOrientation *a = (TabsOrientation*) from->addr;
+
+    if (*num_args != 0)
+       XtAppErrorMsg
+           (XtDisplayToApplicationContext(display),
+            "cvtTabsOrientationToString", "wrongParameters", "XtToolkitError",
+            "TabsOrientation to String conversion needs no arguments",
+            (String*) NULL, (Cardinal*) NULL);
+    switch (*a) {
+    case XfwfUpTabs: done(String, "up");
+    case XfwfDownTabs: done(String, "down");
+    case XfwfLeftTabs: done(String, "left");
+    case XfwfRightTabs: done(String, "right");
+    }
+    XtAppErrorMsg
+       (XtDisplayToApplicationContext(display),
+        "cvtTabsOrientationToString", "illParameters", "XtToolkitError",
+            "TabsOrientation to String conversion got illegal argument",
+            (String*) NULL, (Cardinal*) NULL);
+    return TRUE;
+}
+
+static XtResource resources[] = {
+{XtNorientation,XtCOrientation,XtRTabsOrientation,sizeof(((XmTabsRec*)NULL)->xmTabs.orientation),XtOffsetOf(XmTabsRec,xmTabs.orientation),XtRImmediate,(XtPointer)XfwfUpTabs },
+{XtNlefttabs,XtCLefttabs,XtRInt,sizeof(((XmTabsRec*)NULL)->xmTabs.lefttabs),XtOffsetOf(XmTabsRec,xmTabs.lefttabs),XtRImmediate,(XtPointer)0 },
+{XtNrighttabs,XtCRighttabs,XtRInt,sizeof(((XmTabsRec*)NULL)->xmTabs.righttabs),XtOffsetOf(XmTabsRec,xmTabs.righttabs),XtRImmediate,(XtPointer)0 },
+{XtNlabels,XtCLabels,XtRStringArray,sizeof(((XmTabsRec*)NULL)->xmTabs.labels),XtOffsetOf(XmTabsRec,xmTabs.labels),XtRImmediate,(XtPointer)NULL },
+{XtNtabWidthPercentage,XtCTabWidthPercentage,XtRInt,sizeof(((XmTabsRec*)NULL)->xmTabs.tabWidthPercentage),XtOffsetOf(XmTabsRec,xmTabs.tabWidthPercentage),XtRImmediate,(XtPointer)50 },
+{XtNcornerwidth,XtCCornerwidth,XtRCardinal,sizeof(((XmTabsRec*)NULL)->xmTabs.cornerwidth),XtOffsetOf(XmTabsRec,xmTabs.cornerwidth),XtRImmediate,(XtPointer)3 },
+{XtNcornerheight,XtCCornerheight,XtRCardinal,sizeof(((XmTabsRec*)NULL)->xmTabs.cornerheight),XtOffsetOf(XmTabsRec,xmTabs.cornerheight),XtRImmediate,(XtPointer)3 },
+{XtNtextmargin,XtCTextmargin,XtRInt,sizeof(((XmTabsRec*)NULL)->xmTabs.textmargin),XtOffsetOf(XmTabsRec,xmTabs.textmargin),XtRImmediate,(XtPointer)3 },
+{XtNtabcolor,XtCTabcolor,XtRPixel,sizeof(((XmTabsRec*)NULL)->xmTabs.tabcolor),XtOffsetOf(XmTabsRec,xmTabs.tabcolor),XtRCallProc,(XtPointer)copy_bg },
+{XtNfont,XtCFont,XtRFontStruct,sizeof(((XmTabsRec*)NULL)->xmTabs.font),XtOffsetOf(XmTabsRec,xmTabs.font),XtRString,(XtPointer)XtDefaultFont },
+{XtNactivateCallback,XtCActivateCallback,XtRCallback,sizeof(((XmTabsRec*)NULL)->xmTabs.activateCallback),XtOffsetOf(XmTabsRec,xmTabs.activateCallback),XtRImmediate,(XtPointer)NULL },
+};
+
+XmTabsClassRec xmTabsClassRec = {
+{ /* core_class part */
+/* superclass          */  (WidgetClass) &xmManagerClassRec,
+/* class_name          */  "XmTabs",
+/* widget_size         */  sizeof(XmTabsRec),
+/* class_initialize    */  class_initialize,
+/* class_part_initialize*/  _resolve_inheritance,
+/* class_inited        */  FALSE,
+/* initialize          */  initialize,
+/* initialize_hook     */  NULL,
+/* realize             */  realize,
+/* actions             */  actionsList,
+/* num_actions         */  1,
+/* resources           */  resources,
+/* num_resources       */  11,
+/* xrm_class           */  NULLQUARK,
+/* compres_motion      */  True ,
+/* compress_exposure   */  XtExposeCompressMultiple ,
+/* compress_enterleave         */  True ,
+/* visible_interest    */  False ,
+/* destroy             */  destroy,
+/* resize              */  resize,
+/* expose              */  expose,
+/* set_values          */  set_values,
+/* set_values_hook     */  NULL,
+/* set_values_almost   */  XtInheritSetValuesAlmost,
+/* get_values+hook     */  NULL,
+/* accept_focus        */  XtInheritAcceptFocus,
+/* version             */  XtVersion,
+/* callback_private    */  NULL,
+/* tm_table            */  defaultTranslations,
+/* query_geometry      */  XtInheritQueryGeometry,
+/* display_acceleator  */  XtInheritDisplayAccelerator,
+/* extension           */  NULL 
+},
+{ /* composite_class part */
+XtInheritGeometryManager,
+XtInheritChangeManaged,
+XtInheritInsertChild,
+XtInheritDeleteChild,
+NULL
+},
+{ /* constraint_class part */
+/* constraint_resources     */  NULL,
+/* num_constraint_resources */  0,
+/* constraint_size          */  sizeof(XmTabsConstraintRec),
+/* constraint_initialize    */  NULL,
+/* constraint_destroy       */  NULL,
+/* constraint_set_values    */  NULL,
+/* constraint_extension     */  NULL 
+},
+{ /* XmManager class part */
+#define manager_extension extension
+/* translations                 */  XtInheritTranslations ,
+/* syn_resources                */  NULL ,
+/* num_syn_resources            */  0 ,
+/* syn_constraint_resources     */  NULL ,
+/* num_syn_constraint_resources */  0 ,
+/* parent_process               */  XmInheritParentProcess,
+/* manager_extension            */  NULL ,
+},
+{ /* XmTabs_class part */
+border_highlight,
+border_unhighlight,
+},
+};
+WidgetClass xmTabsWidgetClass = (WidgetClass) &xmTabsClassRec;
+/*ARGSUSED*/
+static void activate(Widget self, XEvent *event, String *params, Cardinal *num_params)
+{
+    int x0, x1, dummy, i, x, y;
+    XPoint poly[12];
+
+    switch (((XmTabsWidget)self)->xmTabs.orientation) {
+    case XfwfUpTabs:
+    case XfwfDownTabs:
+       x = event->xbutton.x;
+       comp_hor_tab_shape(self, ((XmTabsWidget)self)->xmTabs.lefttabs, poly, &x0, &x1, &dummy);
+       if (x0 <= x && x < x1) {
+           XtCallCallbackList(self, ((XmTabsWidget)self)->xmTabs.activateCallback, (XtPointer) 0);
+           return;
+       }
+       for (i = -1; i >= -((XmTabsWidget)self)->xmTabs.lefttabs; i--) {
+           comp_hor_tab_shape(self, i + ((XmTabsWidget)self)->xmTabs.lefttabs, poly, &x0, &x1, &dummy);
+           if (x0 <= x && x < x1) {
+               XtCallCallbackList(self, ((XmTabsWidget)self)->xmTabs.activateCallback, (XtPointer) i);
+               return;
+           }
+       }
+       for (i = 1; i <= ((XmTabsWidget)self)->xmTabs.righttabs; i++) {
+           comp_hor_tab_shape(self, i + ((XmTabsWidget)self)->xmTabs.lefttabs, poly, &x0, &x1, &dummy);
+           if (x0 <= x && x < x1) {
+               XtCallCallbackList(self, ((XmTabsWidget)self)->xmTabs.activateCallback, (XtPointer) i);
+               return;
+           }
+       }
+       break;
+    case XfwfLeftTabs:
+    case XfwfRightTabs:
+       y = event->xbutton.y;
+       comp_ver_tab_shape(self, ((XmTabsWidget)self)->xmTabs.lefttabs, poly, &x0, &x1, &dummy);
+       if (x0 <= y && y < x1) {
+           XtCallCallbackList(self, ((XmTabsWidget)self)->xmTabs.activateCallback, (XtPointer) 0);
+           return;
+       }
+       for (i = -1; i >= -((XmTabsWidget)self)->xmTabs.lefttabs; i--) {
+           comp_ver_tab_shape(self, i + ((XmTabsWidget)self)->xmTabs.lefttabs, poly, &x0, &x1, &dummy);
+           if (x0 <= y && y < x1) {
+               XtCallCallbackList(self, ((XmTabsWidget)self)->xmTabs.activateCallback, (XtPointer) i);
+               return;
+           }
+       }
+       for (i = 1; i <= ((XmTabsWidget)self)->xmTabs.righttabs; i++) {
+           comp_ver_tab_shape(self, i + ((XmTabsWidget)self)->xmTabs.lefttabs, poly, &x0, &x1, &dummy);
+           if (x0 <= y && y < x1) {
+               XtCallCallbackList(self, ((XmTabsWidget)self)->xmTabs.activateCallback, (XtPointer) i);
+               return;
+           }
+       }
+       break;
+    }
+}
+
+static void _resolve_inheritance(WidgetClass class)
+{
+  XmTabsWidgetClass c = (XmTabsWidgetClass) class;
+  XmTabsWidgetClass super;
+  static CompositeClassExtensionRec extension_rec = {
+    NULL, NULLQUARK, XtCompositeExtensionVersion,
+    sizeof(CompositeClassExtensionRec), True};
+  CompositeClassExtensionRec *ext;
+  ext = (XtPointer)XtMalloc(sizeof(*ext));
+  *ext = extension_rec;
+  ext->next_extension = c->composite_class.extension;
+  c->composite_class.extension = ext;
+  if (class == xmTabsWidgetClass) return;
+  super = (XmTabsWidgetClass)class->core_class.superclass;
+  if (c->xmTabs_class.border_highlight == XtInherit_border_highlight)
+    c->xmTabs_class.border_highlight = super->xmTabs_class.border_highlight;
+  if (c->xmTabs_class.border_unhighlight == XtInherit_border_unhighlight)
+    c->xmTabs_class.border_unhighlight = super->xmTabs_class.border_unhighlight;
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void class_initialize(void)
+#else
+static void class_initialize(void)
+#endif
+{
+    XtSetTypeConverter(XtRString, "StringArray",
+                      cvtStringToStringArray,
+                      NULL, 0, XtCacheNone, NULL);
+    XtSetTypeConverter(XtRString, "TabsOrientation",
+                      cvtStringToTabsOrientation,
+                      NULL, 0, XtCacheNone, NULL);
+    XtSetTypeConverter("TabsOrientation", XtRString,
+                      cvtTabsOrientationToString,
+                      NULL, 0, XtCacheNone, NULL);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void initialize(Widget  request,Widget self,ArgList  args,Cardinal * num_args)
+#else
+static void initialize(request,self,args,num_args)Widget  request;Widget self;ArgList  args;Cardinal * num_args;
+#endif
+{
+    String *h;
+    int i;
+
+    ((XmTabsWidget)self)->xmManager.traversal_on = FALSE;
+    ((XmTabsWidget)self)->xmTabs.topgc = NULL;
+    create_topgc(self);
+    ((XmTabsWidget)self)->xmTabs.bottomgc = NULL;
+    create_bottomgc(self);
+    ((XmTabsWidget)self)->xmTabs.textgc = NULL;
+    create_textgc(self);
+    ((XmTabsWidget)self)->xmTabs.fillgc = NULL;
+    create_fillgc(self);
+    ((XmTabsWidget)self)->xmTabs.backgc = NULL;
+    create_backgc(self);
+    if (((XmTabsWidget)self)->xmTabs.labels) {
+       h = (String*) XtMalloc((((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs + 1) * sizeof(*h));
+       for (i = ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i >= 0; i--)
+           h[i] = XtNewString(((XmTabsWidget)self)->xmTabs.labels[i]);
+       ((XmTabsWidget)self)->xmTabs.labels = h;
+    }
+    if (((XmTabsWidget)self)->xmTabs.tabWidthPercentage < 0 || ((XmTabsWidget)self)->xmTabs.tabWidthPercentage > 100) {
+       XtAppWarning(XtWidgetToApplicationContext(self),
+                    "tabWidthPercentage out of range; reset to 50");
+       ((XmTabsWidget)self)->xmTabs.tabWidthPercentage = 50;
+    }
+    ((XmTabsWidget)self)->xmTabs.offsets = NULL;
+    ((XmTabsWidget)self)->xmTabs.tabwidths = NULL;
+    compute_tabsizes(self);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static Boolean  set_values(Widget  old,Widget  request,Widget self,ArgList  args,Cardinal * num_args)
+#else
+static Boolean  set_values(old,request,self,args,num_args)Widget  old;Widget  request;Widget self;ArgList  args;Cardinal * num_args;
+#endif
+{
+    Bool redraw = FALSE, resize_labels = FALSE;
+    String *h;
+    int i;
+
+    if (((XmTabsWidget)self)->core.background_pixel != ((XmTabsWidget)old)->core.background_pixel
+       || ((XmTabsWidget)self)->core.background_pixmap != ((XmTabsWidget)old)->core.background_pixmap
+       || ((XmTabsWidget)self)->xmManager.shadow_thickness != ((XmTabsWidget)old)->xmManager.shadow_thickness) {
+       create_topgc(self);
+       create_bottomgc(self);
+       create_backgc(self);
+    }
+    if (((XmTabsWidget)self)->xmManager.foreground != ((XmTabsWidget)old)->xmManager.foreground || ((XmTabsWidget)self)->xmTabs.font != ((XmTabsWidget)old)->xmTabs.font) {
+       create_textgc(self);
+       redraw = TRUE;
+    }
+    if (((XmTabsWidget)self)->xmTabs.tabcolor != ((XmTabsWidget)old)->xmTabs.tabcolor) {
+       create_fillgc(self);
+       redraw = TRUE;
+    }
+    if ((((XmTabsWidget)self)->xmTabs.textmargin != ((XmTabsWidget)old)->xmTabs.textmargin && ((XmTabsWidget)self)->xmTabs.tabWidthPercentage == 0)
+       || ((XmTabsWidget)self)->xmTabs.cornerwidth != ((XmTabsWidget)old)->xmTabs.cornerwidth
+       || ((XmTabsWidget)self)->xmTabs.cornerheight != ((XmTabsWidget)old)->xmTabs.cornerheight) {
+       resize_labels = TRUE;
+    }
+    if (((XmTabsWidget)self)->xmTabs.labels != ((XmTabsWidget)old)->xmTabs.labels) {
+       if (((XmTabsWidget)self)->xmTabs.labels) {
+           h = (String*) XtMalloc((((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs + 1) * sizeof(*h));
+           for (i = ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i >= 0; i--)
+               h[i] = XtNewString(((XmTabsWidget)self)->xmTabs.labels[i]);
+           ((XmTabsWidget)self)->xmTabs.labels = h;
+       }
+       if (((XmTabsWidget)old)->xmTabs.labels) {
+           for (i = ((XmTabsWidget)old)->xmTabs.lefttabs + ((XmTabsWidget)old)->xmTabs.righttabs; i >= 0; i--)
+               XtFree(((XmTabsWidget)old)->xmTabs.labels[i]);
+           XtFree((XtPointer) ((XmTabsWidget)old)->xmTabs.labels);
+       }
+       resize_labels = TRUE;
+    }
+    if (((XmTabsWidget)self)->xmTabs.tabWidthPercentage < 0 || ((XmTabsWidget)self)->xmTabs.tabWidthPercentage > 100) {
+       XtAppWarning(XtWidgetToApplicationContext(self),
+                    "tabWidthPercentage out of range; reset to 50");
+       ((XmTabsWidget)self)->xmTabs.tabWidthPercentage = 50;
+    }
+    if (((XmTabsWidget)old)->xmTabs.tabWidthPercentage != ((XmTabsWidget)self)->xmTabs.tabWidthPercentage)
+       resize_labels = TRUE;
+    if (((XmTabsWidget)self)->xmTabs.lefttabs != ((XmTabsWidget)old)->xmTabs.lefttabs || ((XmTabsWidget)self)->xmTabs.righttabs != ((XmTabsWidget)old)->xmTabs.righttabs)
+       redraw = TRUE;
+    if (resize_labels) {
+       compute_tabsizes(self);
+       redraw = TRUE;
+    }
+    return redraw;
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void realize(Widget self,XtValueMask * mask,XSetWindowAttributes * attributes)
+#else
+static void realize(self,mask,attributes)Widget self;XtValueMask * mask;XSetWindowAttributes * attributes;
+#endif
+{
+    *mask |= CWBitGravity;
+    attributes->bit_gravity = ForgetGravity;
+    xmManagerClassRec.core_class.realize(self, mask, attributes);
+    set_shape(self);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void resize(Widget self)
+#else
+static void resize(self)Widget self;
+#endif
+{
+    if (XtIsRealized(self))
+       XClearArea(XtDisplay(self), XtWindow(self), 0, 0, 0, 0, True);
+    compute_tabsizes(self);
+    set_shape(self);
+    if ( xmManagerClassRec.core_class.resize ) xmManagerClassRec.core_class.resize(self);
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void expose(Widget self,XEvent * event,Region  region)
+#else
+static void expose(self,event,region)Widget self;XEvent * event;Region  region;
+#endif
+{
+    int i;
+
+    if (! XtIsRealized(self)) return;
+
+    switch (((XmTabsWidget)self)->xmTabs.orientation) {
+    case XfwfUpTabs:
+    case XfwfDownTabs:
+       for (i = 0; i < ((XmTabsWidget)self)->xmTabs.lefttabs; i++)
+           draw_hor_tab(self, region, i);
+       for (i = ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i > ((XmTabsWidget)self)->xmTabs.lefttabs; i--)
+           draw_hor_tab(self, region, i);
+       draw_hor_tab(self, region, ((XmTabsWidget)self)->xmTabs.lefttabs);
+       break;
+    case XfwfLeftTabs:
+    case XfwfRightTabs:
+       for (i = 0; i < ((XmTabsWidget)self)->xmTabs.lefttabs; i++)
+           draw_ver_tab(self, region, i);
+       for (i = ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i > ((XmTabsWidget)self)->xmTabs.lefttabs; i--)
+           draw_ver_tab(self, region, i);
+       draw_ver_tab(self, region, ((XmTabsWidget)self)->xmTabs.lefttabs);
+       break;
+    }
+    /* Focus highlight? */
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void border_highlight(void)
+#else
+static void border_highlight(void)
+#endif
+{
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void border_unhighlight(void)
+#else
+static void border_unhighlight(void)
+#endif
+{
+}
+/*ARGSUSED*/
+#if NeedFunctionPrototypes
+static void destroy(Widget self)
+#else
+static void destroy(self)Widget self;
+#endif
+{
+    int i;
+
+    if (((XmTabsWidget)self)->xmTabs.labels) {
+       for (i = ((XmTabsWidget)self)->xmTabs.lefttabs + ((XmTabsWidget)self)->xmTabs.righttabs; i >= 0; i--)
+           XtFree(((XmTabsWidget)self)->xmTabs.labels[i]);
+       XtFree((XtPointer) ((XmTabsWidget)self)->xmTabs.labels);
+    }
+    if (((XmTabsWidget)self)->xmTabs.offsets)
+       XtFree((XtPointer) ((XmTabsWidget)self)->xmTabs.offsets);
+    if (((XmTabsWidget)self)->xmTabs.tabwidths)
+       XtFree((XtPointer) ((XmTabsWidget)self)->xmTabs.tabwidths);
+}
+
+\f
+/* ***********************************************************************
+ * Routines for drawing rotated text
+ * ***********************************************************************
+ */
+
+/* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma)
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both the
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  All work developed as a consequence of the use of
+ * this program should duly acknowledge such use. No representations are
+ * made about the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ *
+ * 8 Jun '95: [Bert Bos] added GCClipXOrigin|GCClipYOrigin|GCClipMask
+ * when calling XCopyGC()
+ */
+
+/* ********************************************************************** */
+
+
+/* BETTER: xvertext now does rotation at any angle!!
+ *
+ * BEWARE: function arguments have CHANGED since version 2.0!!
+ */
+
+/* ********************************************************************** */
+
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* Make sure cache size is set */
+
+#ifndef CACHE_SIZE_LIMIT
+#define CACHE_SIZE_LIMIT 0
+#endif /*CACHE_SIZE_LIMIT */
+    
+/* Make sure a cache method is specified */
+
+#ifndef CACHE_XIMAGES
+#ifndef CACHE_BITMAPS
+#define CACHE_BITMAPS
+#endif /*CACHE_BITMAPS*/
+#endif /*CACHE_XIMAGES*/
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* Debugging macros */
+
+#ifdef DEBUG
+static int debug=1;
+#else
+static int debug=0;
+#endif /*DEBUG*/
+
+#define DEBUG_PRINT1(a) if (debug) printf (a)
+#define DEBUG_PRINT2(a, b) if (debug) printf (a, b)
+#define DEBUG_PRINT3(a, b, c) if (debug) printf (a, b, c)
+#define DEBUG_PRINT4(a, b, c, d) if (debug) printf (a, b, c, d)
+#define DEBUG_PRINT5(a, b, c, d, e) if (debug) printf (a, b, c, d, e)
+
+
+/* ---------------------------------------------------------------------- */
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* A structure holding everything needed for a rotated string */
+
+typedef struct rotated_text_item_template {
+    Pixmap bitmap;
+    XImage *ximage;
+    
+    char *text;
+    char *font_name;
+    Font fid;
+    float angle;
+    int align;
+    float magnify;
+    
+    int cols_in;
+    int rows_in;
+    int cols_out;
+    int rows_out;
+    
+    int nl;
+    int max_width;
+    float *corners_x;
+    float *corners_y;
+    
+    long int size;
+    int cached;
+
+    struct rotated_text_item_template *next;
+} RotatedTextItem;
+
+RotatedTextItem *first_text_item=NULL;
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/* A structure holding current magnification and bounding box padding */
+
+static struct style_template {
+    float magnify;
+    int bbx_pad;
+} style={
+    1.,
+    0
+    };
+
+
+/* ---------------------------------------------------------------------- */
+
+
+static char            *my_strdup(char *str);
+static char            *my_strtok(char *str1, char *str2);
+
+static float                   XRotVersion(char *str, int n);
+static void                    XRotSetMagnification(float m);
+static void                    XRotSetBoundingBoxPad(int p);
+static int                     XRotDrawString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str);
+static int                     XRotDrawImageString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str);
+static int                     XRotDrawAlignedString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align);
+static int                     XRotDrawAlignedImageString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align);
+static XPoint                 *XRotTextExtents(Display *dpy, XFontStruct *font, float angle, int x, int y, char *text, int align);
+
+static XImage          *MakeXImage(Display *dpy, int w, int h);
+static int              XRotPaintAlignedString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align, int bg);
+static int              XRotDrawHorizontalString(Display *dpy, XFontStruct *font, Drawable drawable, GC gc, int x, int y, char *text, int align, int bg);
+static RotatedTextItem *XRotRetrieveFromCache(Display *dpy, XFontStruct *font, float angle, char *text, int align);
+static RotatedTextItem *XRotCreateTextItem(Display *dpy, XFontStruct *font, float angle, char *text, int align);
+static void             XRotAddToLinkedList(Display *dpy, RotatedTextItem *item);
+static void             XRotFreeTextItem(Display *dpy, RotatedTextItem *item);
+static XImage          *XRotMagnifyImage(Display *dpy, XImage *ximage);
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Routine to mimic `strdup()' (some machines don't have it)              */
+/**************************************************************************/
+
+static char *my_strdup(char *str)
+{
+    char *s;
+    
+    if(str==NULL)
+       return NULL;
+    
+    s=(char *)malloc((unsigned)(strlen(str)+1));
+    if(s!=NULL) 
+       strcpy(s, str);
+    
+    return s;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Routine to replace `strtok' : this one returns a zero length string if */
+/* it encounters two consecutive delimiters                               */
+/**************************************************************************/
+
+static char *my_strtok(char *str1, char *str2)
+{
+    char *ret;
+    int i, j, stop;
+    static int start, len;
+    static char *stext;
+    
+    if(str2==NULL)
+       return NULL;
+    
+    /* initialise if str1 not NULL */
+    if(str1!=NULL) {
+       start=0;
+       stext=str1;
+       len=strlen(str1);
+    }
+    
+    /* run out of tokens ? */
+    if(start>=len)
+       return NULL;
+    
+    /* loop through characters */
+    for(i=start; i<len; i++) {
+       /* loop through delimiters */
+       stop=0;
+       for(j=0; j<strlen(str2); j++)
+           if(stext[i]==str2[j])
+               stop=1;
+       
+       if(stop)
+           break;
+    }
+    
+    stext[i]='\0';
+    
+    ret=stext+start;
+    
+    start=i+1;
+    
+    return ret;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Return version/copyright information                                   */
+/**************************************************************************/
+static
+float XRotVersion(char *str, int n)
+{
+    if(str!=NULL)
+       strncpy(str, XV_COPYRIGHT, n);
+    return XV_VERSION;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Set the font magnification factor for all subsequent operations        */
+/**************************************************************************/
+static
+void XRotSetMagnification(float m)
+{
+    if(m>0.)
+       style.magnify=m;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Set the padding used when calculating bounding boxes                   */
+/**************************************************************************/
+static
+void XRotSetBoundingBoxPad(int p)
+{
+    if(p>=0)
+       style.bbx_pad=p;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  Create an XImage structure and allocate memory for it                 */
+/**************************************************************************/
+
+static XImage *MakeXImage(Display *dpy, int w, int h)
+{
+    XImage *I;
+    char *data;
+    
+    /* reserve memory for image */
+    data=(char *)calloc((unsigned)(((w-1)/8+1)*h), 1);
+    if(data==NULL)
+       return NULL;
+    
+    /* create the XImage */
+    I=XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), 1, XYBitmap,
+                   0, data, w, h, 8, 0);
+    if(I==NULL)
+       return NULL;
+    
+    I->byte_order=I->bitmap_bit_order=MSBFirst;
+    return I;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  A front end to XRotPaintAlignedString:                                */
+/*      -no alignment, no background                                      */
+/**************************************************************************/
+static
+int XRotDrawString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str)
+{
+    return (XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+                                  x, y, str, NONE, 0));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  A front end to XRotPaintAlignedString:                                */
+/*      -no alignment, paints background                                  */
+/**************************************************************************/
+static
+int XRotDrawImageString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *str)
+{
+    return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+                                 x, y, str, NONE, 1));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  A front end to XRotPaintAlignedString:                                */
+/*      -does alignment, no background                                    */
+/**************************************************************************/
+static 
+int XRotDrawAlignedString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align)
+{
+    return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+                                 x, y, text, align, 0));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  A front end to XRotPaintAlignedString:                                */
+/*      -does alignment, paints background                                */
+/**************************************************************************/
+static
+int XRotDrawAlignedImageString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align)
+{
+    return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
+                                 x, y, text, align, 1));
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  Aligns and paints a rotated string                                    */
+/**************************************************************************/
+
+static int XRotPaintAlignedString(Display *dpy, XFontStruct *font, float angle, Drawable drawable, GC gc, int x, int y, char *text, int align, int bg)
+{
+    int i;
+    GC my_gc;
+    int xp, yp;
+    float hot_x, hot_y;
+    float hot_xp, hot_yp;
+    float sin_angle, cos_angle;
+    RotatedTextItem *item;
+    Pixmap bitmap_to_paint;
+    
+    /* return early for NULL/empty strings */
+    if(text==NULL)
+        return 0;
+    
+    if(strlen(text)==0)
+       return 0;
+
+    /* manipulate angle to 0<=angle<360 degrees */
+    while(angle<0)
+        angle+=360;
+    
+    while(angle>=360)
+        angle-=360;
+    
+    angle*=M_PI/180;
+    
+    /* horizontal text made easy */
+    if(angle==0. && style.magnify==1.) 
+       return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y,
+                                       text, align, bg));
+    
+    /* get a rotated bitmap */
+    item=XRotRetrieveFromCache(dpy, font, angle, text, align);
+    if(item==NULL)
+       return NULL;
+    
+    /* this gc has similar properties to the user's gc */
+    my_gc=XCreateGC(dpy, drawable, NULL, 0);
+    XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask
+           |GCClipXOrigin|GCClipYOrigin|GCClipMask, my_gc);
+
+    /* alignment : which point (hot_x, hot_y) relative to bitmap centre
+       coincides with user's specified point? */
+    
+    /* y position */
+    if(align==TLEFT || align==TCENTRE || align==TRIGHT)
+        hot_y=(float)item->rows_in/2*style.magnify;
+    else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
+       hot_y=0;
+    else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
+       hot_y = -(float)item->rows_in/2*style.magnify;
+    else
+       hot_y = -((float)item->rows_in/2-(float)font->descent)*style.magnify;
+    
+    /* x position */
+    if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+       hot_x = -(float)item->max_width/2*style.magnify;
+    else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+       hot_x=0;
+    else
+        hot_x=(float)item->max_width/2*style.magnify;
+    
+    /* pre-calculate sin and cos */
+    sin_angle=sin(angle);
+    cos_angle=cos(angle);
+    
+    /* rotate hot_x and hot_y around bitmap centre */
+    hot_xp= hot_x*cos_angle - hot_y*sin_angle;
+    hot_yp= hot_x*sin_angle + hot_y*cos_angle;
+    
+    /* text background will be drawn using XFillPolygon */
+    if(bg) {
+       GC depth_one_gc;
+       XPoint *xpoints;
+       Pixmap empty_stipple;
+       
+       /* reserve space for XPoints */
+       xpoints=(XPoint *)malloc((unsigned)(4*item->nl*sizeof(XPoint)));
+       if(!xpoints)
+           return 1;
+       
+       /* rotate corner positions */
+       for(i=0; i<4*item->nl; i++) {
+           xpoints[i].x=(float)x + ( (item->corners_x[i]-hot_x)*cos_angle + 
+                                     (item->corners_y[i]+hot_y)*sin_angle);
+           xpoints[i].y=(float)y + (-(item->corners_x[i]-hot_x)*sin_angle + 
+                                     (item->corners_y[i]+hot_y)*cos_angle);
+       }
+       
+       /* we want to swap foreground and background colors here;
+          XGetGCValues() is only available in R4+ */
+       
+       empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1);
+       
+       depth_one_gc=XCreateGC(dpy, empty_stipple, NULL, 0);
+       XSetForeground(dpy, depth_one_gc, 0);
+       XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2);
+
+       XSetStipple(dpy, my_gc, empty_stipple);
+       XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
+       
+       XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->nl, Nonconvex,
+                    CoordModeOrigin);
+       
+       /* free our resources */
+       free((char *)xpoints);
+       XFreeGC(dpy, depth_one_gc);
+       XFreePixmap(dpy, empty_stipple);
+    }
+    
+    /* where should top left corner of bitmap go ? */
+    xp=(float)x-((float)item->cols_out/2 +hot_xp);
+    yp=(float)y-((float)item->rows_out/2 -hot_yp);
+    
+    /* by default we draw the rotated bitmap, solid */
+    bitmap_to_paint=item->bitmap;
+
+    /* handle user stippling */
+#ifndef X11R3
+    {
+       GC depth_one_gc;
+       XGCValues values;
+       Pixmap new_bitmap, inverse;
+       
+       /* try and get some GC properties */
+       if(XGetGCValues(dpy, gc, 
+                       GCStipple|GCFillStyle|GCForeground|GCBackground|
+                       GCTileStipXOrigin|GCTileStipYOrigin,
+                       &values)) {
+
+           /* only do this if stippling requested */
+           if((values.fill_style==FillStippled ||
+               values.fill_style==FillOpaqueStippled) && !bg) {
+
+               /* opaque stipple: draw rotated text in background colour */
+               if(values.fill_style==FillOpaqueStippled) {
+                   XSetForeground(dpy, my_gc, values.background);
+                   XSetFillStyle(dpy, my_gc, FillStippled);
+                   XSetStipple(dpy, my_gc, item->bitmap);
+                   XSetTSOrigin(dpy, my_gc, xp, yp);
+                   XFillRectangle(dpy, drawable, my_gc, xp, yp,
+                                  item->cols_out, item->rows_out);
+                   XSetForeground(dpy, my_gc, values.foreground);
+               }
+
+               /* this will merge the rotated text and the user's stipple */
+               new_bitmap=XCreatePixmap(dpy, drawable,
+                                        item->cols_out, item->rows_out, 1);
+
+               /* create a GC */
+               depth_one_gc=XCreateGC(dpy, new_bitmap, NULL, 0);
+               XSetForeground(dpy, depth_one_gc, 1);
+               XSetBackground(dpy, depth_one_gc, 0);
+
+               /* set the relative stipple origin */
+               XSetTSOrigin(dpy, depth_one_gc, 
+                            values.ts_x_origin-xp, values.ts_y_origin-yp);
+
+               /* fill the whole bitmap with the user's stipple */
+               XSetStipple(dpy, depth_one_gc, values.stipple);
+               XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled);
+               XFillRectangle(dpy, new_bitmap, depth_one_gc,
+                              0, 0, item->cols_out, item->rows_out);
+
+               /* set stipple origin back to normal */
+               XSetTSOrigin(dpy, depth_one_gc, 0, 0);
+
+               /* this will contain an inverse copy of the rotated text */
+               inverse=XCreatePixmap(dpy, drawable,
+                                     item->cols_out, item->rows_out, 1);
+
+               /* invert text */
+               XSetFillStyle(dpy, depth_one_gc, FillSolid);
+               XSetFunction(dpy, depth_one_gc, GXcopyInverted);
+               XCopyArea(dpy, item->bitmap, inverse, depth_one_gc,
+                         0, 0, item->cols_out, item->rows_out, 0, 0);
+
+               /* now delete user's stipple everywhere EXCEPT on text */
+                XSetForeground(dpy, depth_one_gc, 0);
+                XSetBackground(dpy, depth_one_gc, 1);
+               XSetStipple(dpy, depth_one_gc, inverse);
+               XSetFillStyle(dpy, depth_one_gc, FillStippled);
+               XSetFunction(dpy, depth_one_gc, GXcopy);
+               XFillRectangle(dpy, new_bitmap, depth_one_gc,
+                               0, 0, item->cols_out, item->rows_out);
+
+               /* free resources */
+               XFreePixmap(dpy, inverse);
+               XFreeGC(dpy, depth_one_gc);
+
+               /* this is the new bitmap */
+               bitmap_to_paint=new_bitmap;
+           }
+       }
+    }
+#endif /*X11R3*/
+
+    /* paint text using stipple technique */
+    XSetFillStyle(dpy, my_gc, FillStippled);
+    XSetStipple(dpy, my_gc, bitmap_to_paint);
+    XSetTSOrigin(dpy, my_gc, xp, yp);
+    XFillRectangle(dpy, drawable, my_gc, xp, yp, 
+                  item->cols_out, item->rows_out);
+    
+    /* free our resources */
+    XFreeGC(dpy, my_gc);
+
+    /* stippled bitmap no longer needed */
+    if(bitmap_to_paint!=item->bitmap)
+       XFreePixmap(dpy, bitmap_to_paint);
+
+#ifdef CACHE_XIMAGES
+    XFreePixmap(dpy, item->bitmap);
+#endif /*CACHE_XIMAGES*/
+
+    /* if item isn't cached, destroy it completely */
+    if(!item->cached) 
+       XRotFreeTextItem(dpy,item);
+
+    /* we got to the end OK! */
+    return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  Draw a horizontal string in a quick fashion                           */
+/**************************************************************************/
+
+static int XRotDrawHorizontalString(Display *dpy, XFontStruct *font, Drawable drawable, GC gc, int x, int y, char *text, int align, int bg)
+{
+    GC my_gc;
+    int nl=1, i;
+    int height;
+    int xp, yp;
+    char *str1, *str2, *str3;
+    char *str2_a="\0", *str2_b="\n\0";
+    int dir, asc, desc;
+    XCharStruct overall;
+
+    DEBUG_PRINT1("**\nHorizontal text.\n");
+
+    /* this gc has similar properties to the user's gc (including stipple) */
+    my_gc=XCreateGC(dpy, drawable, NULL, 0);
+    XCopyGC(dpy, gc,
+           GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle|
+           GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask|
+           GCClipXOrigin|GCClipYOrigin|GCClipMask, my_gc);
+    XSetFont(dpy, my_gc, font->fid);
+       
+    /* count number of sections in string */
+    if(align!=NONE)
+       for(i=0; i<strlen(text)-1; i++)
+           if(text[i]=='\n')
+               nl++;
+    
+    /* ignore newline characters if not doing alignment */
+    if(align==NONE)
+       str2=str2_a;
+    else
+       str2=str2_b;
+    
+    /* overall font height */
+    height=font->ascent+font->descent;
+    
+    /* y position */
+    if(align==TLEFT || align==TCENTRE || align==TRIGHT)
+       yp=y+font->ascent;
+    else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
+       yp=y-nl*height/2+font->ascent;
+    else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
+       yp=y-nl*height+font->ascent;
+    else
+       yp=y;
+    
+    str1=my_strdup(text);
+    if(str1==NULL)
+       return 1;
+    
+    str3=my_strtok(str1, str2);
+    
+    /* loop through each section in the string */
+    do {
+        XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+                     &overall);
+
+       /* where to draw section in x ? */
+       if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+           xp=x;
+       else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+           xp=x-overall.rbearing/2;
+       else
+           xp=x-overall.rbearing;
+       
+       /* draw string onto bitmap */
+       if(!bg)
+           XDrawString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
+       else
+           XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
+       
+       /* move to next line */
+       yp+=height;
+       
+       str3=my_strtok((char *)NULL, str2);
+    }
+    while(str3!=NULL);
+    
+    free(str1);
+    XFreeGC(dpy, my_gc);
+
+    return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*   Query cache for a match with this font/text/angle/alignment          */
+/*       request, otherwise arrange for its creation                      */
+/**************************************************************************/
+
+static RotatedTextItem *XRotRetrieveFromCache(Display *dpy, XFontStruct *font, float angle, char *text, int align)
+{
+    Font fid;
+    char *font_name=NULL;
+    unsigned long name_value;
+    RotatedTextItem *item=NULL;
+    RotatedTextItem *i1=first_text_item;
+    
+    /* get font name, if it exists */
+    if(XGetFontProperty(font, XA_FONT, &name_value)) {
+       DEBUG_PRINT1("got font name OK\n");
+       font_name=XGetAtomName(dpy, name_value);
+       fid=0;
+    }
+#ifdef CACHE_FID
+    /* otherwise rely (unreliably?) on font ID */
+    else {
+       DEBUG_PRINT1("can't get fontname, caching FID\n");
+       font_name=NULL;
+       fid=font->fid;
+    }
+#else
+    /* not allowed to cache font ID's */
+    else {
+       DEBUG_PRINT1("can't get fontname, can't cache\n");
+       font_name=NULL;
+       fid=0;
+    }
+#endif /*CACHE_FID*/
+    
+    /* look for a match in cache */
+
+    /* matching formula:
+       identical text;
+       identical fontname (if defined, font ID's if not);
+       angles close enough (<0.00001 here, could be smaller);
+       HORIZONTAL alignment matches, OR it's a one line string;
+       magnifications the same */
+
+    while(i1 && !item) {
+       /* match everything EXCEPT fontname/ID */
+       if(strcmp(text, i1->text)==0 &&
+          fabs(angle-i1->angle)<0.00001 &&
+          style.magnify==i1->magnify &&
+          (i1->nl==1 ||
+           ((align==0)?9:(align-1))%3==
+             ((i1->align==0)?9:(i1->align-1))%3)) {
+
+           /* now match fontname/ID */
+           if(font_name!=NULL && i1->font_name!=NULL) {
+               if(strcmp(font_name, i1->font_name)==0) {
+                   item=i1;
+                   DEBUG_PRINT1("Matched against font names\n");
+               }
+               else
+                   i1=i1->next;
+           }
+#ifdef CACHE_FID
+           else if(font_name==NULL && i1->font_name==NULL) {
+               if(fid==i1->fid) {
+                   item=i1;
+                   DEBUG_PRINT1("Matched against FID's\n");
+                }
+               else
+                    i1=i1->next;
+           }
+#endif /*CACHE_FID*/
+           else
+               i1=i1->next;
+       }
+       else
+           i1=i1->next;
+    }
+    
+    if(item)
+       DEBUG_PRINT1("**\nFound target in cache.\n");
+    if(!item)
+       DEBUG_PRINT1("**\nNo match in cache.\n");
+
+    /* no match */
+    if(!item) {
+       /* create new item */
+       item=XRotCreateTextItem(dpy, font, angle, text, align);
+       if(!item)
+           return NULL;
+
+       /* record what it shows */
+       item->text=my_strdup(text);
+
+       /* fontname or ID */
+       if(font_name!=NULL) {
+           item->font_name=my_strdup(font_name);
+           item->fid=0;
+       }
+       else {
+           item->font_name=NULL;
+           item->fid=fid;
+       }
+
+       item->angle=angle;
+       item->align=align;
+       item->magnify=style.magnify;
+
+       /* cache it */
+       XRotAddToLinkedList(dpy, item);
+    }
+
+    if(font_name)
+       XFree(font_name);
+
+    /* if XImage is cached, need to recreate the bitmap */
+
+#ifdef CACHE_XIMAGES
+    {
+       GC depth_one_gc;
+
+       /* create bitmap to hold rotated text */
+       item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+                                  item->cols_out, item->rows_out, 1);
+       
+       /* depth one gc */
+       depth_one_gc=XCreateGC(dpy, item->bitmap, NULL, 0);
+       XSetBackground(dpy, depth_one_gc, 0);
+       XSetForeground(dpy, depth_one_gc, 1);
+
+       /* make the text bitmap from XImage */
+       XPutImage(dpy, item->bitmap, depth_one_gc, item->ximage, 0, 0, 0, 0,
+                 item->cols_out, item->rows_out);
+
+       XFreeGC(dpy, depth_one_gc);
+    }
+#endif /*CACHE_XIMAGES*/
+    
+    return item;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  Create a rotated text item                                            */
+/**************************************************************************/
+
+static RotatedTextItem *XRotCreateTextItem(Display *dpy, XFontStruct *font, float angle, char *text, int align)
+{
+    RotatedTextItem *item=NULL;
+    Pixmap canvas;
+    GC font_gc;
+    XImage *I_in;
+    register int i, j;
+    char *str1, *str2, *str3;
+    char *str2_a="\0", *str2_b="\n\0";
+    int height;
+    int byte_w_in, byte_w_out;
+    int xp, yp;
+    float sin_angle, cos_angle;
+    int it, jt;
+    float di, dj;
+    int ic=0;
+    float xl, xr, xinc;
+    int byte_out;
+    int dir, asc, desc;
+    XCharStruct overall;
+    int old_cols_in=0, old_rows_in=0;
+    
+    /* allocate memory */
+    item=(RotatedTextItem *)malloc((unsigned)sizeof(RotatedTextItem));
+    if(!item)
+       return NULL;
+       
+    /* count number of sections in string */
+    item->nl=1;
+    if(align!=NONE)
+       for(i=0; i<strlen(text)-1; i++)
+           if(text[i]=='\n')
+               item->nl++;
+    
+    /* ignore newline characters if not doing alignment */
+    if(align==NONE)
+       str2=str2_a;
+    else
+       str2=str2_b;
+    
+    /* find width of longest section */
+    str1=my_strdup(text);
+    if(str1==NULL)
+       return NULL;
+    
+    str3=my_strtok(str1, str2);
+
+    XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+                &overall);
+    
+    item->max_width=overall.rbearing;
+    
+    /* loop through each section */
+    do {
+       str3=my_strtok((char *)NULL, str2);
+
+       if(str3!=NULL) {
+           XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+                        &overall);
+
+           if(overall.rbearing>item->max_width)
+               item->max_width=overall.rbearing;
+       }
+    }
+    while(str3!=NULL);
+    
+    free(str1);
+    
+    /* overall font height */
+    height=font->ascent+font->descent;
+    
+    /* dimensions horizontal text will have */
+    item->cols_in=item->max_width;
+    item->rows_in=item->nl*height;
+    
+    /* bitmap for drawing on */
+    canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+                        item->cols_in, item->rows_in, 1);
+    
+    /* create a GC for the bitmap */
+    font_gc=XCreateGC(dpy, canvas, NULL, 0);
+    XSetBackground(dpy, font_gc, 0);
+    XSetFont(dpy, font_gc, font->fid);
+    
+    /* make sure the bitmap is blank */
+    XSetForeground(dpy, font_gc, 0);
+    XFillRectangle(dpy, canvas, font_gc, 0, 0, 
+                  item->cols_in+1, item->rows_in+1);
+    XSetForeground(dpy, font_gc, 1);
+    
+    /* pre-calculate sin and cos */
+    sin_angle=sin(angle);
+    cos_angle=cos(angle);
+    
+    /* text background will be drawn using XFillPolygon */
+    item->corners_x=
+       (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
+    if(!item->corners_x)
+       return NULL;
+    
+    item->corners_y=
+       (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
+    if(!item->corners_y)
+       return NULL;
+    
+    /* draw text horizontally */
+    
+    /* start at top of bitmap */
+    yp=font->ascent;
+    
+    str1=my_strdup(text);
+    if(str1==NULL)
+       return NULL;
+    
+    str3=my_strtok(str1, str2);
+    
+    /* loop through each section in the string */
+    do {
+       XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+               &overall);
+
+       /* where to draw section in x ? */
+       if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+           xp=0;
+       else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+           xp=(item->max_width-overall.rbearing)/2;
+       else
+            xp=item->max_width-overall.rbearing;
+
+       /* draw string onto bitmap */
+       XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3));
+       
+       /* keep a note of corner positions of this string */
+       item->corners_x[ic]=((float)xp-(float)item->cols_in/2)*style.magnify;
+       item->corners_y[ic]=((float)(yp-font->ascent)-(float)item->rows_in/2)
+           *style.magnify;
+       item->corners_x[ic+1]=item->corners_x[ic];
+       item->corners_y[ic+1]=item->corners_y[ic]+(float)height*style.magnify;
+       item->corners_x[item->nl*4-1-ic]=item->corners_x[ic]+
+           (float)overall.rbearing*style.magnify;
+       item->corners_y[item->nl*4-1-ic]=item->corners_y[ic];
+       item->corners_x[item->nl*4-2-ic]=
+           item->corners_x[item->nl*4-1-ic];
+       item->corners_y[item->nl*4-2-ic]=item->corners_y[ic+1];
+       
+       ic+=2;
+       
+       /* move to next line */
+       yp+=height;
+       
+       str3=my_strtok((char *)NULL, str2);
+    }
+    while(str3!=NULL);
+    
+    free(str1);
+    
+    /* create image to hold horizontal text */
+    I_in=MakeXImage(dpy, item->cols_in, item->rows_in);
+    if(I_in==NULL)
+       return NULL;
+    
+    /* extract horizontal text */
+    XGetSubImage(dpy, canvas, 0, 0, item->cols_in, item->rows_in,
+                1, XYPixmap, I_in, 0, 0);
+    I_in->format=XYBitmap;
+    
+    /* magnify horizontal text */
+    if(style.magnify!=1.) {
+       I_in=XRotMagnifyImage(dpy, I_in);
+
+       old_cols_in=item->cols_in;
+       old_rows_in=item->rows_in;
+       item->cols_in=(float)item->cols_in*style.magnify;
+       item->rows_in=(float)item->rows_in*style.magnify;
+    }
+
+    /* how big will rotated text be ? */
+    item->cols_out=fabs((float)item->rows_in*sin_angle) +
+       fabs((float)item->cols_in*cos_angle) +0.99999 +2;
+
+    item->rows_out=fabs((float)item->rows_in*cos_angle) +
+       fabs((float)item->cols_in*sin_angle) +0.99999 +2;
+
+    if(item->cols_out%2==0)
+       item->cols_out++;
+    
+    if(item->rows_out%2==0)
+       item->rows_out++;
+    
+    /* create image to hold rotated text */
+    item->ximage=MakeXImage(dpy, item->cols_out, item->rows_out);
+    if(item->ximage==NULL)
+       return NULL;
+    
+    byte_w_in=(item->cols_in-1)/8+1;
+    byte_w_out=(item->cols_out-1)/8+1;
+    
+    /* we try to make this bit as fast as possible - which is why it looks
+       a bit over-the-top */
+    
+    /* vertical distance from centre */
+    dj=0.5-(float)item->rows_out/2;
+
+    /* where abouts does text actually lie in rotated image? */
+    if(angle==0 || angle==M_PI/2 || 
+       angle==M_PI || angle==3*M_PI/2) {
+       xl=0;
+       xr=(float)item->cols_out;
+       xinc=0;
+    }
+    else if(angle<M_PI) {
+       xl=(float)item->cols_out/2+
+           (dj-(float)item->rows_in/(2*cos_angle))/
+               tan(angle)-2;
+       xr=(float)item->cols_out/2+
+           (dj+(float)item->rows_in/(2*cos_angle))/
+               tan(angle)+2;
+       xinc=1./tan(angle);
+    }
+    else {
+       xl=(float)item->cols_out/2+
+           (dj+(float)item->rows_in/(2*cos_angle))/
+               tan(angle)-2;
+       xr=(float)item->cols_out/2+
+           (dj-(float)item->rows_in/(2*cos_angle))/
+               tan(angle)+2;
+       
+       xinc=1./tan(angle);
+    }
+
+    /* loop through all relevent bits in rotated image */
+    for(j=0; j<item->rows_out; j++) {
+       
+       /* no point re-calculating these every pass */
+       di=(float)((xl<0)?0:(int)xl)+0.5-(float)item->cols_out/2;
+       byte_out=(item->rows_out-j-1)*byte_w_out;
+       
+       /* loop through meaningful columns */
+       for(i=((xl<0)?0:(int)xl); 
+           i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++) {
+           
+           /* rotate coordinates */
+           it=(float)item->cols_in/2 + ( di*cos_angle + dj*sin_angle);
+           jt=(float)item->rows_in/2 - (-di*sin_angle + dj*cos_angle);
+           
+            /* set pixel if required */
+            if(it>=0 && it<item->cols_in && jt>=0 && jt<item->rows_in)
+                if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
+                    item->ximage->data[byte_out+i/8]|=128>>i%8;
+           
+           di+=1;
+       }
+       dj+=1;
+       xl+=xinc;
+       xr+=xinc;
+    }
+    XDestroyImage(I_in);
+    
+    if(style.magnify!=1.) {
+       item->cols_in=old_cols_in;
+       item->rows_in=old_rows_in;
+    }
+
+
+#ifdef CACHE_BITMAPS
+
+    /* create a bitmap to hold rotated text */
+    item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
+                              item->cols_out, item->rows_out, 1);
+    
+    /* make the text bitmap from XImage */
+    XPutImage(dpy, item->bitmap, font_gc, item->ximage, 0, 0, 0, 0,
+             item->cols_out, item->rows_out);
+
+    XDestroyImage(item->ximage);
+
+#endif /*CACHE_BITMAPS*/
+
+    XFreeGC(dpy, font_gc);
+    XFreePixmap(dpy, canvas);
+
+    return item;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  Adds a text item to the end of the cache, removing as many items      */
+/*      from the front as required to keep cache size below limit         */
+/**************************************************************************/
+
+static void XRotAddToLinkedList(Display *dpy, RotatedTextItem *item)
+{
+    
+    static long int current_size=0;
+    static RotatedTextItem *last=NULL;
+    RotatedTextItem *i1=first_text_item, *i2=NULL;
+
+#ifdef CACHE_BITMAPS
+
+    /* I don't know how much memory a pixmap takes in the server -
+           probably this + a bit more we can't account for */
+
+    item->size=((item->cols_out-1)/8+1)*item->rows_out;
+
+#else
+
+    /* this is pretty much the size of a RotatedTextItem */
+
+    item->size=((item->cols_out-1)/8+1)*item->rows_out +
+       sizeof(XImage) + strlen(item->text) + 
+           item->nl*8*sizeof(float) + sizeof(RotatedTextItem);
+
+    if(item->font_name!=NULL)
+       item->size+=strlen(item->font_name);
+    else
+       item->size+=sizeof(Font);
+
+#endif /*CACHE_BITMAPS */
+
+#ifdef DEBUG
+    /* count number of items in cache, for debugging */
+    {
+       int i=0;
+
+       while(i1) {
+           i++;
+           i1=i1->next;
+       }
+       DEBUG_PRINT2("Cache has %d items.\n", i);
+       i1=first_text_item;
+    }
+#endif
+
+    DEBUG_PRINT4("current cache size=%ld, new item=%ld, limit=%ld\n",
+                current_size, item->size, CACHE_SIZE_LIMIT*1024);
+
+    /* if this item is bigger than whole cache, forget it */
+    if(item->size>CACHE_SIZE_LIMIT*1024) {
+       DEBUG_PRINT1("Too big to cache\n\n");
+       item->cached=0;
+       return;
+    }
+
+    /* remove elements from cache as needed */
+    while(i1 && current_size+item->size>CACHE_SIZE_LIMIT*1024) {
+
+       DEBUG_PRINT2("Removed %d bytes\n", i1->size);
+
+       if(i1->font_name!=NULL)
+           DEBUG_PRINT5("  (`%s'\n   %s\n   angle=%f align=%d)\n",
+                        i1->text, i1->font_name, i1->angle, i1->align);
+
+#ifdef CACHE_FID
+       if(i1->font_name==NULL)
+           DEBUG_PRINT5("  (`%s'\n  FID=%ld\n   angle=%f align=%d)\n",
+                         i1->text, i1->fid, i1->angle, i1->align);
+#endif /*CACHE_FID*/
+
+       current_size-=i1->size;
+
+       i2=i1->next;
+
+       /* free resources used by the unlucky item */
+       XRotFreeTextItem(dpy, i1);
+
+       /* remove it from linked list */
+       first_text_item=i2;
+       i1=i2;
+    }
+
+    /* add new item to end of linked list */
+    if(first_text_item==NULL) {
+       item->next=NULL;
+       first_text_item=item;
+       last=item;
+    }
+    else {
+       item->next=NULL;
+       last->next=item;
+       last=item;
+    }
+
+    /* new cache size */
+    current_size+=item->size;
+
+    item->cached=1;
+
+    DEBUG_PRINT1("Added item to cache.\n");
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/*  Free the resources used by a text item                                */
+/**************************************************************************/
+
+static void XRotFreeTextItem(Display *dpy, RotatedTextItem *item)
+{
+    free(item->text);
+
+    if(item->font_name!=NULL)
+       free(item->font_name);
+
+    free((char *)item->corners_x);
+    free((char *)item->corners_y);
+
+#ifdef CACHE_BITMAPS
+    XFreePixmap(dpy, item->bitmap);
+#else
+    XDestroyImage(item->ximage);
+#endif /* CACHE_BITMAPS */
+
+    free((char *)item);
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Magnify an XImage using bilinear interpolation                         */
+/**************************************************************************/
+
+static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage)
+{
+    int i, j;
+    float x, y;
+    float u,t;
+    XImage *I_out;
+    int cols_in, rows_in;
+    int cols_out, rows_out;
+    register int i2, j2;
+    float z1, z2, z3, z4;
+    int byte_width_in, byte_width_out;
+    float mag_inv;
+
+    /* size of input image */
+    cols_in=ximage->width;
+    rows_in=ximage->height;
+
+    /* size of final image */
+    cols_out=(float)cols_in*style.magnify;
+    rows_out=(float)rows_in*style.magnify;
+
+    /* this will hold final image */
+    I_out=MakeXImage(dpy, cols_out, rows_out);
+    if(I_out==NULL)
+       return NULL;
+
+    /* width in bytes of input, output images */
+    byte_width_in=(cols_in-1)/8+1;
+    byte_width_out=(cols_out-1)/8+1;
+
+    /* for speed */
+    mag_inv=1./style.magnify;
+
+    y=0.;
+
+    /* loop over magnified image */
+    for(j2=0; j2<rows_out; j2++) {
+       x=0;
+       j=y;
+
+       for(i2=0; i2<cols_out; i2++) {
+           i=x;
+
+           /* bilinear interpolation - where are we on bitmap ? */
+           /* right edge */
+           if(i==cols_in-1 && j!=rows_in-1) {
+               t=0;
+               u=y-(float)j;
+
+               z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+               z2=z1;
+               z3=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
+               z4=z3;
+           }
+           /* top edge */
+           else if(i!=cols_in-1 && j==rows_in-1) {
+               t=x-(float)i;
+               u=0;
+
+               z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+               z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
+               z3=z2;
+               z4=z1;
+           }
+           /* top right corner */
+           else if(i==cols_in-1 && j==rows_in-1) {
+               u=0;
+               t=0;
+
+               z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+               z2=z1;
+               z3=z1;
+               z4=z1;
+           }
+           /* somewhere `safe' */
+           else {
+               t=x-(float)i;
+               u=y-(float)j;
+
+               z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
+               z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
+               z3=(ximage->data[(j+1)*byte_width_in+(i+1)/8] &
+                   128>>((i+1)%8))>0;
+               z4=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
+           }
+
+           /* if interpolated value is greater than 0.5, set bit */
+           if(((1-t)*(1-u)*z1 + t*(1-u)*z2 + t*u*z3 + (1-t)*u*z4)>0.5)
+               I_out->data[j2*byte_width_out+i2/8]|=128>>i2%8;
+
+           x+=mag_inv;
+       }
+       y+=mag_inv;
+    }
+    
+    /* destroy original */
+    XDestroyImage(ximage);
+
+    /* return big image */
+    return I_out;
+}
+
+
+
+/* ---------------------------------------------------------------------- */
+
+
+/**************************************************************************/
+/* Calculate the bounding box some text will have when painted            */
+/**************************************************************************/
+static
+XPoint *XRotTextExtents(Display *dpy, XFontStruct *font, float angle, int x, int y, char *text, int align)
+{
+    register int i;
+    char *str1, *str2, *str3;
+    char *str2_a="\0", *str2_b="\n\0";
+    int height;
+    float sin_angle, cos_angle;
+    int nl, max_width;
+    int cols_in, rows_in;
+    float hot_x, hot_y;
+    XPoint *xp_in, *xp_out;
+    int dir, asc, desc;
+    XCharStruct overall;
+    
+    /* manipulate angle to 0<=angle<360 degrees */
+    while(angle<0)
+        angle+=360;
+    
+    while(angle>360)
+        angle-=360;
+    
+    angle*=M_PI/180;
+    
+    /* count number of sections in string */
+    nl=1;
+    if(align!=NONE)
+       for(i=0; i<strlen(text)-1; i++)
+           if(text[i]=='\n')
+               nl++;
+    
+    /* ignore newline characters if not doing alignment */
+    if(align==NONE)
+       str2=str2_a;
+    else
+       str2=str2_b;
+    
+    /* find width of longest section */
+    str1=my_strdup(text);
+    if(str1==NULL)
+       return NULL;
+    
+    str3=my_strtok(str1, str2);
+
+    XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+                &overall);
+
+    max_width=overall.rbearing;
+    
+    /* loop through each section */
+    do {
+       str3=my_strtok((char *)NULL, str2);
+
+       if(str3!=NULL) {
+           XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
+                        &overall);
+
+           if(overall.rbearing>max_width)
+               max_width=overall.rbearing;
+       }
+    }
+    while(str3!=NULL);
+    
+    free(str1);
+    
+    /* overall font height */
+    height=font->ascent+font->descent;
+    
+    /* dimensions horizontal text will have */
+    cols_in=max_width;
+    rows_in=nl*height;
+    
+    /* pre-calculate sin and cos */
+    sin_angle=sin(angle);
+    cos_angle=cos(angle);
+    
+    /* y position */
+    if(align==TLEFT || align==TCENTRE || align==TRIGHT)
+        hot_y=(float)rows_in/2*style.magnify;
+    else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
+       hot_y=0;
+    else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
+       hot_y = -(float)rows_in/2*style.magnify;
+    else
+       hot_y = -((float)rows_in/2-(float)font->descent)*style.magnify;
+    
+    /* x position */
+    if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
+       hot_x = -(float)max_width/2*style.magnify;
+    else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
+       hot_x=0;
+    else
+        hot_x=(float)max_width/2*style.magnify;
+    
+    /* reserve space for XPoints */
+    xp_in=(XPoint *)malloc((unsigned)(5*sizeof(XPoint)));
+    if(!xp_in)
+       return NULL;
+
+    xp_out=(XPoint *)malloc((unsigned)(5*sizeof(XPoint)));
+    if(!xp_out)
+       return NULL;
+
+    /* bounding box when horizontal, relative to bitmap centre */
+    xp_in[0].x = -(float)cols_in*style.magnify/2-style.bbx_pad;
+    xp_in[0].y= (float)rows_in*style.magnify/2+style.bbx_pad;
+    xp_in[1].x= (float)cols_in*style.magnify/2+style.bbx_pad;
+    xp_in[1].y= (float)rows_in*style.magnify/2+style.bbx_pad;
+    xp_in[2].x= (float)cols_in*style.magnify/2+style.bbx_pad;
+    xp_in[2].y = -(float)rows_in*style.magnify/2-style.bbx_pad;
+    xp_in[3].x = -(float)cols_in*style.magnify/2-style.bbx_pad;
+    xp_in[3].y = -(float)rows_in*style.magnify/2-style.bbx_pad;
+    xp_in[4].x=xp_in[0].x;
+    xp_in[4].y=xp_in[0].y;
+       
+    /* rotate and translate bounding box */
+    for(i=0; i<5; i++) {
+       xp_out[i].x=(float)x + ( ((float)xp_in[i].x-hot_x)*cos_angle +
+                                ((float)xp_in[i].y+hot_y)*sin_angle);
+       xp_out[i].y=(float)y + (-((float)xp_in[i].x-hot_x)*sin_angle +
+                                ((float)xp_in[i].y+hot_y)*cos_angle);
+    }
+
+    free((char *)xp_in);
+
+    return xp_out;
+}
+
+
+\f
+/* ***********************************************************************
+ * Conversion routines for the X resource manager
+ * ***********************************************************************
+ */
+
+#if defined(__STDC__)
+static
+Boolean        strtocard(  Display *dsp,
+                   XrmValue *args,
+                   Cardinal *num_args,
+                   XrmValue *from,
+                   XrmValue *to,
+                   XtPointer *unused
+                   )
+#else
+static
+Boolean        strtocard(  dsp, args, num_args, from, to, unused )
+Display *dsp;
+XrmValue *args;
+Cardinal *num_args;
+XrmValue *from;
+XrmValue *to;
+XtPointer *unused;
+#endif
+{
+    static Cardinal temp;
+
+    if ( to->addr == NULL ) {
+       to->addr = (XtPointer) &temp;
+       to->size = sizeof(Cardinal);
+    }
+
+    *((Cardinal *) to->addr) = atoi( from->addr );
+    return True;
+}
+
+
+#define done_bert(type, value) \
+    do {\
+       if (to->addr != NULL) {\
+           if (to->size < sizeof(type)) {\
+               to->size = sizeof(type);\
+               return False;\
+           }\
+           *(type*)(to->addr) = (value);\
+        } else {\
+           static type static_val;\
+           static_val = (value);\
+           to->addr = (XtPointer)&static_val;\
+        }\
+        to->size = sizeof(type);\
+        return True;\
+    } while (0)
+static
+Boolean cvtStringToStringArray(Display *display, XrmValuePtr args, Cardinal *num_args, XrmValuePtr from, XrmValuePtr to, XtPointer *converter_data)
+{
+    String t, s;
+    StringArray a = NULL;
+    Cardinal i;
+    char delim;
+
+    if (*num_args != 0)
+       XtAppErrorMsg(XtDisplayToApplicationContext(display),
+                     "cvtStringToStringArray", "wrongParameters",
+                     "XtToolkitError",
+                     "String to StringArray conversion needs no arguments",
+                     (String*) NULL, (Cardinal*) NULL);
+
+    delim = ((String) from->addr)[0];
+    s = XtNewString((String) from->addr + 1);
+    i = 0;
+    while (s && *s) {
+       t = strchr(s, delim);
+        if (t) *t = '\0';
+       a = (StringArray) XtRealloc((String) a, (i + 1) * sizeof(*a));
+       a[i] = s;
+       i++;
+        s = t ? t + 1 : NULL;
+    }
+    a = (StringArray) XtRealloc((String) a, (i + 1) * sizeof(*a));
+    a[i] = NULL;
+    done_bert(StringArray, a);
+}
+
+\f
+/* ***********************************************************************
+ * A driver for the above in the flavor of the xt utilities module
+ * ***********************************************************************
+ */
+
+#define TABHT 25
+
+typedef struct tab_data {
+    Widget     form;
+    int                cur,
+               num_tabs;
+    void       (*activate_func)();
+} *TabData;
+
+
+#if defined(__STDC__)
+static void handle_click( Widget w, TabData td, XtPointer call_data )
+#else
+static void handle_click(w, td, call_data)
+    Widget w;
+    TabData td;
+    XtPointer call_data;
+#endif
+{
+    int tab = (int) call_data;
+
+    /* note that the tab is relative to the current tab.
+     * if tab is 0, the user clicked on the current one.
+     * there is nothing to do
+     */
+    if (tab == 0) return;
+    td->cur += tab;
+
+    /* Change tabs.  We must manually inform the UI which tab is current  */
+    XtVaSetValues( w,
+                  XtNlefttabs, td->cur,
+                  XtNrighttabs, td->num_tabs - td->cur - 1,
+                  NULL
+                  );
+
+    (*td->activate_func)( td->form, td->cur );
+}
+
+
+/*
+ * PUBLIC: Widget __vi_CreateTabbedFolder
+ * PUBLIC:     __P((String, Widget, String, int, void (*)(Widget, int)));
+ */
+#if defined(__STDC__)
+Widget __vi_CreateTabbedFolder( String name,
+                               Widget parent,
+                               String tab_labels,
+                               int num_tabs,
+                               void (*activate_func)()
+                               )
+#else
+Widget __vi_CreateTabbedFolder( name, parent, tab_labels, num_tabs, activate_func )
+String name;
+String tab_labels;
+Widget parent;
+int    num_tabs;
+void   (*activate_func)();
+#endif
+{
+    Widget     tabs;
+    TabData    td = (TabData) malloc( sizeof(struct tab_data) );
+    int                i;
+
+    XtAppSetTypeConverter(  XtDisplayToApplicationContext(XtDisplay(parent)),
+                           XtRString,
+                           XtRCardinal,
+                           strtocard,
+                           NULL,
+                           0,
+                           XtCacheNone,
+                           NULL
+                           );
+
+    /* init our internal structure */
+    td->cur            = 0;
+    td->num_tabs       = num_tabs;
+    td->activate_func  = activate_func;
+
+    /* tabs go on the top */
+    tabs = XtVaCreateManagedWidget( "tabs",
+                                    xmTabsWidgetClass,
+                                    parent,
+                                    XtNlefttabs,       0,
+                                    XtNrighttabs,      num_tabs-1,
+                                    XtNorientation,    XfwfUpTabs,
+                                    XmNtopAttachment,  XmATTACH_FORM,
+                                    XmNleftAttachment, XmATTACH_FORM,
+                                    XmNleftOffset,     TABHT/4,
+                                    XmNrightAttachment,XmATTACH_FORM,
+                                    XmNrightOffset,    TABHT/4,
+                                    XmNbottomAttachment,XmATTACH_OPPOSITE_FORM,
+                                    XmNbottomOffset,   -TABHT,
+                                    XtNlabels,         tab_labels,
+                                    XtVaTypedArg,      XtNlabels,
+                                                       XtRString,
+                                                       tab_labels,
+                                                       strlen(tab_labels) + 1,
+                                    NULL
+                                    );
+
+    /* add the callback */
+    XtAddCallback( tabs,
+                  XtNactivateCallback,
+                  (XtCallbackProc) handle_click,
+                  td
+                  );
+
+    /* another form to hold the controls */
+    td->form = XtVaCreateWidget( "form",
+                                xmFormWidgetClass,
+                                parent,
+                                XmNtopAttachment,      XmATTACH_WIDGET,
+                                XmNtopWidget,          tabs,
+                                XmNleftAttachment,     XmATTACH_FORM,
+                                XmNbottomAttachment,   XmATTACH_FORM,
+                                XmNrightAttachment,    XmATTACH_FORM,
+                                NULL
+                                );
+
+    /* done */
+    return td->form;
+}
diff --git a/dist/nvi/nvi2netbsd b/dist/nvi/nvi2netbsd
new file mode 100644 (file)
index 0000000..a5c6ff9
--- /dev/null
@@ -0,0 +1,147 @@
+#! /bin/sh
+#
+#      $NetBSD: nvi2netbsd,v 1.2 2008/05/20 17:05:40 aymeric Exp $
+#
+# Copyright (c) 2000 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# based on amd2netbsd,
+# itself based on bind2netbsd by Bernd Ernesti and changes by Simon Burge
+#
+# Rough instructions for importing new nvi release:
+#
+#      $ cd /some/where/temporary
+#      $ tar xpfz /new/nvi/release/tar/file
+#      $ sh /usr/src/dist/nvi/nvi2netbsd nvi-x.y.z `pwd`
+#      $ cd src/dist/nvi
+#      $ cvs import -m "Import nvi x.y.z" src/dist/nvi NVI nvi-x-y-z
+#      $ cd ../../../nvi/build.unix
+#      $ run ../dist/configure --with-db_type=db1 --enable-widechar
+#      ... to be continued
+#
+
+if [ $# -ne 2 ]; then echo "nvi2netbsd src dest"; exit 1; fi
+
+r="$1"
+d="$2"/src/dist/nvi
+
+case "$d" in
+       /*)
+               ;;
+       *)
+               d="`/bin/pwd`/$d"
+               ;;
+esac
+
+case "$r" in
+       /*)
+               ;;
+       *)
+               r="`/bin/pwd`/$r"
+               ;;
+esac
+
+echo preparing directory "$d"
+rm -rf "$d"
+mkdir -p "$d"
+
+### Copy the files and directories
+echo copying "$r" to "$d"
+cd "$r"
+pax -rw * "$d"
+
+echo removing unneeded directories and files
+
+### Remove unneeded files
+cd "$d"
+rm -f catalog/english.base             # we generate it
+rm -fr dist/autom4te.cache
+rm -f dist/tags
+rm -fr docs/html
+rm -f docs/*/*.ps docs/*/grohtml* docs/*/*.0 docs/*/*.txt
+rm -f common/options_def.h             # must be removed: we generate it
+
+cd catalog
+for f in *.base; do
+       f2="`echo "$f" | sed -e 's/\.base$//'`"
+       rm -f "$f2" "$f2".check
+done
+
+### Remove the $'s around RCS tags
+find "$d" -type f -print | \
+    xargs egrep -l '\$(Created|Date|Header|Id|Revision)' | while read f; do
+       sed -e 's/\$\(Id[^$]*\) \$/\1/' \
+           -e 's/\$\(Created[^$]*\) \$/\1/' \
+           -e 's/\$\(Date[^$]*\) \$/\1/' \
+           -e 's/\$\(Header[^$]*\) \$/\1/' \
+           -e 's/\$\(Revision[^$]*\) \$/\1/' \
+           < "$f" > /tmp/nvi1f$$ && mv /tmp/nvi1f$$ "$f" && \
+       echo removed \$RCS tag from "$f"
+done
+
+### Add our NetBSD RCS Id
+find "$d" -type f -name '*.[ch]' -print | while read c; do
+       sed 1q < "$c" | grep -q '\$NetBSD' || (
+echo "/*       \$NetBSD\$ */" >/tmp/nvi3n$$
+echo "" >>/tmp/nvi3n$$
+cat "$c"  >> /tmp/nvi3n$$
+mv /tmp/nvi3n$$ $c && echo added NetBSD RCS tag to "$c"
+       )
+done
+
+find "$d" -type f -name '*.[0-9]' -print | while read m; do
+       sed 1q < "$m" | grep -q '\$NetBSD' || (
+echo ".\\\"    \$NetBSD\$" >/tmp/nvi2m$$
+echo ".\\\"" >>/tmp/nvi2m$$
+cat "$m" >> /tmp/nvi2m$$
+mv /tmp/nvi2m$$ "$m" && echo added NetBSD RCS tag to "$m"
+       )
+done
+
+find "$d" -type f -name '*.texi' -print | while read t; do
+        sed "2 s/^/@c \$NetBSD\$\\
+/" < "$t" > /tmp/nvi4t$$
+       mv /tmp/nvi4t$$ "$t" && echo added NetBSD RCS tag to "$t"
+done
+
+echo done
+
+### Clean up any CVS directories that might be around.
+echo "cleaning up CVS residue."
+(
+       cd "$d"
+       find . -type d -name "CVS" -print | xargs rm -r
+)
+echo done
+
+### Fixing file and directory permissions.
+echo "Fixing file/directory permissions."
+(
+       cd "$d"
+       find . -type f -print | xargs chmod u+rw,go+r
+       find . -type d -print | xargs chmod u+rwx,go+rx
+)
+echo done
+
+exit 0
diff --git a/dist/nvi/perl_api/VI.pod b/dist/nvi/perl_api/VI.pod
new file mode 100644 (file)
index 0000000..f73a936
--- /dev/null
@@ -0,0 +1,281 @@
+=head1 NAME
+
+VI - VI module within perl embedded nvi
+
+=head1 SYNOPSIS
+
+    sub wc {
+      my $words;
+      $i = $VI::StartLine;
+      while ($i <= $VI::StopLine) {
+       $_ = $curscr->GetLine($i++);
+        $words+=split;
+      }
+      $curscr->Msg("$words words");
+    }
+
+=head1 DESCRIPTION
+
+This pseudo module is available to perl programs run from within nvi and
+provides access to the files being edited and some internal data.
+
+Beware that you should not use this module from within a C<perldo> or
+from within an C<END> block or a C<DESTROY> method.
+
+=head2 Variables
+
+These are set by nvi before starting each perl command.
+
+=over 8
+
+=item * $curscr
+
+Object that represents the current screen.
+It can be used as the ScreenId parameter of the functions below,
+or you can use object oriented syntax.
+
+       # the following two are equivalent
+       $curscr->DelLine(57);
+       VI::DelLine($curscr, 57);
+
+=item * $StartLine
+
+Line number of the first line of the selected range or of the file if no
+range was specified.
+
+=item * $StopLine
+
+Line number of the last line of the selected range or of the file if no
+range was specified.
+
+=back
+
+=head2 Functions
+
+=over 8
+
+=item * AppendLine
+
+    VI::AppendLine(screenId,lineNumber,text);
+
+Append the string text after the line in lineNumber.
+
+=item * DelLine
+
+    VI::DelLine(screenId,lineNum);
+
+Delete lineNum.
+
+=item * EndScreen
+
+VI::EndScreen(screenId);
+
+End a screen.
+
+=item * FindScreen
+
+    VI::FindScreen(file);
+
+Return the screen id associated with file name.
+
+=item * GetCursor
+
+    ($line, $column) = VI::GetCursor(screenId);
+
+Return the current cursor position as a list with two elements.
+
+=item * GetLine
+
+    VI::GetLine(screenId,lineNumber);
+
+Return lineNumber.
+
+=item * GetMark
+
+    ($line, $column) = VI::GetMark(screenId,mark);
+
+Return the mark's cursor position as a list with two elements.
+
+=item * GetOpt
+
+    VI::GetOpt(screenId,option);
+
+Return the value of an option.
+
+=item * InsertLine
+
+    VI::InsertLine(screenId,lineNumber,text);
+
+Insert the string text before the line in lineNumber.
+
+=item * LastLine
+
+    VI::LastLine(screenId);
+
+Return the last line in the screen.
+
+=item * MapKey
+
+    VI::MapKey(screenId,key,perlproc);
+
+Associate a key with a perl procedure.
+
+=item * Msg
+
+    VI::Msg(screenId,text);
+
+Set the message line to text.
+
+=item * NewScreen
+
+    VI::NewScreen(screenId);
+    VI::NewScreen(screenId,file);
+
+Create a new screen.  If a filename is specified then the screen is
+opened with that file.
+
+=item * Run
+
+    VI::Run(screenId,cmd);
+
+Run the ex command cmd.
+
+=item * SetCursor
+
+    VI::SetCursor(screenId,line,column);
+
+Set the cursor to the line and column numbers supplied.
+
+=item * SetLine
+
+    VI::SetLine(screenId,lineNumber,text);
+
+Set lineNumber to the text supplied.
+
+=item * SetMark
+
+    VI::SetMark(screenId,mark,line,column);
+
+Set the mark to the line and column numbers supplied.
+
+=item * SetOpt
+
+    VI::SetOpt(screenId,command);
+
+Set an option.
+
+=item * SwitchScreen
+
+    VI::SwitchScreen(screenId,screenId);
+
+Change the current focus to screen.
+
+=item * TagQ
+
+    $screen->TagQ("tag identification string")
+
+Creates a new tag queue object associated to $screen
+to which "tags" can be added.
+See further about methods you can use on tag queues.
+
+=item * UnmapKey
+
+    VI::UnmmapKey(screenId,key);
+
+Unmap a key.
+
+=item * Warn
+
+This is the default warning handler.
+It adds any warnings to the error string.
+
+=item * Opt
+
+    $screen->Opt;
+
+Returns a tied hash representing the options of the screen.
+Note that you can only retrieve and set hash elements.
+
+=item * Map
+
+    $screen->Map;
+
+Returns a tied hash representing the mappings of the screen.
+Note that you can only retrieve, set and delete hash elements.
+
+=item * Mark
+
+    $screen->Mark;
+
+Returns a tied hash representing the marks of the screen.
+
+=item * Line
+
+    $screen->Line;
+
+Returns a tied array representing the lines of the screen.
+
+=back
+
+=head2 Tag queue methods
+
+=item * Add
+
+    $tagq->Add($filename, $searchstring, $msg)
+
+Adds a tag to the tag queue. 
+The $searchstring argument is (line)number or
+a string representing a regular expression.
+
+=item * Push
+
+    $tagq->Push()
+
+Pushes the tag queue onto its associated screen.
+The result of the operation is as if the user had enter the
+tag command and nvi had found the locations that were added
+using the Add method.
+
+For an example, see the make.pl script.
+
+=back
+
+=head1 EXAMPLES
+
+    sub showmarks {
+      my ($mark, $all);
+      for $mark ('a' .. 'z') {
+        eval {VI::GetMark($VI::ScreenId, $mark)};
+        $all .= $mark unless ($@);
+      }
+      VI::Msg($VI::ScreenId,"Set marks: $all");
+    }
+
+    sub forall {
+      my ($code) = shift;
+      my ($i) = $VI::StartLine-1;
+      while (++$i <= $VI::StopLine) {
+        $_ = VI::GetLine($VI::ScreenId, $i);
+        VI::SetLine($VI::ScreenId, $i, $_) if(&$code);
+      }
+    }
+
+Now you can do
+
+    :perl forall sub{s/perlre/substitution/}
+
+Although you'll probably use
+
+    :perldo s/perlre/substitution/
+
+instead.
+
+See L<perlre> for perl regular expressions.
+
+=head1 SEE ALSO
+
+L<nviperl>
+
+=head1 AUTHOR
+
+Sven Verdoolaege <skimo@kotnet.org>
diff --git a/dist/nvi/perl_api/extern.h b/dist/nvi/perl_api/extern.h
new file mode 100644 (file)
index 0000000..42223c0
--- /dev/null
@@ -0,0 +1,12 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:34 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+#ifdef USE_SFIO
+Sfdisc_t* sfdcnewnvi __P((SCR*));
+#endif
+int perl_end __P((GS *));
+int perl_init __P((SCR *));
+int perl_screen_end __P((SCR*));
+int perl_setenv __P((SCR* sp, const char *name, const char *value));
+int perl_ex_perl __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
+int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
diff --git a/dist/nvi/perl_api/nviperl.pod b/dist/nvi/perl_api/nviperl.pod
new file mode 100644 (file)
index 0000000..432fbe9
--- /dev/null
@@ -0,0 +1,43 @@
+=head1 NAME
+
+nviperl - nvi with embedded perl
+
+=head1 SYNOPSIS
+
+    :perl require 'wc.pl'
+    :perl wc
+    :,$perldo $_=reverse($_)
+
+=head1 DESCRIPTION
+
+nvi with embedded perl allows you to run perl commands from within nvi.
+Two additional commands are made available when you enable the perl
+interpreter:
+
+=over 8
+
+=item * perl cmd
+
+The perl command passes the specified commands to the perl interpreter.
+The C<$VI::ScreenId>, C<$VI::StartLine> and C<$VI::StopLine> are set.
+To find out how to maniplulate the nvi screens, see L<VI>.
+
+=item * perldo cmd
+
+The perldo command runs the specified commands on each line of the range
+(every line of the file if no range specified).  Before running the
+command the line is copied into $_.  If the command returns a true value
+the line is replaced by the new value of $_.
+
+The perldo commando does B<not> set the C<VI> variables.  (If you think
+this is a bad idea, tell me.)
+
+=back
+
+=head1 SEE ALSO
+
+L<VI>
+
+=head1 AUTHOR
+
+Sven Verdoolaege <skimo@kotnet.org>
diff --git a/dist/nvi/perl_api/perl.xs b/dist/nvi/perl_api/perl.xs
new file mode 100644 (file)
index 0000000..9c8bbd2
--- /dev/null
@@ -0,0 +1,1594 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1995
+ *     George V. Neville-Neil. All rights reserved.
+ * Copyright (c) 1996-2001
+ *     Sven Verdoolaege. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#undef VI
+
+#ifndef lint
+static const char sccsid[] = "Id: perl.xs,v 8.46 2001/08/28 11:33:42 skimo Exp (Berkeley) Date: 2001/08/28 11:33:42";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+/* perl redefines them
+ * avoid warnings
+ */
+#undef USE_DYNAMIC_LOADING
+#undef DEBUG
+#undef PACKAGE
+#undef ARGS
+#define ARGS ARGS
+
+#include "config.h"
+
+#include "../common/common.h"
+#include "../perl_api/extern.h"
+
+#ifndef DEFSV
+#define DEFSV GvSV(defgv)
+#endif
+#ifndef ERRSV
+#define ERRSV GvSV(errgv)
+#endif
+#ifndef dTHX
+#define dTHXs
+#else
+#define dTHXs dTHX;
+#endif
+
+static void msghandler __P((SCR *, mtype_t, char *, size_t));
+
+typedef struct _perl_data {
+       PerlInterpreter*        interp;
+       SV      *svcurscr, *svstart, *svstop, *svid;
+       CONVWIN  cw;
+       char    *errmsg;
+} perl_data_t;
+
+#define PERLP(sp)   ((perl_data_t *)sp->wp->perl_private)
+
+#define CHAR2INTP(sp,n,nlen,w,wlen)                                        \
+    CHAR2INT5(sp,((perl_data_t *)sp->wp->perl_private)->cw,n,nlen,w,wlen)
+
+/*
+ * INITMESSAGE --
+ *     Macros to point messages at the Perl message handler.
+ */
+#define        INITMESSAGE(sp)                                                 \
+       scr_msg = sp->wp->scr_msg;                                      \
+       sp->wp->scr_msg = msghandler;
+#define        ENDMESSAGE(sp)                                                  \
+       sp->wp->scr_msg = scr_msg;                                      \
+       if (rval) croak(PERLP(sp)->errmsg);
+
+void xs_init __P((pTHXo));
+
+/*
+ * perl_end --
+ *     Clean up perl interpreter
+ *
+ * PUBLIC: int perl_end __P((GS *));
+ */
+int
+perl_end(gp)
+       GS *gp;
+{
+       /*
+        * Call perl_run and perl_destuct to call END blocks and DESTROY
+        * methods.
+        */
+       if (gp->perl_interp) {
+               perl_run(gp->perl_interp);
+               perl_destruct(gp->perl_interp);
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+               perl_free(gp->perl_interp);
+#endif
+               /* XXX rather make sure only one thread calls perl_end */
+               gp->perl_interp = 0;
+       }
+}
+
+/*
+ * perl_eval
+ *     Evaluate a string
+ *     We don't use mortal SVs because no one will clean up after us
+ */
+static void 
+perl_eval(string)
+       char *string;
+{
+       dTHXs
+
+       SV* sv = newSVpv(string, 0);
+
+       /* G_KEEPERR to catch syntax error; better way ? */
+       sv_setpv(ERRSV,"");
+       perl_eval_sv(sv, G_DISCARD | G_NOARGS | G_KEEPERR);
+       SvREFCNT_dec(sv);
+}
+
+/*
+ * perl_init --
+ *     Create the perl commands used by nvi.
+ *
+ * PUBLIC: int perl_init __P((SCR *));
+ */
+int
+perl_init(scrp)
+       SCR *scrp;
+{
+       AV * av;
+       GS *gp;
+       WIN *wp;
+       char *bootargs[] = { "VI", NULL };
+#ifndef USE_SFIO
+       SV *svcurscr;
+#endif
+       perl_data_t *pp;
+
+       static char *args[] = { "", "-e", "" };
+       size_t length;
+       char *file = __FILE__;
+
+       gp = scrp->gp;
+       wp = scrp->wp;
+
+       if (gp->perl_interp == NULL) {
+       gp->perl_interp = perl_alloc();
+       perl_construct(gp->perl_interp);
+       if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
+               perl_destruct(gp->perl_interp);
+               perl_free(gp->perl_interp);
+               gp->perl_interp = NULL;
+               return 1;
+       }
+       {
+       dTHXs
+
+        perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
+       perl_eval("$SIG{__WARN__}='VI::Warn'");
+
+       av_unshift(av = GvAVn(PL_incgv), 1);
+       av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
+                               sizeof(_PATH_PERLSCRIPTS)-1));
+
+#ifdef USE_SFIO
+       sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
+       sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
+#else
+       svcurscr = perl_get_sv("curscr", TRUE);
+       sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
+                       'q', Nullch, 0);
+       sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
+                       'q', Nullch, 0);
+#endif /* USE_SFIO */
+       }
+       }
+       MALLOC(scrp, pp, perl_data_t *, sizeof(perl_data_t));
+       wp->perl_private = pp;
+       memset(&pp->cw, 0, sizeof(pp->cw));
+#ifdef USE_ITHREADS
+       pp->interp = perl_clone(gp->perl_interp, 0);
+        if (1) { /* hack for bug fixed in perl-current (5.6.1) */
+            dTHXa(pp->interp);
+            if (PL_scopestack_ix == 0) {
+                ENTER;
+            }
+        }
+#else
+       pp->interp = gp->perl_interp;
+#endif
+       pp->errmsg = 0;
+       {
+               dTHXs
+
+               SvREADONLY_on(pp->svcurscr = perl_get_sv("curscr", TRUE));
+               SvREADONLY_on(pp->svstart = perl_get_sv("VI::StartLine", TRUE));
+               SvREADONLY_on(pp->svstop = perl_get_sv("VI::StopLine", TRUE));
+               SvREADONLY_on(pp->svid = perl_get_sv("VI::ScreenId", TRUE));
+       }
+       return (0);
+}
+
+/*
+ * perl_screen_end
+ *     Remove all refences to the screen to be destroyed
+ *
+ * PUBLIC: int perl_screen_end __P((SCR*));
+ */
+int
+perl_screen_end(scrp)
+       SCR *scrp;
+{
+       dTHXs
+
+       if (scrp->perl_private) {
+               sv_setiv((SV*) scrp->perl_private, 0);
+       }
+       return 0;
+}
+
+static void
+my_sighandler(i)
+       int i;
+{
+       croak("Perl command interrupted by SIGINT");
+}
+
+/* Create a new reference to an SV pointing to the SCR structure
+ * The perl_private part of the SCR structure points to the SV,
+ * so there can only be one such SV for a particular SCR structure.
+ * When the last reference has gone (DESTROY is called),
+ * perl_private is reset; When the screen goes away before
+ * all references are gone, the value of the SV is reset;
+ * any subsequent use of any of those reference will produce
+ * a warning. (see typemap)
+ */
+static SV *
+newVIrv(rv, screen)
+       SV *rv;
+       SCR *screen;
+{
+       dTHXs
+
+       if (!screen) return sv_setsv(rv, &PL_sv_undef), rv;
+       sv_upgrade(rv, SVt_RV);
+       if (!screen->perl_private) {
+               screen->perl_private = newSV(0);
+               sv_setiv(screen->perl_private, (IV) screen);
+       } 
+       else SvREFCNT_inc(screen->perl_private);
+       SvRV(rv) = screen->perl_private;
+       SvROK_on(rv);
+       return sv_bless(rv, gv_stashpv("VI", TRUE));
+}
+
+/*
+ * perl_setenv
+ *     Use perl's setenv if perl interpreter has been started.
+ *     Perl uses its own setenv and gets confused if we change
+ *     the environment after it has started.
+ *
+ * PUBLIC: int perl_setenv __P((SCR* sp, const char *name, const char *value));
+ */
+int
+perl_setenv(SCR* scrp, const char *name, const char *value)
+{
+       if (scrp->wp->perl_private == NULL) {
+           if (value == NULL)
+               unsetenv(name);
+           else
+               setenv(name, value, 1);
+       } else
+           my_setenv(name, value);
+}
+
+
+/* 
+ * perl_ex_perl -- :[line [,line]] perl [command]
+ *     Run a command through the perl interpreter.
+ *
+ * PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
+ */
+int 
+perl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
+       SCR *scrp;
+       CHAR_T *cmdp;
+       size_t cmdlen;
+       db_recno_t f_lno, t_lno;
+{
+       WIN *wp;
+       size_t length;
+       size_t len;
+       char *err;
+       char *np;
+       size_t nlen;
+       Signal_t (*istat)();
+       perl_data_t *pp;
+
+       /* Initialize the interpreter. */
+       if (scrp->wp->perl_private == NULL && perl_init(scrp))
+                       return (1);
+       pp = scrp->wp->perl_private;
+    {
+       dTHXs
+       dSP;
+
+       sv_setiv(pp->svstart, f_lno);
+       sv_setiv(pp->svstop, t_lno);
+       newVIrv(pp->svcurscr, scrp);
+       /* Backwards compatibility. */
+       newVIrv(pp->svid, scrp);
+
+       istat = signal(SIGINT, my_sighandler);
+       INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
+       perl_eval(np);
+       signal(SIGINT, istat);
+
+       SvREFCNT_dec(SvRV(pp->svcurscr));
+       SvROK_off(pp->svcurscr);
+       SvREFCNT_dec(SvRV(pp->svid));
+       SvROK_off(pp->svid);
+
+       err = SvPV(ERRSV, length);
+       if (!length)
+               return (0);
+
+       err[length - 1] = '\0';
+       msgq(scrp, M_ERR, "perl: %s", err);
+       return (1);
+    }
+}
+
+/*
+ * replace_line
+ *     replace a line with the contents of the perl variable $_
+ *     lines are split at '\n's
+ *     if $_ is undef, the line is deleted
+ *     returns possibly adjusted linenumber
+ */
+static int 
+replace_line(scrp, line, t_lno, defsv)
+       SCR *scrp;
+       db_recno_t line, *t_lno;
+       SV *defsv;
+{
+       char *str, *next;
+       CHAR_T *wp;
+       size_t len, wlen;
+       dTHXs
+
+       if (SvOK(defsv)) {
+               str = SvPV(defsv,len);
+               next = memchr(str, '\n', len);
+               CHAR2INTP(scrp, str, next ? (next - str) : len, wp, wlen);
+               api_sline(scrp, line, wp, wlen);
+               while (next++) {
+                       len -= next - str;
+                       next = memchr(str = next, '\n', len);
+                       CHAR2INTP(scrp, str, next ? (next - str) : len, 
+                                   wp, wlen);
+                       api_iline(scrp, ++line, wp, wlen);
+                       (*t_lno)++;
+               }
+       } else {
+               api_dline(scrp, line--);
+               (*t_lno)--;
+       }
+       return line;
+}
+
+/* 
+ * perl_ex_perldo -- :[line [,line]] perl [command]
+ *     Run a set of lines through the perl interpreter.
+ *
+ * PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, db_recno_t, db_recno_t));
+ */
+int 
+perl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
+       SCR *scrp;
+       CHAR_T *cmdp;
+       size_t cmdlen;
+       db_recno_t f_lno, t_lno;
+{
+       CHAR_T *p;
+       WIN *wp;
+       size_t length;
+       size_t len;
+       db_recno_t i;
+       CHAR_T *str;
+       char *estr;
+       SV* cv;
+       char *command;
+       perl_data_t *pp;
+       char *np;
+       size_t nlen;
+
+       /* Initialize the interpreter. */
+       if (scrp->wp->perl_private == NULL && perl_init(scrp))
+                       return (1);
+       pp = scrp->wp->perl_private;
+    {
+       dTHXs
+       dSP;
+
+       newVIrv(pp->svcurscr, scrp);
+       /* Backwards compatibility. */
+       newVIrv(pp->svid, scrp);
+
+       INT2CHAR(scrp, cmdp, STRLEN(cmdp)+1, np, nlen);
+       if (!(command = malloc(length = nlen - 1 + sizeof("sub {}"))))
+               return 1;
+       snprintf(command, length, "sub {%s}", np);
+
+       ENTER;
+       SAVETMPS;
+
+       cv = perl_eval_pv(command, FALSE);
+       free (command);
+
+       estr = SvPV(ERRSV,length);
+       if (length)
+               goto err;
+
+       for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
+               INT2CHAR(scrp, str, len, np, nlen);
+               sv_setpvn(DEFSV,np,nlen);
+               sv_setiv(pp->svstart, i);
+               sv_setiv(pp->svstop, i);
+               PUSHMARK(sp);
+                perl_call_sv(cv, G_SCALAR | G_EVAL);
+               estr = SvPV(ERRSV, length);
+               if (length) break;
+               SPAGAIN;
+               if(SvTRUEx(POPs)) 
+                       i = replace_line(scrp, i, &t_lno, DEFSV);
+               PUTBACK;
+       }
+       FREETMPS;
+       LEAVE;
+
+       SvREFCNT_dec(SvRV(pp->svcurscr));
+       SvROK_off(pp->svcurscr);
+       SvREFCNT_dec(SvRV(pp->svid));
+       SvROK_off(pp->svid);
+
+       if (!length)
+               return (0);
+
+err:   estr[length - 1] = '\0';
+       msgq(scrp, M_ERR, "perl: %s", estr);
+       return (1);
+    }
+}
+
+/*
+ * msghandler --
+ *     Perl message routine so that error messages are processed in
+ *     Perl, not in nvi.
+ */
+static void
+msghandler(sp, mtype, msg, len)
+       SCR *sp;
+       mtype_t mtype;
+       char *msg;
+       size_t len;
+{
+       char    *errmsg;
+
+       errmsg = PERLP(sp)->errmsg;
+
+       /* Replace the trailing <newline> with an EOS. */
+       /* Let's do that later instead */
+       if (errmsg) free (errmsg);
+       errmsg = malloc(len + 1);
+       memcpy(errmsg, msg, len);
+       errmsg[len] = '\0';
+       PERLP(sp)->errmsg = errmsg;
+}
+
+
+typedef SCR *  VI;
+typedef SCR *  VI__OPT;
+typedef SCR *  VI__MAP;
+typedef SCR *  VI__MARK;
+typedef SCR *  VI__LINE;
+typedef AV *   AVREF;
+
+typedef struct {
+    SV      *sprv;
+    TAGQ    *tqp;
+} perl_tagq;
+
+typedef perl_tagq *  VI__TAGQ;
+typedef perl_tagq *  VI__TAGQ2;
+
+MODULE = VI    PACKAGE = VI
+
+# msg --
+#      Set the message line to text.
+#
+# Perl Command: VI::Msg
+# Usage: VI::Msg screenId text
+
+void
+Msg(screen, text)
+       VI          screen
+       char *      text
+       ALIAS:
+       PRINT = 1
+
+       CODE:
+       api_imessage(screen, text);
+
+# XS_VI_escreen --
+#      End a screen.
+#
+# Perl Command: VI::EndScreen
+# Usage: VI::EndScreen screenId
+
+void
+EndScreen(screen)
+       VI      screen
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_escreen(screen);
+       ENDMESSAGE(screen);
+
+# XS_VI_iscreen --
+#      Create a new screen.  If a filename is specified then the screen
+#      is opened with that file.
+#
+# Perl Command: VI::NewScreen
+# Usage: VI::NewScreen screenId [file]
+
+VI
+Edit(screen, ...)
+       VI screen
+
+       ALIAS:
+       NewScreen = 1
+
+       PROTOTYPE: $;$
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *file;
+       SCR *nsp;
+
+       CODE:
+       file = (items == 1) ? NULL : (char *)SvPV(ST(1),PL_na);
+       INITMESSAGE(screen);
+       rval = api_edit(screen, file, &nsp, ix);
+       ENDMESSAGE(screen);
+       
+       RETVAL = ix ? nsp : screen;
+
+       OUTPUT:
+       RETVAL
+
+# XS_VI_fscreen --
+#      Return the screen id associated with file name.
+#
+# Perl Command: VI::FindScreen
+# Usage: VI::FindScreen file
+
+VI
+FindScreen(file)
+       char *file
+
+       PREINIT:
+       SCR *fsp;
+       CODE:
+       RETVAL = api_fscreen(0, file);
+
+       OUTPUT:
+       RETVAL
+
+# XS_VI_GetFileName --
+#      Return the file name of the screen
+#
+# Perl Command: VI::GetFileName
+# Usage: VI::GetFileName screenId
+
+char *
+GetFileName(screen)
+       VI screen;
+
+       PPCODE:
+       EXTEND(sp,1);
+       PUSHs(sv_2mortal(newSVpv(screen->frp->name, 0)));
+
+# XS_VI_aline --
+#      -- Append the string text after the line in lineNumber.
+#
+# Perl Command: VI::AppendLine
+# Usage: VI::AppendLine screenId lineNumber text
+
+void
+AppendLine(screen, linenumber, text)
+       VI screen
+       int linenumber
+       char *text
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       size_t length;
+
+       CODE:
+       SvPV(ST(2), length);
+       INITMESSAGE(screen);
+       rval = api_aline(screen, linenumber, text, length);
+       ENDMESSAGE(screen);
+
+# XS_VI_dline --
+#      Delete lineNum.
+#
+# Perl Command: VI::DelLine
+# Usage: VI::DelLine screenId lineNum
+
+void 
+DelLine(screen, linenumber)
+       VI screen
+       int linenumber
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_dline(screen, (db_recno_t)linenumber);
+       ENDMESSAGE(screen);
+
+# XS_VI_gline --
+#      Return lineNumber.
+#
+# Perl Command: VI::GetLine
+# Usage: VI::GetLine screenId lineNumber
+
+char *
+GetLine(screen, linenumber)
+       VI screen
+       int linenumber
+
+       PREINIT:
+       size_t len;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *line;
+       CHAR_T *p;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
+       ENDMESSAGE(screen);
+
+       EXTEND(sp,1);
+        PUSHs(sv_2mortal(newSVpv(len ? (char *)p : "", len)));
+
+# XS_VI_sline --
+#      Set lineNumber to the text supplied.
+#
+# Perl Command: VI::SetLine
+# Usage: VI::SetLine screenId lineNumber text
+
+void
+SetLine(screen, linenumber, text)
+       VI screen
+       int linenumber
+       char *text
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       size_t length;
+       size_t len;
+       CHAR_T *line;
+
+       CODE:
+       SvPV(ST(2), length);
+       INITMESSAGE(screen);
+       CHAR2INTP(screen, text, length, line, len);
+       rval = api_sline(screen, linenumber, line, len);
+       ENDMESSAGE(screen);
+
+# XS_VI_iline --
+#      Insert the string text before the line in lineNumber.
+#
+# Perl Command: VI::InsertLine
+# Usage: VI::InsertLine screenId lineNumber text
+
+void
+InsertLine(screen, linenumber, text)
+       VI screen
+       int linenumber
+       char *text
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       size_t length;
+       size_t len;
+       CHAR_T *line;
+
+       CODE:
+       SvPV(ST(2), length);
+       INITMESSAGE(screen);
+       CHAR2INTP(screen, text, length, line, len);
+       rval = api_iline(screen, linenumber, line, len);
+       ENDMESSAGE(screen);
+
+# XS_VI_lline --
+#      Return the last line in the screen.
+#
+# Perl Command: VI::LastLine
+# Usage: VI::LastLine screenId
+
+int 
+LastLine(screen)
+       VI screen
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       ENDMESSAGE(screen);
+       RETVAL=last;
+
+       OUTPUT:
+       RETVAL
+
+# XS_VI_getmark --
+#      Return the mark's cursor position as a list with two elements.
+#      {line, column}.
+#
+# Perl Command: VI::GetMark
+# Usage: VI::GetMark screenId mark
+
+void
+GetMark(screen, mark)
+       VI screen
+       char mark
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       rval = api_getmark(screen, (int)mark, &cursor);
+       ENDMESSAGE(screen);
+
+       EXTEND(sp,2);
+        PUSHs(sv_2mortal(newSViv(cursor.lno)));
+        PUSHs(sv_2mortal(newSViv(cursor.cno)));
+
+# XS_VI_setmark --
+#      Set the mark to the line and column numbers supplied.
+#
+# Perl Command: VI::SetMark
+# Usage: VI::SetMark screenId mark line column
+
+void
+SetMark(screen, mark, line, column)
+       VI screen
+       char mark
+       int line
+       int column
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       cursor.lno = line;
+       cursor.cno = column;
+       rval = api_setmark(screen, (int)mark, &cursor);
+       ENDMESSAGE(screen);
+
+# XS_VI_getcursor --
+#      Return the current cursor position as a list with two elements.
+#      {line, column}.
+#
+# Perl Command: VI::GetCursor
+# Usage: VI::GetCursor screenId
+
+void
+GetCursor(screen)
+       VI screen
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       rval = api_getcursor(screen, &cursor);
+       ENDMESSAGE(screen);
+
+       EXTEND(sp,2);
+        PUSHs(sv_2mortal(newSViv(cursor.lno)));
+        PUSHs(sv_2mortal(newSViv(cursor.cno)));
+
+# XS_VI_setcursor --
+#      Set the cursor to the line and column numbers supplied.
+#
+# Perl Command: VI::SetCursor
+# Usage: VI::SetCursor screenId line column
+
+void
+SetCursor(screen, line, column)
+       VI screen
+       int line
+       int column
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       cursor.lno = line;
+       cursor.cno = column;
+       rval = api_setcursor(screen, &cursor);
+       ENDMESSAGE(screen);
+
+# XS_VI_swscreen --
+#      Change the current focus to screen.
+#
+# Perl Command: VI::SwitchScreen
+# Usage: VI::SwitchScreen screenId screenId
+
+void
+SwitchScreen(screenFrom, screenTo)
+       VI screenFrom
+       VI screenTo
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screenFrom);
+       rval = api_swscreen(screenFrom, screenTo);
+       ENDMESSAGE(screenFrom);
+
+# XS_VI_map --
+#      Associate a key with a perl procedure.
+#
+# Perl Command: VI::MapKey
+# Usage: VI::MapKey screenId key perlproc
+
+void
+MapKey(screen, key, commandsv)
+       VI screen
+       char *key
+       SV *commandsv
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       int length;
+       char *command;
+
+       CODE:
+       INITMESSAGE(screen);
+       command = SvPV(commandsv, length);
+       rval = api_map(screen, key, command, length);
+       ENDMESSAGE(screen);
+
+# XS_VI_unmap --
+#      Unmap a key.
+#
+# Perl Command: VI::UnmapKey
+# Usage: VI::UnmmapKey screenId key
+
+void
+UnmapKey(screen, key)
+       VI screen
+       char *key
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_unmap(screen, key);
+       ENDMESSAGE(screen);
+
+# XS_VI_opts_set --
+#      Set an option.
+#
+# Perl Command: VI::SetOpt
+# Usage: VI::SetOpt screenId setting
+
+void
+SetOpt(screen, setting)
+       VI screen
+       char *setting
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       SV *svc;
+
+       CODE:
+       INITMESSAGE(screen);
+       svc = sv_2mortal(newSVpv(":set ", 5));
+       sv_catpv(svc, setting);
+       rval = api_run_str(screen, SvPV(svc, PL_na));
+       ENDMESSAGE(screen);
+
+# XS_VI_opts_get --
+#      Return the value of an option.
+#      
+# Perl Command: VI::GetOpt
+# Usage: VI::GetOpt screenId option
+
+void
+GetOpt(screen, option)
+       VI screen
+       char *option
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *value;
+       CHAR_T *wp;
+       size_t wlen;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       CHAR2INTP(screen, option, strlen(option)+1, wp, wlen);
+       rval = api_opts_get(screen, wp, &value, NULL);
+       ENDMESSAGE(screen);
+
+       EXTEND(SP,1);
+       PUSHs(sv_2mortal(newSVpv(value, 0)));
+       free(value);
+
+# XS_VI_run --
+#      Run the ex command cmd.
+#
+# Perl Command: VI::Run
+# Usage: VI::Run screenId cmd
+
+void
+Run(screen, command)
+       VI screen
+       char *command;
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_run_str(screen, command);
+       ENDMESSAGE(screen);
+
+void 
+DESTROY(screensv)
+       SV* screensv
+
+       PREINIT:
+       VI  screen;
+
+       CODE:
+       if (sv_isa(screensv, "VI")) {
+               IV tmp = SvIV((SV*)SvRV(screensv));
+               screen = (SCR *) tmp;
+       }
+       else
+               croak("screen is not of type VI");
+
+       if (screen)
+       screen->perl_private = 0;
+
+void
+Warn(warning)
+       char *warning;
+
+       CODE:
+       sv_catpv(ERRSV,warning);
+
+#define TIED(kind,package) \
+       sv_magic((SV *) (var = \
+           (kind##V *)sv_2mortal((SV *)new##kind##V())), \
+               sv_setref_pv(sv_newmortal(), package, \
+                       newVIrv(newSV(0), screen)),\
+               'P', Nullch, 0);\
+       RETVAL = newRV((SV *)var)
+
+SV *
+Opt(screen)
+       VI screen;
+       PREINIT:
+       HV *var;
+       CODE:
+       TIED(H,"VI::OPT");
+       OUTPUT:
+       RETVAL
+
+SV *
+Map(screen)
+       VI screen;
+       PREINIT:
+       HV *var;
+       CODE:
+       TIED(H,"VI::MAP");
+       OUTPUT:
+       RETVAL
+
+SV *
+Mark(screen)
+       VI screen
+       PREINIT:
+       HV *var;
+       CODE:
+       TIED(H,"VI::MARK");
+       OUTPUT:
+       RETVAL
+
+SV *
+Line(screen)
+       VI screen
+       PREINIT:
+       AV *var;
+       CODE:
+       TIED(A,"VI::LINE");
+       OUTPUT:
+       RETVAL
+
+SV *
+TagQ(screen, tag)
+       VI screen
+       char *tag;
+
+       PREINIT:
+       perl_tagq *ptag;
+
+       PPCODE:
+       if ((ptag = malloc(sizeof(perl_tagq))) == NULL)
+               goto err;
+
+       ptag->sprv = newVIrv(newSV(0), screen);
+       ptag->tqp = api_tagq_new(screen, tag);
+       if (ptag->tqp != NULL) {
+               EXTEND(SP,1);
+               PUSHs(sv_2mortal(sv_setref_pv(newSV(0), "VI::TAGQ", ptag)));
+       } else {
+err:
+               ST(0) = &PL_sv_undef;
+               return;
+       }
+
+MODULE = VI    PACKAGE = VI::OPT
+
+void 
+DESTROY(screen)
+       VI::OPT screen
+
+       CODE:
+       # typemap did all the checking
+       SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+void
+FETCH(screen, key)
+       VI::OPT screen
+       char *key
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *value;
+       int boolvalue;
+       CHAR_T *wp;
+       size_t wlen;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
+       rval = api_opts_get(screen, wp, &value, &boolvalue);
+       if (!rval) {
+               EXTEND(SP,1);
+               PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
+                                                  : newSViv(boolvalue)));
+               free(value);
+       } else ST(0) = &PL_sv_undef;
+       rval = 0;
+       ENDMESSAGE(screen);
+
+void
+STORE(screen, key, value)
+       VI::OPT screen
+       char    *key
+       SV      *value
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       CHAR_T *wp;
+       size_t wlen;
+
+       CODE:
+       INITMESSAGE(screen);
+       CHAR2INTP(screen, key, strlen(key)+1, wp, wlen);
+       rval = api_opts_set(screen, wp, SvPV(value, PL_na), SvIV(value), 
+                                         SvTRUEx(value));
+       ENDMESSAGE(screen);
+
+MODULE = VI    PACKAGE = VI::MAP
+
+void 
+DESTROY(screen)
+       VI::MAP screen
+
+       CODE:
+       # typemap did all the checking
+       SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+void
+STORE(screen, key, commandsv)
+       VI::MAP screen
+       char *key
+       SV *commandsv
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       int length;
+       char *command;
+
+       CODE:
+       INITMESSAGE(screen);
+       command = SvPV(commandsv, length);
+       rval = api_map(screen, key, command, length);
+       ENDMESSAGE(screen);
+
+void
+DELETE(screen, key)
+       VI::MAP screen
+       char *key
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_unmap(screen, key);
+       ENDMESSAGE(screen);
+
+MODULE = VI    PACKAGE = VI::MARK
+
+void 
+DESTROY(screen)
+       VI::MARK screen
+
+       CODE:
+       # typemap did all the checking
+       SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+int
+EXISTS(screen, mark)
+       VI::MARK screen
+       char mark
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval = 0; /* never croak */
+       int missing;
+
+       CODE:
+       INITMESSAGE(screen);
+       missing = api_getmark(screen, (int)mark, &cursor);
+       ENDMESSAGE(screen);
+       RETVAL = !missing;
+
+       OUTPUT:
+       RETVAL
+
+AV *
+FETCH(screen, mark)
+       VI::MARK screen
+       char mark
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_getmark(screen, (int)mark, &cursor);
+       ENDMESSAGE(screen);
+       RETVAL = newAV();
+       av_push(RETVAL, newSViv(cursor.lno));
+       av_push(RETVAL, newSViv(cursor.cno));
+
+       OUTPUT:
+       RETVAL
+
+void
+STORE(screen, mark, pos)
+       VI::MARK screen
+       char mark
+       AVREF pos
+
+       PREINIT:
+       struct _mark cursor;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       if (av_len(pos) < 1) 
+           croak("cursor position needs 2 elements");
+       INITMESSAGE(screen);
+       cursor.lno = SvIV(*av_fetch(pos, 0, 0));
+       cursor.cno = SvIV(*av_fetch(pos, 1, 0));
+       rval = api_setmark(screen, (int)mark, &cursor);
+       ENDMESSAGE(screen);
+
+void
+FIRSTKEY(screen, ...)
+       VI::MARK screen
+
+       ALIAS:
+       NEXTKEY = 1
+       
+       PROTOTYPE: $;$
+
+       PREINIT:
+       int next;
+       char key[] = {0, 0};
+
+       PPCODE:
+       if (items == 2) {
+               next = 1;
+               *key = *(char *)SvPV(ST(1),PL_na);
+       } else next = 0;
+       if (api_nextmark(screen, next, key) != 1) {
+               EXTEND(sp, 1);
+               PUSHs(sv_2mortal(newSVpv(key, 1)));
+       } else ST(0) = &PL_sv_undef;
+
+MODULE = VI    PACKAGE = VI::LINE
+
+void 
+DESTROY(screen)
+       VI::LINE screen
+
+       CODE:
+       # typemap did all the checking
+       SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+# similar to SetLine
+
+void
+STORE(screen, linenumber, text)
+       VI::LINE screen
+       int linenumber
+       char *text
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       size_t length;
+       db_recno_t last;
+       size_t len;
+       CHAR_T *line;
+
+       CODE:
+       ++linenumber;   /* vi 1 based ; perl 0 based */
+       SvPV(ST(2), length);
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       if (!rval) {
+           if (linenumber > last)
+               rval = api_extend(screen, linenumber);
+           if (!rval)
+               CHAR2INTP(screen, text, length, line, len);
+               rval = api_sline(screen, linenumber, line, len);
+       }
+       ENDMESSAGE(screen);
+
+# similar to GetLine 
+
+char *
+FETCH(screen, linenumber)
+       VI::LINE screen
+       int linenumber
+
+       PREINIT:
+       size_t len;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *line;
+       CHAR_T *p;
+
+       PPCODE:
+       ++linenumber;   /* vi 1 based ; perl 0 based */
+       INITMESSAGE(screen);
+       rval = api_gline(screen, (db_recno_t)linenumber, &p, &len);
+       ENDMESSAGE(screen);
+
+       EXTEND(sp,1);
+       PUSHs(sv_2mortal(newSVpv(len ? (char*)p : "", len)));
+
+# similar to LastLine 
+
+int
+FETCHSIZE(screen)
+       VI::LINE screen
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       ENDMESSAGE(screen);
+       RETVAL=last;
+
+       OUTPUT:
+       RETVAL
+
+void
+STORESIZE(screen, count)
+       VI::LINE screen
+       int count
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       if (!rval) {
+           if (count > last)
+               rval = api_extend(screen, count);
+           else while(last && last > count) {
+               rval = api_dline(screen, last--);
+               if (rval) break;
+           }
+       }
+       ENDMESSAGE(screen);
+
+void
+EXTEND(screen, count)
+       VI::LINE screen
+       int count
+
+       CODE:
+
+void
+CLEAR(screen)
+       VI::LINE screen
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       if (!rval) {
+           while(last) {
+               rval = api_dline(screen, last--);
+               if (rval) break;
+           }
+       }
+       ENDMESSAGE(screen);
+
+void
+PUSH(screen, ...)
+       VI::LINE screen;
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval, i, len;
+       char *line;
+
+       CODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+
+       if (!rval)
+               for (i = 1; i < items; ++i) {
+                       line = SvPV(ST(i), len);
+                       if ((rval = api_aline(screen, last++, line, len)))
+                               break;
+               }
+       ENDMESSAGE(screen);
+
+SV *
+POP(screen)
+       VI::LINE screen;
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval, i, len;
+       CHAR_T *line;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       if (rval || last < 1)
+               ST(0) = &PL_sv_undef;
+       else {
+               rval = api_gline(screen, last, &line, &len) ||
+                      api_dline(screen, last);
+               EXTEND(sp,1);
+               PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
+       }
+       ENDMESSAGE(screen);
+
+SV *
+SHIFT(screen)
+       VI::LINE screen;
+
+       PREINIT:
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval, i, len;
+       CHAR_T *line;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       if (rval || last < 1)
+               ST(0) = &PL_sv_undef;
+       else {
+               rval = api_gline(screen, (db_recno_t)1, &line, &len) ||
+                      api_dline(screen, (db_recno_t)1);
+               EXTEND(sp,1);
+               PUSHs(sv_2mortal(newSVpv(len ? (char *)line : "", len)));
+       }
+       ENDMESSAGE(screen);
+
+void
+UNSHIFT(screen, ...)
+       VI::LINE screen;
+
+       PREINIT:
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval, i, len;
+       char *np;
+       size_t nlen;
+       CHAR_T *line;
+
+       CODE:
+       INITMESSAGE(screen);
+       while (--items != 0) {
+               np = SvPV(ST(items), nlen);
+               CHAR2INTP(screen, np, nlen, line, len);
+               if ((rval = api_iline(screen, (db_recno_t)1, line, len)))
+                       break;
+       }
+       ENDMESSAGE(screen);
+
+void
+SPLICE(screen, ...)
+       VI::LINE screen;
+
+       PREINIT:
+       db_recno_t last, db_offset;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval, length, common, len, i, offset;
+       CHAR_T *line;
+       char *np;
+       size_t nlen;
+
+       PPCODE:
+       INITMESSAGE(screen);
+       rval = api_lline(screen, &last);
+       offset = items > 1 ? (int)SvIV(ST(1)) : 0;
+       if (offset < 0) offset += last;
+       if (offset < 0) {
+           ENDMESSAGE(screen);
+           croak("Invalid offset");
+       }
+       length = items > 2 ? (int)SvIV(ST(2)) : last - offset;
+       if (length > last - offset)
+               length = last - offset;
+       db_offset = offset + 1; /* 1 based */
+       EXTEND(sp,length);
+       for (common = MIN(length, items - 3), i = 3; common > 0; 
+           --common, ++db_offset, --length, ++i) {
+               rval |= api_gline(screen, db_offset, &line, &len);
+               INT2CHAR(screen, line, len, np, nlen);
+               PUSHs(sv_2mortal(newSVpv(nlen ? np : "", nlen)));
+               np = SvPV(ST(i), nlen);
+               CHAR2INTP(screen, np, nlen, line, len);
+               rval |= api_sline(screen, db_offset, line, len);
+       }
+       for (; length; --length) {
+               rval |= api_gline(screen, db_offset, &line, &len);
+               INT2CHAR(screen, line, len, np, nlen);
+               PUSHs(sv_2mortal(newSVpv(len ? np : "", nlen)));
+               rval |= api_dline(screen, db_offset);
+       }
+       for (; i < items; ++i) {
+               np = SvPV(ST(i), len);
+               CHAR2INTP(screen, np, len, line, nlen);
+               rval |= api_iline(screen, db_offset, line, nlen);
+       }
+       ENDMESSAGE(screen);
+
+MODULE = VI    PACKAGE = VI::TAGQ
+
+void
+Add(tagq, filename, search, msg)
+       VI::TAGQ    tagq;
+       char       *filename;
+       char       *search;
+       char       *msg;
+
+       PREINIT:
+       SCR *sp;
+
+       CODE:
+       sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
+       if (!sp)
+               croak("screen no longer exists");
+       api_tagq_add(sp, tagq->tqp, filename, search, msg);
+
+void
+Push(tagq)
+       VI::TAGQ    tagq;
+
+       PREINIT:
+       SCR *sp;
+
+       CODE:
+       sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
+       if (!sp)
+               croak("screen no longer exists");
+       api_tagq_push(sp, &tagq->tqp);
+
+void
+DESTROY(tagq)
+       # Can already be invalidated by push 
+       VI::TAGQ2    tagq; 
+
+       PREINIT:
+       SCR *sp;
+
+       CODE:
+       sp = (SCR *)SvIV((SV*)SvRV(tagq->sprv));
+       if (sp)
+               api_tagq_free(sp, tagq->tqp);
+       SvREFCNT_dec(tagq->sprv);
+       free(tagq);
diff --git a/dist/nvi/perl_api/perlsfio.c b/dist/nvi/perl_api/perlsfio.c
new file mode 100644 (file)
index 0000000..3ba707d
--- /dev/null
@@ -0,0 +1,95 @@
+/*     $NetBSD: perlsfio.c,v 1.1.1.2 2008/05/18 14:31:33 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1996
+ *     Sven Verdoolaege. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#ifndef lint
+static const char sccsid[] = "Id: perlsfio.c,v 8.3 2000/04/30 17:00:15 skimo Exp (Berkeley) Date: 2000/04/30 17:00:15";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+/* perl redefines them
+ * avoid warnings
+ */
+#undef USE_DYNAMIC_LOADING
+#undef DEBUG
+#undef PACKAGE
+#undef ARGS
+#define ARGS ARGS
+
+#include "config.h"
+
+#include "../common/common.h"
+#include "extern.h"
+
+/*
+ * PUBLIC: #ifdef USE_SFIO
+ */
+#ifdef USE_SFIO
+
+#define NIL(type)       ((type)0)
+
+static int
+sfnviwrite(f, buf, n, disc)
+Sfio_t* f;      /* stream involved */
+char*           buf;    /* buffer to read into */
+int             n;      /* number of bytes to read */
+Sfdisc_t*       disc;   /* discipline */        
+{
+       SCR *scrp;
+
+       scrp = (SCR *)SvIV((SV*)SvRV(perl_get_sv("curscr", FALSE)));
+       msgq(scrp, M_INFO, "%.*s", n, buf);
+       return n;
+}
+
+/*
+ * sfdcnewnvi --
+ *     Create nvi discipline
+ *
+ * PUBLIC: Sfdisc_t* sfdcnewnvi __P((SCR*));
+ */
+
+Sfdisc_t *
+sfdcnewnvi(scrp)
+       SCR *scrp;
+{
+       Sfdisc_t*   disc;
+
+       MALLOC(scrp, disc, Sfdisc_t*, sizeof(Sfdisc_t));
+       if (!disc) return disc;
+
+       disc->readf = (Sfread_f)NULL;
+       disc->writef = sfnviwrite;
+       disc->seekf = (Sfseek_f)NULL;
+       disc->exceptf = (Sfexcept_f)NULL;
+       return disc;
+}
+
+/*
+ * PUBLIC: #endif
+ */
+#endif /* USE_SFIO */
diff --git a/dist/nvi/perl_api/typemap b/dist/nvi/perl_api/typemap
new file mode 100644 (file)
index 0000000..1e0a43a
--- /dev/null
@@ -0,0 +1,57 @@
+TYPEMAP
+# Grr can't let it end in OBJ 'cause xsubpp would
+# s/OBJ$/REF/ that for the DESTROY function
+VI     T_VIOBJNOMUNGE
+VI::OPT        T_VIOBJREF
+VI::MAP        T_VIOBJREF
+VI::MARK       T_VIOBJREF
+VI::LINE       T_VIOBJREF
+VI::TAGQ       T_VITAGQ
+VI::TAGQ2      T_VITAGQ2
+AVREF  T_AVREFREF
+
+INPUT
+T_AVREFREF
+       if (SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV) 
+           $var = (AV *)SvRV($arg);
+       else
+           croak(\"$var is not a reference to an array\")
+T_VIOBJNOMUNGE
+       if (sv_isa($arg, \"VI\")) {
+           IV tmp = SvIV((SV*)SvRV($arg));
+           $var = ($type) tmp;
+           if (!tmp)
+               croak(\"screen no longer exists\");
+       }
+       else
+           croak(\"$var is not of type ${ntype}\")
+T_VIOBJREF
+       if (sv_isa($arg, \"${ntype}\")) {
+           IV tmp = SvIV((SV*)SvRV($arg));
+           if (sv_isa((SV *)tmp, \"VI\")) {
+               IV tmp2 = SvIV((SV*)SvRV((SV *)tmp));
+               $var = ($type) tmp2;
+               if (!tmp2)
+                   croak(\"screen no longer exists\");
+           }
+           else
+               croak(\"$var is not of type ${ntype}\");
+       }
+       else
+           croak(\"$var is not of type ${ntype}\")
+T_VITAGQ
+       if (sv_isa($arg, \"VI::TAGQ\")) {
+           $var = ($type) SvIV((SV*)SvRV($arg));
+           if ($var->tqp == 0)
+               croak(\"Tag queue invalidated\");
+       } else
+           croak(\"$var is not of type ${ntype}\")
+T_VITAGQ2
+       if (sv_isa($arg, \"VI::TAGQ\")) {
+           $var = ($type) SvIV((SV*)SvRV($arg));
+       } else
+           croak(\"$var is not of type ${ntype}\")
+
+OUTPUT
+T_VIOBJNOMUNGE
+       newVIrv($arg, $var);
diff --git a/dist/nvi/perl_scripts/forall.pl b/dist/nvi/perl_scripts/forall.pl
new file mode 100644 (file)
index 0000000..b9f8501
--- /dev/null
@@ -0,0 +1,10 @@
+sub forall {
+  my ($code) = shift;
+  my ($i) = $VI::StartLine-1;
+  while (++$i <= $VI::StopLine) {
+    $_ = $curscr->GetLine($i);
+    VI::SetLine($VI::ScreenId, $i, $_) if(&$code);
+  }
+}
+
+1;
diff --git a/dist/nvi/perl_scripts/make.pl b/dist/nvi/perl_scripts/make.pl
new file mode 100644 (file)
index 0000000..54a9c86
--- /dev/null
@@ -0,0 +1,20 @@
+sub push_tags {
+    my ($fh) = shift;
+    my ($tagq) = $curscr->TagQ("msg");
+    while(<$fh>) {
+       my ($f, $l, $m);
+       if ((($f, $l, $m) = split /:/) >= 2 && -f $f && $l =~ /^\d+$/) {
+           $tagq->Add($f, $l, $m);
+       }
+    }
+    $tagq->Push();
+}
+
+sub make {
+    local (*FH);
+    open FH, "make 2>&1 |";
+    ::push_tags(\*FH);
+    close FH;
+}
+
+1;
diff --git a/dist/nvi/perl_scripts/tk.pl b/dist/nvi/perl_scripts/tk.pl
new file mode 100644 (file)
index 0000000..f8d1bc0
--- /dev/null
@@ -0,0 +1,20 @@
+# make sure every subprocess has it's exit and that the main one
+# hasn't
+sub fun {
+    unless ($pid = fork) {
+        unless (fork) {
+            use Tk;
+            $MW = MainWindow->new;
+            $hello = $MW->Button(
+                -text    => 'Hello, world',
+                -command => sub {exit;},
+            );
+            $hello->pack;
+            MainLoop;
+        }
+        exit 0;
+    }
+    waitpid($pid, 0);
+}
+
+1;
diff --git a/dist/nvi/perl_scripts/wc.pl b/dist/nvi/perl_scripts/wc.pl
new file mode 100644 (file)
index 0000000..0a50159
--- /dev/null
@@ -0,0 +1,11 @@
+sub wc {
+  my $words;
+  $i = $VI::StartLine;
+  while ($i <= $VI::StopLine) {
+    $_ = $curscr->GetLine($i++);
+    $words+=split;
+  }
+  $curscr->Msg("$words words");
+}
+
+1;
diff --git a/dist/nvi/regex/COPYRIGHT b/dist/nvi/regex/COPYRIGHT
new file mode 100644 (file)
index 0000000..574f6bc
--- /dev/null
@@ -0,0 +1,56 @@
+Copyright 1992, 1993, 1994 Henry Spencer.  All rights reserved.
+This software is not subject to any license of the American Telephone
+and Telegraph Company or of the Regents of the University of California.
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it, subject
+to the following restrictions:
+
+1. The author is not responsible for the consequences of use of this
+   software, no matter how awful, even if they arise from flaws in it.
+
+2. The origin of this software must not be misrepresented, either by
+   explicit claim or by omission.  Since few users ever read sources,
+   credits must appear in the documentation.
+
+3. Altered versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.  Since few users
+   ever read sources, credits must appear in the documentation.
+
+4. This notice may not be removed or altered.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/*-
+ * Copyright (c) 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)COPYRIGHT   8.1 (Berkeley) 3/16/94
+ */
diff --git a/dist/nvi/regex/WHATSNEW b/dist/nvi/regex/WHATSNEW
new file mode 100644 (file)
index 0000000..f4301d3
--- /dev/null
@@ -0,0 +1,94 @@
+# @(#)WHATSNEW 8.3 (Berkeley) 3/18/94
+
+New in alpha3.4:  The complex bug alluded to below has been fixed (in a
+slightly kludgey temporary way that may hurt efficiency a bit; this is
+another "get it out the door for 4.4" release).  The tests at the end of
+the tests file have accordingly been uncommented.  The primary sign of
+the bug was that something like a?b matching ab matched b rather than ab.
+(The bug was essentially specific to this exact situation, else it would
+have shown up earlier.)
+
+New in alpha3.3:  The definition of word boundaries has been altered
+slightly, to more closely match the usual programming notion that "_"
+is an alphabetic.  Stuff used for pre-ANSI systems is now in a subdir,
+and the makefile no longer alludes to it in mysterious ways.  The
+makefile has generally been cleaned up some.  Fixes have been made
+(again!) so that the regression test will run without -DREDEBUG, at
+the cost of weaker checking.  A workaround for a bug in some folks'
+<assert.h> has been added.  And some more things have been added to
+tests, including a couple right at the end which are commented out
+because the code currently flunks them (complex bug; fix coming).
+Plus the usual minor cleanup.
+
+New in alpha3.2:  Assorted bits of cleanup and portability improvement
+(the development base is now a BSDI system using GCC instead of an ancient
+Sun system, and the newer compiler exposed some glitches).  Fix for a
+serious bug that affected REs using many [] (including REG_ICASE REs
+because of the way they are implemented), *sometimes*, depending on
+memory-allocation patterns.  The header-file prototypes no longer name
+the parameters, avoiding possible name conflicts.  The possibility that
+some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is
+now handled gracefully.  "uchar" is no longer used as an internal type
+name (too many people have the same idea).  Still the same old lousy
+performance, alas.
+
+New in alpha3.1:  Basically nothing, this release is just a bookkeeping
+convenience.  Stay tuned.
+
+New in alpha3.0:  Performance is no better, alas, but some fixes have been
+made and some functionality has been added.  (This is basically the "get
+it out the door in time for 4.4" release.)  One bug fix:  regfree() didn't
+free the main internal structure (how embarrassing).  It is now possible
+to put NULs in either the RE or the target string, using (resp.) a new
+REG_PEND flag and the old REG_STARTEND flag.  The REG_NOSPEC flag to
+regcomp() makes all characters ordinary, so you can match a literal
+string easily (this will become more useful when performance improves!).
+There are now primitives to match beginnings and ends of words, although
+the syntax is disgusting and so is the implementation.  The REG_ATOI
+debugging interface has changed a bit.  And there has been considerable
+internal cleanup of various kinds.
+
+New in alpha2.3:  Split change list out of README, and moved flags notes
+into Makefile.  Macro-ized the name of regex(7) in regex(3), since it has
+to change for 4.4BSD.  Cleanup work in engine.c, and some new regression
+tests to catch tricky cases thereof.
+
+New in alpha2.2:  Out-of-date manpages updated.  Regerror() acquires two
+small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges
+in my own test program and might be useful to others for similar purposes.
+The regression test will now compile (and run) without REDEBUG.  The
+BRE \$ bug is fixed.  Most uses of "uchar" are gone; it's all chars now.
+Char/uchar parameters are now written int/unsigned, to avoid possible
+portability problems with unpromoted parameters.  Some unsigned casts have
+been introduced to minimize portability problems with shifting into sign
+bits.
+
+New in alpha2.1:  Lots of little stuff, cleanup and fixes.  The one big
+thing is that regex.h is now generated, using mkh, rather than being
+supplied in the distribution; due to circularities in dependencies,
+you have to build regex.h explicitly by "make h".  The two known bugs
+have been fixed (and the regression test now checks for them), as has a
+problem with assertions not being suppressed in the absence of REDEBUG.
+No performance work yet.
+
+New in alpha2:  Backslash-anything is an ordinary character, not an
+error (except, of course, for the handful of backslashed metacharacters
+in BREs), which should reduce script breakage.  The regression test
+checks *where* null strings are supposed to match, and has generally
+been tightened up somewhat.  Small bug fixes in parameter passing (not
+harmful, but technically errors) and some other areas.  Debugging
+invoked by defining REDEBUG rather than not defining NDEBUG.
+
+New in alpha+3:  full prototyping for internal routines, using a little
+helper program, mkh, which extracts prototypes given in stylized comments.
+More minor cleanup.  Buglet fix:  it's CHAR_BIT, not CHAR_BITS.  Simple
+pre-screening of input when a literal string is known to be part of the
+RE; this does wonders for performance.
+
+New in alpha+2:  minor bits of cleanup.  Notably, the number "32" for the
+word width isn't hardwired into regexec.c any more, the public header
+file prototypes the functions if __STDC__ is defined, and some small typos
+in the manpages have been fixed.
+
+New in alpha+1:  improvements to the manual pages, and an important
+extension, the REG_STARTEND option to regexec().
diff --git a/dist/nvi/regex/cclass.h b/dist/nvi/regex/cclass.h
new file mode 100644 (file)
index 0000000..f28bccd
--- /dev/null
@@ -0,0 +1,85 @@
+/*     $NetBSD: cclass.h,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)cclass.h    8.2 (Berkeley) 3/16/94
+ */
+
+RCHAR_T ALNUM[] = {'a','l','n','u','m',0};
+RCHAR_T ALPHA[] = {'a','l','p','h','a',0};
+RCHAR_T BLANK[] = {'b','l','a','n','k',0};
+RCHAR_T CNTRL[] = {'c','n','t','r','l',0};
+RCHAR_T DIGIT[] = {'d','i','g','i','t',0};
+RCHAR_T GRAPH[] = {'g','r','a','p','h',0};
+RCHAR_T LOWER[] = {'l','o','w','e','r',0};
+RCHAR_T PRINT[] = {'p','r','i','n','t',0};
+RCHAR_T PUNCT[] = {'p','u','n','c','t',0};
+RCHAR_T SPACE[] = {'s','p','a','c','e',0};
+RCHAR_T UPPER[] = {'u','p','p','e','r',0};
+RCHAR_T XDIGIT[] = {'x','d','i','g','i','t',0};
+
+/* character-class table */
+static struct cclass {
+       RCHAR_T *name;
+       const char *chars;
+       const char *multis;
+} cclasses[] = {
+       { ALNUM,        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789",                           "" },
+       { ALPHA,        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+                                       "" },
+       { BLANK,        " \t",          "" },
+       { CNTRL,        "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
+\25\26\27\30\31\32\33\34\35\36\37\177",        "" },
+       { DIGIT,        "0123456789",   "" },
+       { GRAPH,        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+                                       "" },
+       { LOWER,        "abcdefghijklmnopqrstuvwxyz",
+                                       "" },
+       { PRINT,        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
+0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
+                                       "" },
+       { PUNCT,        "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+                                       "" },
+       { SPACE,        "\t\n\v\f\r ",  "" },
+       { UPPER,        "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+                                       "" },
+       { XDIGIT,       "0123456789ABCDEFabcdef",
+                                       "" },
+       { NULL,         0,              "" },
+};
diff --git a/dist/nvi/regex/cname.h b/dist/nvi/regex/cname.h
new file mode 100644 (file)
index 0000000..da69843
--- /dev/null
@@ -0,0 +1,143 @@
+/*     $NetBSD: cname.h,v 1.2 2008/12/05 22:51:42 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)cname.h     8.2 (Berkeley) 3/16/94
+ */
+
+/* character-name table */
+static struct cname {
+       const RCHAR_T *name;
+       char code;
+} cnames[] = {
+       { L("NUL"),             '\0' },
+       { L("SOH"),             '\001' },
+       { L("STX"),             '\002' },
+       { L("ETX"),             '\003' },
+       { L("EOT"),             '\004' },
+       { L("ENQ"),             '\005' },
+       { L("ACK"),             '\006' },
+       { L("BEL"),             '\007' },
+       { L("alert"),           '\007' },
+       { L("BS"),              '\010' },
+       { L("backspace"),       '\b' },
+       { L("HT"),              '\011' },
+       { L("tab"),             '\t' },
+       { L("LF"),              '\012' },
+       { L("newline"),         '\n' },
+       { L("VT"),              '\013' },
+       { L("vertical-tab"),    '\v' },
+       { L("FF"),              '\014' },
+       { L("form-feed"),       '\f' },
+       { L("CR"),              '\015' },
+       { L("carriage-return"), '\r' },
+       { L("SO"),              '\016' },
+       { L("SI"),              '\017' },
+       { L("DLE"),             '\020' },
+       { L("DC1"),             '\021' },
+       { L("DC2"),             '\022' },
+       { L("DC3"),             '\023' },
+       { L("DC4"),             '\024' },
+       { L("NAK"),             '\025' },
+       { L("SYN"),             '\026' },
+       { L("ETB"),             '\027' },
+       { L("CAN"),             '\030' },
+       { L("EM"),              '\031' },
+       { L("SUB"),             '\032' },
+       { L("ESC"),             '\033' },
+       { L("IS4"),             '\034' },
+       { L("FS"),              '\034' },
+       { L("IS3"),             '\035' },
+       { L("GS"),              '\035' },
+       { L("IS2"),             '\036' },
+       { L("RS"),              '\036' },
+       { L("IS1"),             '\037' },
+       { L("US"),              '\037' },
+       { L("space"),           ' ' },
+       { L("exclamation-mark"),'!' },
+       { L("quotation-mark"),  '"' },
+       { L("number-sign"),     '#' },
+       { L("dollar-sign"),     '$' },
+       { L("percent-sign"),    '%' },
+       { L("ampersand"),       '&' },
+       { L("apostrophe"),      '\'' },
+       { L("left-parenthesis"),'(' },
+       { L("right-parenthesis"),')' },
+       { L("asterisk"),        '*' },
+       { L("plus-sign"),       '+' },
+       { L("comma"),           ',' },
+       { L("hyphen"),          '-' },
+       { L("hyphen-minus"),    '-' },
+       { L("period"),          '.' },
+       { L("full-stop"),       '.' },
+       { L("slash"),           '/' },
+       { L("solidus"),         '/' },
+       { L("zero"),            '0' },
+       { L("one"),             '1' },
+       { L("two"),             '2' },
+       { L("three"),           '3' },
+       { L("four"),            '4' },
+       { L("five"),            '5' },
+       { L("six"),             '6' },
+       { L("seven"),           '7' },
+       { L("eight"),           '8' },
+       { L("nine"),            '9' },
+       { L("colon"),           ':' },
+       { L("semicolon"),       ';' },
+       { L("less-than-sign"),  '<' },
+       { L("equals-sign"),     '=' },
+       { L("greater-than-sign"),'>' },
+       { L("question-mark"),   '?' },
+       { L("commercial-at"),   '@' },
+       { L("left-square-bracket"),'[' },
+       { L("backslash"),       '\\' },
+       { L("reverse-solidus"), '\\' },
+       { L("right-square-bracket"),']' },
+       { L("circumflex"),      '^' },
+       { L("circumflex-accent"),'^' },
+       { L("underscore"),      '_' },
+       { L("low-line"),        '_' },
+       { L("grave-accent"),    '`' },
+       { L("left-brace"),      '{' },
+       { L("left-curly-bracket"),'{' },
+       { L("vertical-line"),   '|' },
+       { L("right-brace"),     '}' },
+       { L("right-curly-bracket"),'}' },
+       { L("tilde"),           '~' },
+       { L("DEL"),             '\177' },
+       { NULL,                 0 },
+};
diff --git a/dist/nvi/regex/engine.c b/dist/nvi/regex/engine.c
new file mode 100644 (file)
index 0000000..06dd4ec
--- /dev/null
@@ -0,0 +1,1102 @@
+/*     $NetBSD: engine.c,v 1.7 2011/11/19 17:45:11 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)engine.c    8.4 (Berkeley) 3/19/94
+ */
+
+/*
+ * The matching engine and friends.  This file is #included by regexec.c
+ * after suitable #defines of a variety of macros used herein, so that
+ * different state representations can be used without duplicating masses
+ * of code.
+ */
+
+#ifdef SNAMES
+#define        matcher smatcher
+#define        fast    sfast
+#define        slow    sslow
+#define        dissect sdissect
+#define        backref sbackref
+#define        step    sstep
+#define        print   sprint
+#define        at      sat
+#define        match   smat
+#endif
+#ifdef LNAMES
+#define        matcher lmatcher
+#define        fast    lfast
+#define        slow    lslow
+#define        dissect ldissect
+#define        backref lbackref
+#define        step    lstep
+#define        print   lprint
+#define        at      lat
+#define        match   lmat
+#endif
+
+/* another structure passed up and down to avoid zillions of parameters */
+struct match {
+       struct re_guts *g;
+       int eflags;
+       regmatch_t *pmatch;     /* [nsub+1] (0 element unused) */
+       RCHAR_T *offp;          /* offsets work from here */
+       RCHAR_T *beginp;                /* start of string -- virtual NUL precedes */
+       RCHAR_T *endp;          /* end of string -- virtual NUL here */
+       RCHAR_T *coldp;         /* can be no match starting before here */
+       RCHAR_T **lastpos;      /* [nplus+1] */
+       STATEVARS;
+       states st;              /* current states */
+       states fresh;           /* states for a fresh start */
+       states tmp;             /* temporary */
+       states empty;           /* empty set of states */
+};
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === engine.c === */
+static int matcher __P((struct re_guts *g, RCHAR_T *string, size_t nmatch, regmatch_t pmatch[], int eflags));
+static RCHAR_T *dissect __P((struct match *m, RCHAR_T *start, RCHAR_T *stop, sopno startst, sopno stopst));
+static RCHAR_T *backref __P((struct match *m, RCHAR_T *start, RCHAR_T *stop, sopno startst, sopno stopst, sopno lev));
+static RCHAR_T *fast __P((struct match *m, RCHAR_T *start, RCHAR_T *stop, sopno startst, sopno stopst));
+static RCHAR_T *slow __P((struct match *m, RCHAR_T *start, RCHAR_T *stop, sopno startst, sopno stopst));
+static states step __P((struct re_guts *g, sopno start, sopno stop, states bef, int flag, RCHAR_T ch, states aft));
+#define        BOL     (1)
+#define        EOL     (BOL+1)
+#define        BOLEOL  (BOL+2)
+#define        NOTHING (BOL+3)
+#define        BOW     (BOL+4)
+#define        EOW     (BOL+5)
+#ifdef REDEBUG
+static void print __P((struct match *m, char *caption, states st, int ch, FILE *d));
+#endif
+#ifdef REDEBUG
+static void at __P((struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst));
+#endif
+#ifdef REDEBUG
+static char *pchar __P((int ch));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+
+#ifdef REDEBUG
+#define        SP(t, s, c)     print(m, t, s, c, stdout)
+#define        AT(t, p1, p2, s1, s2)   at(m, t, p1, p2, s1, s2)
+#define        NOTE(str)       { if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }
+#else
+#define        SP(t, s, c)     /* nothing */
+#define        AT(t, p1, p2, s1, s2)   /* nothing */
+#define        NOTE(s) /* nothing */
+#endif
+
+/*
+ - matcher - the actual matching engine
+ == static int matcher(register struct re_guts *g, RCHAR_T *string, \
+ ==    size_t nmatch, regmatch_t pmatch[], int eflags);
+ */
+static int                     /* 0 success, REG_NOMATCH failure */
+matcher(g, string, nmatch, pmatch, eflags)
+register struct re_guts *g;
+RCHAR_T *string;
+size_t nmatch;
+regmatch_t pmatch[];
+int eflags;
+{
+       register RCHAR_T *endp;
+       register size_t i;
+       struct match mv;
+       register struct match *m = &mv;
+       register RCHAR_T *dp;
+       register const sopno gf = g->firststate+1;      /* +1 for OEND */
+       register const sopno gl = g->laststate;
+       RCHAR_T *start;
+       RCHAR_T *stop;
+
+       /* simplify the situation where possible */
+       if (g->cflags&REG_NOSUB)
+               nmatch = 0;
+       if (eflags&REG_STARTEND) {
+               start = string + pmatch[0].rm_so;
+               stop = string + pmatch[0].rm_eo;
+       } else {
+               start = string;
+               stop = start + STRLEN(start);
+       }
+       if (stop < start)
+               return(REG_INVARG);
+
+       /* prescreening; this does wonders for this rather slow code */
+       if (g->must != NULL) {
+               for (dp = start; dp < stop; dp++)
+                       if (*dp == g->must[0] && (size_t)(stop - dp) >= g->mlen &&
+                               MEMCMP(dp, g->must, g->mlen) == 0)
+                               break;
+               if (dp == stop)         /* we didn't find g->must */
+                       return(REG_NOMATCH);
+       }
+
+       /* match struct setup */
+       m->g = g;
+       m->eflags = eflags;
+       m->pmatch = NULL;
+       m->lastpos = NULL;
+       m->offp = string;
+       m->beginp = start;
+       m->endp = stop;
+       STATESETUP(m, 4);
+       SETUP(m->st);
+       SETUP(m->fresh);
+       SETUP(m->tmp);
+       SETUP(m->empty);
+       CLEAR(m->empty);
+
+       /* this loop does only one repetition except for backrefs */
+       for (;;) {
+               endp = fast(m, start, stop, gf, gl);
+               if (endp == NULL) {             /* a miss */
+                       STATETEARDOWN(m);
+                       return(REG_NOMATCH);
+               }
+               if (nmatch == 0 && !g->backrefs)
+                       break;          /* no further info needed */
+
+               /* where? */
+               assert(m->coldp != NULL);
+               for (;;) {
+                       NOTE("finding start");
+                       endp = slow(m, m->coldp, stop, gf, gl);
+                       if (endp != NULL)
+                               break;
+                       assert(m->coldp < m->endp);
+                       m->coldp++;
+               }
+               if (nmatch == 1 && !g->backrefs)
+                       break;          /* no further info needed */
+
+               /* oh my, he wants the subexpressions... */
+               if (m->pmatch == NULL)
+                       m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
+                                                       sizeof(regmatch_t));
+               if (m->pmatch == NULL) {
+                       STATETEARDOWN(m);
+                       return(REG_ESPACE);
+               }
+               for (i = 1; i <= m->g->nsub; i++)
+                       m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
+               if (!g->backrefs && !(m->eflags&REG_BACKR)) {
+                       NOTE("dissecting");
+                       dp = dissect(m, m->coldp, endp, gf, gl);
+               } else {
+                       if (g->nplus > 0 && m->lastpos == NULL)
+                               m->lastpos = (RCHAR_T **)malloc((g->nplus+1) *
+                                                       sizeof(RCHAR_T *));
+                       if (g->nplus > 0 && m->lastpos == NULL) {
+                               free(m->pmatch);
+                               STATETEARDOWN(m);
+                               return(REG_ESPACE);
+                       }
+                       NOTE("backref dissect");
+                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+               }
+               if (dp != NULL)
+                       break;
+
+               /* uh-oh... we couldn't find a subexpression-level match */
+               assert(g->backrefs);    /* must be back references doing it */
+               assert(g->nplus == 0 || m->lastpos != NULL);
+               for (;;) {
+                       if (dp != NULL || endp <= m->coldp)
+                               break;          /* defeat */
+                       NOTE("backoff");
+                       endp = slow(m, m->coldp, endp-1, gf, gl);
+                       if (endp == NULL)
+                               break;          /* defeat */
+                       /* try it on a shorter possibility */
+#ifndef NDEBUG
+                       for (i = 1; i <= m->g->nsub; i++) {
+                               assert(m->pmatch[i].rm_so == -1);
+                               assert(m->pmatch[i].rm_eo == -1);
+                       }
+#endif
+                       NOTE("backoff dissect");
+                       dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+               }
+               assert(dp == NULL || dp == endp);
+               if (dp != NULL)         /* found a shorter one */
+                       break;
+
+               /* despite initial appearances, there is no match here */
+               NOTE("false alarm");
+               start = m->coldp + 1;   /* recycle starting later */
+               assert(start <= stop);
+       }
+
+       /* fill in the details if requested */
+       if (nmatch > 0) {
+               pmatch[0].rm_so = m->coldp - m->offp;
+               pmatch[0].rm_eo = endp - m->offp;
+       }
+       if (nmatch > 1) {
+               assert(m->pmatch != NULL);
+               for (i = 1; i < nmatch; i++)
+                       if (i <= m->g->nsub)
+                               pmatch[i] = m->pmatch[i];
+                       else {
+                               pmatch[i].rm_so = -1;
+                               pmatch[i].rm_eo = -1;
+                       }
+       }
+
+       if (m->pmatch != NULL)
+               free((char *)m->pmatch);
+       if (m->lastpos != NULL)
+               free((char *)m->lastpos);
+       STATETEARDOWN(m);
+       return(0);
+}
+
+/*
+ - dissect - figure out what matched what, no back references
+ == static RCHAR_T *dissect(register struct match *m, RCHAR_T *start, \
+ ==    RCHAR_T *stop, sopno startst, sopno stopst);
+ */
+static RCHAR_T *                       /* == stop (success) always */
+dissect(m, start, stop, startst, stopst)
+register struct match *m;
+RCHAR_T *start;
+RCHAR_T *stop;
+sopno startst;
+sopno stopst;
+{
+       register int i;
+       register sopno ss;      /* start sop of current subRE */
+       register sopno es;      /* end sop of current subRE */
+       register RCHAR_T *sp;   /* start of string matched by it */
+       register RCHAR_T *stp;  /* string matched by it cannot pass here */
+       register RCHAR_T *rest; /* start of rest of string */
+       register RCHAR_T *tail; /* string unmatched by rest of RE */
+       register sopno ssub;    /* start sop of subsubRE */
+       register sopno esub;    /* end sop of subsubRE */
+       register RCHAR_T *ssp;  /* start of string matched by subsubRE */
+       register RCHAR_T *sep;  /* end of string matched by subsubRE */
+       register RCHAR_T *oldssp;       /* previous ssp */
+       register RCHAR_T *dp;
+
+       AT("diss", start, stop, startst, stopst);
+       sp = start;
+       for (ss = startst; ss < stopst; ss = es) {
+               /* identify end of subRE */
+               es = ss;
+               switch (m->g->strip[es]) {
+               case OPLUS_:
+               case OQUEST_:
+                       es += m->g->stripdata[es];
+                       break;
+               case OCH_:
+                       while (m->g->strip[es] != O_CH)
+                               es += m->g->stripdata[es];
+                       break;
+               }
+               es++;
+
+               /* figure out what it matched */
+               switch (m->g->strip[ss]) {
+               case OEND:
+                       assert(nope);
+                       break;
+               case OCHAR:
+                       sp++;
+                       break;
+               case OBOL:
+               case OEOL:
+               case OBOW:
+               case OEOW:
+                       break;
+               case OANY:
+               case OANYOF:
+                       sp++;
+                       break;
+               case OBACK_:
+               case O_BACK:
+                       assert(nope);
+                       break;
+               /* cases where length of match is hard to find */
+               case OQUEST_:
+                       stp = stop;
+                       for (;;) {
+                               /* how long could this one be? */
+                               rest = slow(m, sp, stp, ss, es);
+                               assert(rest != NULL);   /* it did match */
+                               /* could the rest match the rest? */
+                               tail = slow(m, rest, stop, es, stopst);
+                               if (tail == stop)
+                                       break;          /* yes! */
+                               /* no -- try a shorter match for this one */
+                               stp = rest - 1;
+                               assert(stp >= sp);      /* it did work */
+                       }
+                       ssub = ss + 1;
+                       esub = es - 1;
+                       /* did innards match? */
+                       if (slow(m, sp, rest, ssub, esub) != NULL) {
+                               dp = dissect(m, sp, rest, ssub, esub);
+                               assert(dp == rest);
+                       } else          /* no */
+                               assert(sp == rest);
+                       sp = rest;
+                       break;
+               case OPLUS_:
+                       stp = stop;
+                       for (;;) {
+                               /* how long could this one be? */
+                               rest = slow(m, sp, stp, ss, es);
+                               assert(rest != NULL);   /* it did match */
+                               /* could the rest match the rest? */
+                               tail = slow(m, rest, stop, es, stopst);
+                               if (tail == stop)
+                                       break;          /* yes! */
+                               /* no -- try a shorter match for this one */
+                               stp = rest - 1;
+                               assert(stp >= sp);      /* it did work */
+                       }
+                       ssub = ss + 1;
+                       esub = es - 1;
+                       ssp = sp;
+                       oldssp = ssp;
+                       for (;;) {      /* find last match of innards */
+                               sep = slow(m, ssp, rest, ssub, esub);
+                               if (sep == NULL || sep == ssp)
+                                       break;  /* failed or matched null */
+                               oldssp = ssp;   /* on to next try */
+                               ssp = sep;
+                       }
+                       if (sep == NULL) {
+                               /* last successful match */
+                               sep = ssp;
+                               ssp = oldssp;
+                       }
+                       assert(sep == rest);    /* must exhaust substring */
+                       assert(slow(m, ssp, sep, ssub, esub) == rest);
+                       dp = dissect(m, ssp, sep, ssub, esub);
+                       assert(dp == sep);
+                       sp = rest;
+                       break;
+               case OCH_:
+                       stp = stop;
+                       for (;;) {
+                               /* how long could this one be? */
+                               rest = slow(m, sp, stp, ss, es);
+                               assert(rest != NULL);   /* it did match */
+                               /* could the rest match the rest? */
+                               tail = slow(m, rest, stop, es, stopst);
+                               if (tail == stop)
+                                       break;          /* yes! */
+                               /* no -- try a shorter match for this one */
+                               stp = rest - 1;
+                               assert(stp >= sp);      /* it did work */
+                       }
+                       ssub = ss + 1;
+                       esub = ss + m->g->stripdata[ss] - 1;
+                       assert(m->g->strip[esub] == OOR1);
+                       for (;;) {      /* find first matching branch */
+                               if (slow(m, sp, rest, ssub, esub) == rest)
+                                       break;  /* it matched all of it */
+                               /* that one missed, try next one */
+                               assert(m->g->strip[esub] == OOR1);
+                               esub++;
+                               assert(m->g->strip[esub] == OOR2);
+                               ssub = esub + 1;
+                               esub += m->g->stripdata[esub];
+                               if (m->g->strip[esub] == OOR2)
+                                       esub--;
+                               else
+                                       assert(m->g->strip[esub] == O_CH);
+                       }
+                       dp = dissect(m, sp, rest, ssub, esub);
+                       assert(dp == rest);
+                       sp = rest;
+                       break;
+               case O_PLUS:
+               case O_QUEST:
+               case OOR1:
+               case OOR2:
+               case O_CH:
+                       assert(nope);
+                       break;
+               case OLPAREN:
+                       i = m->g->stripdata[ss];
+                       assert(0 < i && i <= m->g->nsub);
+                       m->pmatch[i].rm_so = sp - m->offp;
+                       break;
+               case ORPAREN:
+                       i = m->g->stripdata[ss];
+                       assert(0 < i && i <= m->g->nsub);
+                       m->pmatch[i].rm_eo = sp - m->offp;
+                       break;
+               default:                /* uh oh */
+                       assert(nope);
+                       break;
+               }
+       }
+
+       assert(sp == stop);
+       return(sp);
+}
+
+/*
+ - backref - figure out what matched what, figuring in back references
+ == static RCHAR_T *backref(register struct match *m, RCHAR_T *start, \
+ ==    RCHAR_T *stop, sopno startst, sopno stopst, sopno lev);
+ */
+static RCHAR_T *                       /* == stop (success) or NULL (failure) */
+backref(m, start, stop, startst, stopst, lev)
+register struct match *m;
+RCHAR_T *start;
+RCHAR_T *stop;
+sopno startst;
+sopno stopst;
+sopno lev;                     /* PLUS nesting level */
+{
+       register int i;
+       register sopno ss;      /* start sop of current subRE */
+       register RCHAR_T *sp;   /* start of string matched by it */
+       register sopno ssub;    /* start sop of subsubRE */
+       register sopno esub;    /* end sop of subsubRE */
+       register RCHAR_T *ssp;  /* start of string matched by subsubRE */
+       register RCHAR_T *dp;
+       register size_t len;
+       register int hard;
+       register sop s;
+       register RCHAR_T d;
+       register regoff_t offsave;
+       register cset *cs;
+
+       AT("back", start, stop, startst, stopst);
+       sp = start;
+
+       /* get as far as we can with easy stuff */
+       hard = 0;
+       for (ss = startst; !hard && ss < stopst; ss++) {
+               s = m->g->strip[ss];
+               d = m->g->stripdata[ss];
+               switch (s) {
+               case OCHAR:
+                       if (sp == stop || *sp++ != d)
+                               return(NULL);
+                       break;
+               case OANY:
+                       if (sp == stop)
+                               return(NULL);
+                       sp++;
+                       break;
+               case OANYOF:
+                       cs = &m->g->sets[d];
+                       if (sp == stop || !CHIN(cs, *sp++))
+                               return(NULL);
+                       break;
+               case OBOL:
+                       if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+                                       (sp < m->endp && *(sp-1) == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case OEOL:
+                       if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+                                       (sp < m->endp && *sp == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case OBOW:
+                       if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+                                       (sp < m->endp && *(sp-1) == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) ||
+                                       (sp > m->beginp &&
+                                                       !ISWORD(*(sp-1))) ) &&
+                                       (sp < m->endp && ISWORD(*sp)) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case OEOW:
+                       if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+                                       (sp < m->endp && *sp == '\n' &&
+                                               (m->g->cflags&REG_NEWLINE)) ||
+                                       (sp < m->endp && !ISWORD(*sp)) ) &&
+                                       (sp > m->beginp && ISWORD(*(sp-1))) )
+                               { /* yes */ }
+                       else
+                               return(NULL);
+                       break;
+               case O_QUEST:
+                       break;
+               case OOR1:      /* matches null but needs to skip */
+                       ss++;
+                       s = m->g->strip[ss];
+                       d = m->g->stripdata[ss];
+                       do {
+                               assert(s == OOR2);
+                               ss += d;
+                               s = m->g->strip[ss];
+                               d = m->g->stripdata[ss];
+                       } while (s != O_CH);
+                       /* note that the ss++ gets us past the O_CH */
+                       break;
+               default:        /* have to make a choice */
+                       hard = 1;
+                       break;
+               }
+       }
+       if (!hard) {            /* that was it! */
+               if (sp != stop)
+                       return(NULL);
+               return(sp);
+       }
+       ss--;                   /* adjust for the for's final increment */
+
+       /* the hard stuff */
+       AT("hard", sp, stop, ss, stopst);
+       s = m->g->strip[ss];
+       d = m->g->stripdata[ss];
+       switch (s) {
+       case OBACK_:            /* the vilest depths */
+               i = d;
+               assert(0 < i && i <= m->g->nsub);
+               if (m->pmatch[i].rm_eo == -1)
+                       return(NULL);
+               assert(m->pmatch[i].rm_so != -1);
+               len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+               assert(stop - m->beginp >= len);
+               if (sp > stop - len)
+                       return(NULL);   /* not enough left to match */
+               ssp = m->offp + m->pmatch[i].rm_so;
+               if (memcmp(sp, ssp, len) != 0)
+                       return(NULL);
+               while (m->g->strip[ss] != O_BACK || m->g->stripdata[ss] != i)
+                       ss++;
+               return(backref(m, sp+len, stop, ss+1, stopst, lev));
+               break;
+       case OQUEST_:           /* to null or not */
+               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               if (dp != NULL)
+                       return(dp);     /* not */
+               return(backref(m, sp, stop, ss+d+1, stopst, lev));
+               break;
+       case OPLUS_:
+               assert(m->lastpos != NULL);
+               assert(lev+1 <= m->g->nplus);
+               m->lastpos[lev+1] = sp;
+               return(backref(m, sp, stop, ss+1, stopst, lev+1));
+               break;
+       case O_PLUS:
+               if (sp == m->lastpos[lev])      /* last pass matched null */
+                       return(backref(m, sp, stop, ss+1, stopst, lev-1));
+               /* try another pass */
+               m->lastpos[lev] = sp;
+               dp = backref(m, sp, stop, ss-d+1, stopst, lev);
+               if (dp == NULL)
+                       return(backref(m, sp, stop, ss+1, stopst, lev-1));
+               else
+                       return(dp);
+               break;
+       case OCH_:              /* find the right one, if any */
+               ssub = ss + 1;
+               esub = ss + d - 1;
+               assert(m->g->strip[esub] == OOR1);
+               for (;;) {      /* find first matching branch */
+                       dp = backref(m, sp, stop, ssub, esub, lev);
+                       if (dp != NULL)
+                               return(dp);
+                       /* that one missed, try next one */
+                       if (m->g->strip[esub] == O_CH)
+                               return(NULL);   /* there is none */
+                       esub++;
+                       assert(m->g->strip[esub] == OOR2);
+                       ssub = esub + 1;
+                       esub += m->g->stripdata[esub];
+                       if (m->g->strip[esub] == OOR2)
+                               esub--;
+                       else
+                               assert(m->g->strip[esub] == O_CH);
+               }
+               break;
+       case OLPAREN:           /* must undo assignment if rest fails */
+               i = d;
+               assert(0 < i && i <= m->g->nsub);
+               offsave = m->pmatch[i].rm_so;
+               m->pmatch[i].rm_so = sp - m->offp;
+               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               if (dp != NULL)
+                       return(dp);
+               m->pmatch[i].rm_so = offsave;
+               return(NULL);
+               break;
+       case ORPAREN:           /* must undo assignment if rest fails */
+               i = d;
+               assert(0 < i && i <= m->g->nsub);
+               offsave = m->pmatch[i].rm_eo;
+               m->pmatch[i].rm_eo = sp - m->offp;
+               dp = backref(m, sp, stop, ss+1, stopst, lev);
+               if (dp != NULL)
+                       return(dp);
+               m->pmatch[i].rm_eo = offsave;
+               return(NULL);
+               break;
+       default:                /* uh oh */
+               assert(nope);
+               break;
+       }
+
+       /* "can't happen" */
+       assert(nope);
+       /* NOTREACHED */
+       return NULL;
+}
+
+/*
+ - fast - step through the string at top speed
+ == static RCHAR_T *fast(register struct match *m, RCHAR_T *start, \
+ ==    RCHAR_T *stop, sopno startst, sopno stopst);
+ */
+static RCHAR_T *                       /* where tentative match ended, or NULL */
+fast(m, start, stop, startst, stopst)
+register struct match *m;
+RCHAR_T *start;
+RCHAR_T *stop;
+sopno startst;
+sopno stopst;
+{
+       register states st = m->st;
+       register states fresh = m->fresh;
+       register states tmp = m->tmp;
+       register RCHAR_T *p = start;
+       register RCHAR_T c = (start == m->beginp) ? OUT : *(start-1);
+       register RCHAR_T lastc; /* previous c */
+       register int flag;
+       register int i;
+       register RCHAR_T *coldp;        /* last p after which no match was underway */
+
+       CLEAR(st);
+       SET1(st, startst);
+       st = step(m->g, startst, stopst, st, NOTHING, OUT, st);
+       ASSIGN(fresh, st);
+       SP("start", st, *p);
+       coldp = NULL;
+       for (;;) {
+               /* next character */
+               lastc = c;
+               c = (p == m->endp) ? OUT : *p;
+               if (EQ(st, fresh))
+                       coldp = p;
+
+               /* is there an EOL and/or BOL between lastc and c? */
+               flag = 0;
+               i = 0;
+               if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+                       flag = BOL;
+                       i = m->g->nbol;
+               }
+               if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+                       flag = (flag == BOL) ? BOLEOL : EOL;
+                       i += m->g->neol;
+               }
+               if (i != 0) {
+                       for (; i > 0; i--)
+                               st = step(m->g, startst, stopst, st, flag, OUT, st);
+                       SP("boleol", st, c);
+               }
+
+               /* how about a word boundary? */
+               if ( (flag == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+                                       (c != OUT && ISWORD(c)) ) {
+                       flag = BOW;
+               }
+               if ( (lastc != OUT && ISWORD(lastc)) &&
+                               (flag == EOL || (c != OUT && !ISWORD(c))) ) {
+                       flag = EOW;
+               }
+               if (flag == BOW || flag == EOW) {
+                       st = step(m->g, startst, stopst, st, flag, OUT, st);
+                       SP("boweow", st, c);
+               }
+
+               /* are we done? */
+               if (ISSET(st, stopst) || p == stop)
+                       break;          /* NOTE BREAK OUT */
+
+               /* no, we must deal with this character */
+               ASSIGN(tmp, st);
+               ASSIGN(st, fresh);
+               assert(c != OUT);
+               st = step(m->g, startst, stopst, tmp, 0, c, st);
+               SP("aft", st, c);
+               assert(EQ(step(m->g, startst, stopst, st, NOTHING, OUT, st), st));
+               p++;
+       }
+
+       assert(coldp != NULL);
+       m->coldp = coldp;
+       if (ISSET(st, stopst))
+               return(p+1);
+       else
+               return(NULL);
+}
+
+/*
+ - slow - step through the string more deliberately
+ == static RCHAR_T *slow(register struct match *m, RCHAR_T *start, \
+ ==    RCHAR_T *stop, sopno startst, sopno stopst);
+ */
+static RCHAR_T *                       /* where it ended */
+slow(m, start, stop, startst, stopst)
+register struct match *m;
+RCHAR_T *start;
+RCHAR_T *stop;
+sopno startst;
+sopno stopst;
+{
+       register states st = m->st;
+       register states empty = m->empty;
+       register states tmp = m->tmp;
+       register RCHAR_T *p = start;
+       register RCHAR_T c = (start == m->beginp) ? OUT : *(start-1);
+       register RCHAR_T lastc; /* previous c */
+       register int flag;
+       register int i;
+       register RCHAR_T *matchp;       /* last p at which a match ended */
+
+       AT("slow", start, stop, startst, stopst);
+       CLEAR(st);
+       SET1(st, startst);
+       SP("sstart", st, *p);
+       st = step(m->g, startst, stopst, st, NOTHING, OUT, st);
+       matchp = NULL;
+       for (;;) {
+               /* next character */
+               lastc = c;
+               c = (p == m->endp) ? OUT : *p;
+
+               /* is there an EOL and/or BOL between lastc and c? */
+               flag = 0;
+               i = 0;
+               if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+                       flag = BOL;
+                       i = m->g->nbol;
+               }
+               if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+                               (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+                       flag = (flag == BOL) ? BOLEOL : EOL;
+                       i += m->g->neol;
+               }
+               if (i != 0) {
+                       for (; i > 0; i--)
+                               st = step(m->g, startst, stopst, st, flag, OUT, st);
+                       SP("sboleol", st, c);
+               }
+
+               /* how about a word boundary? */
+               if ( (flag == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+                                       (c != OUT && ISWORD(c)) ) {
+                       flag = BOW;
+               }
+               if ( (lastc != OUT && ISWORD(lastc)) &&
+                               (flag == EOL || (c != OUT && !ISWORD(c))) ) {
+                       flag = EOW;
+               }
+               if (flag == BOW || flag == EOW) {
+                       st = step(m->g, startst, stopst, st, flag, OUT, st);
+                       SP("sboweow", st, c);
+               }
+
+               /* are we done? */
+               if (ISSET(st, stopst))
+                       matchp = p;
+               if (EQ(st, empty) || p == stop)
+                       break;          /* NOTE BREAK OUT */
+
+               /* no, we must deal with this character */
+               ASSIGN(tmp, st);
+               ASSIGN(st, empty);
+               assert(c != OUT);
+               st = step(m->g, startst, stopst, tmp, 0, c, st);
+               SP("saft", st, c);
+               assert(EQ(step(m->g, startst, stopst, st, NOTHING, OUT, st), st));
+               p++;
+       }
+
+       return(matchp);
+}
+
+
+/*
+ - step - map set of states reachable before char to set reachable after
+ == static states step(register struct re_guts *g, sopno start, sopno stop, \
+ ==    register states bef, int flag, RCHAR_T ch, register states aft);
+ == #define    BOL     (1)
+ == #define    EOL     (BOL+1)
+ == #define    BOLEOL  (BOL+2)
+ == #define    NOTHING (BOL+3)
+ == #define    BOW     (BOL+4)
+ == #define    EOW     (BOL+5)
+ */
+static states
+step(g, start, stop, bef, flag, ch, aft)
+register struct re_guts *g;
+sopno start;                   /* start state within strip */
+sopno stop;                    /* state after stop state within strip */
+register states bef;           /* states reachable before */
+int flag;                      /* NONCHAR flag */
+RCHAR_T ch;                    /* character code */
+register states aft;           /* states already known reachable after */
+{
+       register cset *cs;
+       register sop s;
+       register RCHAR_T d;
+       register sopno pc;
+       register onestate here;         /* note, macros know this name */
+       register sopno look;
+       register int i;
+
+       for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
+               s = g->strip[pc];
+               d = g->stripdata[pc];
+               switch (s) {
+               case OEND:
+                       assert(pc == stop-1);
+                       break;
+               case OCHAR:
+                       /* only characters can match */
+                       assert(!flag || ch != d);
+                       if (ch == d)
+                               FWD(aft, bef, 1);
+                       break;
+               case OBOL:
+                       if (flag == BOL || flag == BOLEOL)
+                               FWD(aft, bef, 1);
+                       break;
+               case OEOL:
+                       if (flag == EOL || flag == BOLEOL)
+                               FWD(aft, bef, 1);
+                       break;
+               case OBOW:
+                       if (flag == BOW)
+                               FWD(aft, bef, 1);
+                       break;
+               case OEOW:
+                       if (flag == EOW)
+                               FWD(aft, bef, 1);
+                       break;
+               case OANY:
+                       if (!flag)
+                               FWD(aft, bef, 1);
+                       break;
+               case OANYOF:
+                       cs = &g->sets[d];
+                       if (!flag && CHIN(cs, ch))
+                               FWD(aft, bef, 1);
+                       break;
+               case OBACK_:            /* ignored here */
+               case O_BACK:
+                       FWD(aft, aft, 1);
+                       break;
+               case OPLUS_:            /* forward, this is just an empty */
+                       FWD(aft, aft, 1);
+                       break;
+               case O_PLUS:            /* both forward and back */
+                       FWD(aft, aft, 1);
+                       i = ISSETBACK(aft, d);
+                       BACK(aft, aft, d);
+                       if (!i && ISSETBACK(aft, d)) {
+                               /* oho, must reconsider loop body */
+                               pc -= d + 1;
+                               INIT(here, pc);
+                       }
+                       break;
+               case OQUEST_:           /* two branches, both forward */
+                       FWD(aft, aft, 1);
+                       FWD(aft, aft, d);
+                       break;
+               case O_QUEST:           /* just an empty */
+                       FWD(aft, aft, 1);
+                       break;
+               case OLPAREN:           /* not significant here */
+               case ORPAREN:
+                       FWD(aft, aft, 1);
+                       break;
+               case OCH_:              /* mark the first two branches */
+                       FWD(aft, aft, 1);
+                       assert(OP(g->strip[pc+d]) == OOR2);
+                       FWD(aft, aft, d);
+                       break;
+               case OOR1:              /* done a branch, find the O_CH */
+                       if (ISSTATEIN(aft, here)) {
+                               for (look = 1; /**/; look += d) {
+                                       s = g->strip[pc+look];
+                                       d = g->stripdata[pc+look];
+                                       if (s == O_CH)
+                                               break;
+                                       assert(s == OOR2);
+                               }
+                               FWD(aft, aft, look);
+                       }
+                       break;
+               case OOR2:              /* propagate OCH_'s marking */
+                       FWD(aft, aft, 1);
+                       if (g->strip[pc+d] != O_CH) {
+                               assert(g->strip[pc+d] == OOR2);
+                               FWD(aft, aft, d);
+                       }
+                       break;
+               case O_CH:              /* just empty */
+                       FWD(aft, aft, 1);
+                       break;
+               default:                /* ooooops... */
+                       assert(nope);
+                       break;
+               }
+       }
+
+       return(aft);
+}
+
+#ifdef REDEBUG
+/*
+ - print - print a set of states
+ == #ifdef REDEBUG
+ == static void print(struct match *m, char *caption, states st, \
+ ==    int ch, FILE *d);
+ == #endif
+ */
+static void
+print(m, caption, st, ch, d)
+struct match *m;
+char *caption;
+states st;
+int ch;
+FILE *d;
+{
+       register struct re_guts *g = m->g;
+       register int i;
+       register int first = 1;
+
+       if (!(m->eflags&REG_TRACE))
+               return;
+
+       fprintf(d, "%s", caption);
+       if (ch != '\0')
+               fprintf(d, " %s", pchar(ch));
+       for (i = 0; i < g->nstates; i++)
+               if (ISSET(st, i)) {
+                       fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
+                       first = 0;
+               }
+       fprintf(d, "\n");
+}
+
+/* 
+ - at - print current situation
+ == #ifdef REDEBUG
+ == static void at(struct match *m, char *title, char *start, char *stop, \
+ ==                                            sopno startst, sopno stopst);
+ == #endif
+ */
+static void
+at(m, title, start, stop, startst, stopst)
+struct match *m;
+char *title;
+char *start;
+char *stop;
+sopno startst;
+sopno stopst;
+{
+       if (!(m->eflags&REG_TRACE))
+               return;
+
+       printf("%s %s-", title, pchar(*start));
+       printf("%s ", pchar(*stop));
+       printf("%ld-%ld\n", (long)startst, (long)stopst);
+}
+
+#ifndef PCHARDONE
+#define        PCHARDONE       /* never again */
+/*
+ - pchar - make a character printable
+ == #ifdef REDEBUG
+ == static char *pchar(int ch);
+ == #endif
+ *
+ * Is this identical to regchar() over in debug.c?  Well, yes.  But a
+ * duplicate here avoids having a debugging-capable regexec.o tied to
+ * a matching debug.o, and this is convenient.  It all disappears in
+ * the non-debug compilation anyway, so it doesn't matter much.
+ */
+static char *                  /* -> representation */
+pchar(ch)
+int ch;
+{
+       static char pbuf[10];
+
+       if (isprint(ch) || ch == ' ')
+               sprintf(pbuf, "%c", ch);
+       else
+               sprintf(pbuf, "\\%o", ch);
+       return(pbuf);
+}
+#endif
+#endif
+
+#undef matcher
+#undef fast
+#undef slow
+#undef dissect
+#undef backref
+#undef step
+#undef print
+#undef at
+#undef match
diff --git a/dist/nvi/regex/re_format.7 b/dist/nvi/regex/re_format.7
new file mode 100644 (file)
index 0000000..61d1aea
--- /dev/null
@@ -0,0 +1,271 @@
+.\"    $NetBSD: re_format.7,v 1.1.1.2 2008/05/18 14:31:37 aymeric Exp $
+.\"
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer of the University of Toronto.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)re_format.7 8.2 (Berkeley) 3/16/94
+.\"
+.TH RE_FORMAT 7 "March 16, 1994"
+.SH NAME
+re_format \- POSIX 1003.2 regular expressions
+.SH DESCRIPTION
+Regular expressions (``RE''s),
+as defined in POSIX 1003.2, come in two forms:
+modern REs (roughly those of
+.IR egrep ;
+1003.2 calls these ``extended'' REs)
+and obsolete REs (roughly those of
+.IR ed ;
+1003.2 ``basic'' REs).
+Obsolete REs mostly exist for backward compatibility in some old programs;
+they will be discussed at the end.
+1003.2 leaves some aspects of RE syntax and semantics open;
+`\(dg' marks decisions on these aspects that
+may not be fully portable to other 1003.2 implementations.
+.PP
+A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR,
+separated by `|'.
+It matches anything that matches one of the branches.
+.PP
+A branch is one\(dg or more \fIpieces\fR, concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.PP
+A piece is an \fIatom\fR possibly followed
+by a single\(dg `*', `+', `?', or \fIbound\fR.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a sequence of 0 or 1 matches of the atom.
+.PP
+A \fIbound\fR is `{' followed by an unsigned decimal integer,
+possibly followed by `,'
+possibly followed by another unsigned decimal integer,
+always followed by `}'.
+The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer \fIi\fR
+and no comma matches
+a sequence of exactly \fIi\fR matches of the atom.
+An atom followed by a bound
+containing one integer \fIi\fR and a comma matches
+a sequence of \fIi\fR or more matches of the atom.
+An atom followed by a bound
+containing two integers \fIi\fR and \fIj\fR matches
+a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom.
+.PP
+An atom is a regular expression enclosed in `()' (matching a match for the
+regular expression),
+an empty set of `()' (matching the null string)\(dg,
+a \fIbracket expression\fR (see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of a line), `$' (matching the null string at the
+end of a line), a `\e' followed by one of the characters
+`^.[$()|*+?{\e'
+(matching that character taken as an ordinary character),
+a `\e' followed by any other character\(dg
+(matching that character taken as an ordinary character,
+as if the `\e' had not been present\(dg),
+or a single character with no other significance (matching that character).
+A `{' followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dg.
+It is illegal to end an RE with `\e'.
+.PP
+A \fIbracket expression\fR is a list of characters enclosed in `[]'.
+It normally matches any single character from the list (but see below).
+If the list begins with `^',
+it matches any single character
+(but see below) \fInot\fR from the rest of the list.
+If two characters in the list are separated by `\-', this is shorthand
+for the full \fIrange\fR of characters between those two (inclusive) in the
+collating sequence,
+e.g. `[0-9]' in ASCII matches any decimal digit.
+It is illegal\(dg for two ranges to share an
+endpoint, e.g. `a-c-e'.
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.PP
+To include a literal `]' in the list, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character,
+or the second endpoint of a range.
+To use a literal `\-' as the first endpoint of a range,
+enclose it in `[.' and `.]' to make it a collating element (see below).
+With the exception of these and some combinations using `[' (see next
+paragraphs), all other special characters, including `\e', lose their
+special significance within a bracket expression.
+.PP
+Within a bracket expression, a collating element (a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in `[.' and `.]' stands for the
+sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element 
+can thus match more than one character,
+e.g. if the collating sequence includes a `ch' collating element,
+then the RE `[[.ch.]]*c' matches the first five characters
+of `chchcc'.
+.PP
+Within a bracket expression, a collating element enclosed in `[=' and
+`=]' is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were `[.' and `.]'.)
+For example, if o and \o'o^' are the members of an equivalence class,
+then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous.
+An equivalence class may not\(dg be an endpoint
+of a range.
+.PP
+Within a bracket expression, the name of a \fIcharacter class\fR enclosed
+in `[:' and `:]' stands for the list of all characters belonging to that
+class.
+Standard character class names are:
+.PP
+.RS
+.nf
+.ta 3c 6c 9c
+alnum  digit   punct
+alpha  graph   space
+blank  lower   upper
+cntrl  print   xdigit
+.fi
+.RE
+.PP
+These stand for the character classes defined in
+.IR ctype (3).
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.PP
+There are two special cases\(dg of bracket expressions:
+the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at
+the beginning and end of a word respectively.
+A word is defined as a sequence of
+word characters
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.I alnum
+character (as defined by
+.IR ctype (3))
+or an underscore.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.PP
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+`bb*' matches the three middle characters of `abbbc',
+`(wee|week)(knights|nights)' matches all ten characters of `weeknights',
+when `(.*).*' is matched against `abc' the parenthesized subexpression
+matches all three characters, and
+when `(a*)*' is matched against `bc' both the whole RE and the parenthesized
+subexpression match the null string.
+.PP
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+e.g. `x' becomes `[xX]'.
+When it appears inside a bracket expression, all case counterparts
+of it are added to the bracket expression, so that (e.g.) `[x]'
+becomes `[xX]' and `[^x]' becomes `[^xX]'.
+.PP
+No particular limit is imposed on the length of REs\(dg.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.PP
+Obsolete (``basic'') regular expressions differ in several respects.
+`|', `+', and `?' are ordinary characters and there is no equivalent
+for their functionality.
+The delimiters for bounds are `\e{' and `\e}',
+with `{' and `}' by themselves ordinary characters.
+The parentheses for nested subexpressions are `\e(' and `\e)',
+with `(' and `)' by themselves ordinary characters.
+`^' is an ordinary character except at the beginning of the
+RE or\(dg the beginning of a parenthesized subexpression,
+`$' is an ordinary character except at the end of the
+RE or\(dg the end of a parenthesized subexpression,
+and `*' is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading `^').
+Finally, there is one new type of atom, a \fIback reference\fR:
+`\e' followed by a non-zero decimal digit \fId\fR
+matches the same sequence of characters
+matched by the \fId\fRth parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'.
+.SH SEE ALSO
+regex(3)
+.PP
+POSIX 1003.2, section 2.8 (Regular Expression Notation).
+.SH BUGS
+Having two kinds of REs is a botch.
+.PP
+The current 1003.2 spec says that `)' is an ordinary character in
+the absence of an unmatched `(';
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.PP
+Back references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?).
+Avoid using them.
+.PP
+1003.2's specification of case-independent matching is vague.
+The ``one case implies all cases'' definition given above
+is current consensus among implementors as to the right interpretation.
+.PP
+The syntax for word boundaries is incredibly ugly.
diff --git a/dist/nvi/regex/regcomp.c b/dist/nvi/regex/regcomp.c
new file mode 100644 (file)
index 0000000..7d19868
--- /dev/null
@@ -0,0 +1,1736 @@
+/*     $NetBSD: regcomp.c,v 1.7 2011/11/19 17:45:11 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regcomp.c   8.4 (Berkeley) 3/19/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regcomp.c  8.4 (Berkeley) 3/19/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+#include "cclass.h"
+#include "cname.h"
+
+/*
+ * parse structure, passed up and down to avoid global variables and
+ * other clumsinesses
+ */
+struct parse {
+       RCHAR_T *next;          /* next character in RE */
+       RCHAR_T *end;           /* end of string (-> NUL normally) */
+       int error;              /* has an error been seen? */
+       sop *strip;             /* malloced strip */
+       RCHAR_T *stripdata;     /* malloced stripdata */
+       sopno ssize;            /* malloced strip size (allocated) */
+       sopno slen;             /* malloced strip length (used) */
+       int ncsalloc;           /* number of csets allocated */
+       struct re_guts *g;
+#      define  NPAREN  10      /* we need to remember () 1-9 for back refs */
+       sopno pbegin[NPAREN];   /* -> ( ([0] unused) */
+       sopno pend[NPAREN];     /* -> ) ([0] unused) */
+};
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regcomp.c === */
+static void p_ere __P((struct parse *p, int stop, size_t reclimit));
+static void p_ere_exp __P((struct parse *p, size_t reclimit));
+static void p_str __P((struct parse *p));
+static void p_bre __P((struct parse *p, int end1, int end2, size_t reclimit));
+static int p_simp_re __P((struct parse *p, int starordinary, size_t reclimit));
+static int p_count __P((struct parse *p));
+static void p_bracket __P((struct parse *p));
+static void p_b_term __P((struct parse *p, cset *cs));
+static void p_b_cclass __P((struct parse *p, cset *cs));
+static void p_b_eclass __P((struct parse *p, cset *cs));
+static char p_b_symbol __P((struct parse *p));
+static char p_b_coll_elem __P((struct parse *p, int endc));
+static char othercase __P((int ch));
+static void bothcases __P((struct parse *p, int ch));
+static void ordinary __P((struct parse *p, int ch));
+static void nonnewline __P((struct parse *p));
+static void repeat __P((struct parse *p, sopno start, int from, int to, size_t reclimit));
+static int seterr __P((struct parse *p, int e));
+static cset *allocset __P((struct parse *p));
+static void freeset __P((struct parse *p, cset *cs));
+static int freezeset __P((struct parse *p, cset *cs));
+static int firstch __P((struct parse *p, cset *cs));
+static int nch __P((struct parse *p, cset *cs));
+static void mcadd __P((struct parse *p, cset *cs, const char *cp));
+#ifdef notdef
+static void mcsub __P((cset *cs, char *cp));
+static int mcin __P((cset *cs, char *cp));
+static char *mcfind __P((cset *cs, char *cp));
+#endif
+static void mcinvert __P((struct parse *p, cset *cs));
+static void mccase __P((struct parse *p, cset *cs));
+#ifdef notdef
+static int isinsets __P((struct re_guts *g, int c));
+static int samesets __P((struct re_guts *g, int c1, int c2));
+#endif
+static void categorize __P((struct parse *p, struct re_guts *g));
+static sopno dupl __P((struct parse *p, sopno start, sopno finish));
+static void doemit __P((struct parse *p, sop op, size_t opnd));
+static void doinsert __P((struct parse *p, sop op, size_t opnd, sopno pos));
+static void dofwd __P((struct parse *p, sopno pos, sop value));
+static int enlarge __P((struct parse *p, sopno size));
+static void stripsnug __P((struct parse *p, struct re_guts *g));
+static void findmust __P((struct parse *p, struct re_guts *g));
+static sopno pluscount __P((struct parse *p, struct re_guts *g));
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+
+static RCHAR_T nuls[10];               /* place to point scanner in event of error */
+
+/*
+ * macros for use with parse structure
+ * BEWARE:  these know that the parse structure is named `p' !!!
+ */
+#define        PEEK()  (*p->next)
+#define        PEEK2() (*(p->next+1))
+#define        MORE()  (p->next < p->end)
+#define        MORE2() (p->next+1 < p->end)
+#define        SEE(c)  (MORE() && PEEK() == (c))
+#define        SEETWO(a, b)    (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
+#define        EAT(c)  ((SEE(c)) ? (NEXT(), 1) : 0)
+#define        EATTWO(a, b)    ((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
+#define        NEXT()  (p->next++)
+#define        NEXT2() (p->next += 2)
+#define        NEXTn(n)        (p->next += (n))
+#define        GETNEXT()       (*p->next++)
+#define        SETERROR(e)     seterr(p, (e))
+#define        REQUIRE(co, e)  ((co) || SETERROR(e))
+#define        MUSTSEE(c, e)   (REQUIRE(MORE() && PEEK() == (c), e))
+#define        MUSTEAT(c, e)   (REQUIRE(MORE() && GETNEXT() == (c), e))
+#define        MUSTNOTSEE(c, e)        (REQUIRE(!MORE() || PEEK() != (c), e))
+#define        EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd))
+#define        INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
+#define        AHEAD(pos)              dofwd(p, pos, HERE()-(pos))
+#define        ASTERN(sop, pos)        EMIT(sop, HERE()-pos)
+#define        HERE()          (p->slen)
+#define        THERE()         (p->slen - 1)
+#define        THERETHERE()    (p->slen - 2)
+#define        DROP(n) (p->slen -= (n))
+
+#ifndef NDEBUG
+static int never = 0;          /* for use in asserts; shuts lint up */
+#else
+#define        never   0               /* some <assert.h>s have bugs too */
+#endif
+
+#define        MEMLIMIT        0x8000000
+#define MEMSIZE(p) \
+       ((p)->ncsalloc / CHAR_BIT * (p)->g->csetsize + \
+       (p)->ncsalloc * sizeof(cset) + \
+       (p)->ssize * sizeof(sop))
+#define        RECLIMIT        256
+
+/*
+ - regcomp - interface for parser and compilation
+ = extern int regcomp(regex_t *, const RCHAR_T *, int);
+ = #define     REG_BASIC       0000
+ = #define     REG_EXTENDED    0001
+ = #define     REG_ICASE       0002
+ = #define     REG_NOSUB       0004
+ = #define     REG_NEWLINE     0010
+ = #define     REG_NOSPEC      0020
+ = #define     REG_PEND        0040
+ = #define     REG_DUMP        0200
+ */
+int                            /* 0 success, otherwise REG_something */
+regcomp(regex_t *preg, const RCHAR_T *pattern, int cflags)
+{
+       struct parse pa;
+       register struct re_guts *g;
+       register struct parse *p = &pa;
+       register int i;
+       register size_t len;
+#ifdef REDEBUG
+#      define  GOODFLAGS(f)    (f)
+#else
+#      define  GOODFLAGS(f)    ((f)&~REG_DUMP)
+#endif
+
+       cflags = GOODFLAGS(cflags);
+       if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
+               return(REG_INVARG);
+
+       if (cflags&REG_PEND) {
+               if (preg->re_endp < pattern)
+                       return(REG_INVARG);
+               len = preg->re_endp - pattern;
+       } else
+               len = STRLEN(pattern);
+
+       /* do the mallocs early so failure handling is easy */
+       g = (struct re_guts *)malloc(sizeof(struct re_guts) +
+                                                       (NC-1)*sizeof(cat_t));
+       if (g == NULL)
+               return(REG_ESPACE);
+       p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
+       p->strip = (sop *)malloc(p->ssize * sizeof(sop));
+       if (p->strip == NULL) {
+               free((char *)g);
+               return(REG_ESPACE);
+       }
+       p->stripdata = (RCHAR_T *)malloc(p->ssize * sizeof(RCHAR_T));
+       if (p->stripdata == NULL) {
+               free((char *)p->strip);
+               free((char *)g);
+               return(REG_ESPACE);
+       }
+       p->slen = 0;
+
+       /* set things up */
+       p->g = g;
+       p->next = (RCHAR_T *)__UNCONST(pattern);        /* convenience; we do not modify it */
+       p->end = p->next + len;
+       p->error = 0;
+       p->ncsalloc = 0;
+       for (i = 0; i < NPAREN; i++) {
+               p->pbegin[i] = 0;
+               p->pend[i] = 0;
+       }
+       g->csetsize = NC;
+       g->sets = NULL;
+       g->setbits = NULL;
+       g->ncsets = 0;
+       g->cflags = cflags;
+       g->iflags = 0;
+       g->nbol = 0;
+       g->neol = 0;
+       g->must = NULL;
+       g->mlen = 0;
+       g->nsub = 0;
+#if 0
+       g->ncategories = 1;     /* category 0 is "everything else" */
+       g->categories = &g->catspace[-(CHAR_MIN)];
+       (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));
+#endif
+       g->backrefs = 0;
+
+       /* do it */
+       EMIT(OEND, 0);
+       g->firststate = THERE();
+       if (cflags&REG_EXTENDED)
+               p_ere(p, OUT, 0);
+       else if (cflags&REG_NOSPEC)
+               p_str(p);
+       else
+               p_bre(p, OUT, OUT, 0);
+       EMIT(OEND, 0);
+       g->laststate = THERE();
+
+       /* tidy up loose ends and fill things in */
+       categorize(p, g);
+       stripsnug(p, g);
+       findmust(p, g);
+       g->nplus = pluscount(p, g);
+       g->magic = MAGIC2;
+       preg->re_nsub = g->nsub;
+       preg->re_g = g;
+       preg->re_magic = MAGIC1;
+#ifndef REDEBUG
+       /* not debugging, so can't rely on the assert() in regexec() */
+       if (g->iflags&BAD)
+               SETERROR(REG_ASSERT);
+#endif
+
+       /* win or lose, we're done */
+       if (p->error != 0)      /* lose */
+               regfree(preg);
+       return(p->error);
+}
+
+/*
+ - p_ere - ERE parser top level, concatenation and alternation
+ == static void p_ere(register struct parse *p, int stop, size_t reclimit);
+ */
+static void
+p_ere(register struct parse *p, int stop, size_t reclimit)
+                         
+                               /* character this ERE should end at */
+{
+       register char c;
+       register sopno prevback = 0;
+       register sopno prevfwd = 0;
+       register sopno conc;
+       register int first = 1;         /* is this the first alternative? */
+
+       if (reclimit++ > RECLIMIT || p->error == REG_ESPACE) {
+               p->error = REG_ESPACE;
+               return;
+       }
+
+       for (;;) {
+               /* do a bunch of concatenated expressions */
+               conc = HERE();
+               while (MORE() && (c = PEEK()) != '|' && c != stop)
+                       p_ere_exp(p, reclimit);
+               (void)REQUIRE(HERE() != conc, REG_EMPTY);       /* require nonempty */
+
+               if (!EAT('|'))
+                       break;          /* NOTE BREAK OUT */
+
+               if (first) {
+                       INSERT(OCH_, conc);     /* offset is wrong */
+                       prevfwd = conc;
+                       prevback = conc;
+                       first = 0;
+               }
+               ASTERN(OOR1, prevback);
+               prevback = THERE();
+               AHEAD(prevfwd);                 /* fix previous offset */
+               prevfwd = HERE();
+               EMIT(OOR2, 0);                  /* offset is very wrong */
+       }
+
+       if (!first) {           /* tail-end fixups */
+               AHEAD(prevfwd);
+               ASTERN(O_CH, prevback);
+       }
+
+       assert(!MORE() || SEE(stop));
+}
+
+/*
+ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
+ == static void p_ere_exp(register struct parse *p);
+ */
+static void
+p_ere_exp(register struct parse *p, size_t reclimit)
+{
+       register char c;
+       register sopno pos;
+       register int count;
+       register int count2;
+       register sopno subno;
+       int wascaret = 0;
+
+       assert(MORE());         /* caller should have ensured this */
+       c = GETNEXT();
+
+       pos = HERE();
+       switch (c) {
+       case '(':
+               (void)REQUIRE(MORE(), REG_EPAREN);
+               p->g->nsub++;
+               subno = p->g->nsub;
+               if (subno < NPAREN)
+                       p->pbegin[subno] = HERE();
+               EMIT(OLPAREN, subno);
+               if (!SEE(')'))
+                       p_ere(p, ')', reclimit);
+               if (subno < NPAREN) {
+                       p->pend[subno] = HERE();
+                       assert(p->pend[subno] != 0);
+               }
+               EMIT(ORPAREN, subno);
+               (void)MUSTEAT(')', REG_EPAREN);
+               break;
+#ifndef POSIX_MISTAKE
+       case ')':               /* happens only if no current unmatched ( */
+               /*
+                * You may ask, why the ifndef?  Because I didn't notice
+                * this until slightly too late for 1003.2, and none of the
+                * other 1003.2 regular-expression reviewers noticed it at
+                * all.  So an unmatched ) is legal POSIX, at least until
+                * we can get it fixed.
+                */
+               SETERROR(REG_EPAREN);
+               break;
+#endif
+       case '^':
+               EMIT(OBOL, 0);
+               p->g->iflags |= USEBOL;
+               p->g->nbol++;
+               wascaret = 1;
+               break;
+       case '$':
+               EMIT(OEOL, 0);
+               p->g->iflags |= USEEOL;
+               p->g->neol++;
+               break;
+       case '|':
+               SETERROR(REG_EMPTY);
+               break;
+       case '*':
+       case '+':
+       case '?':
+               SETERROR(REG_BADRPT);
+               break;
+       case '.':
+               if (p->g->cflags&REG_NEWLINE)
+                       nonnewline(p);
+               else
+                       EMIT(OANY, 0);
+               break;
+       case '[':
+               p_bracket(p);
+               break;
+       case '\\':
+               (void)REQUIRE(MORE(), REG_EESCAPE);
+               c = GETNEXT();
+               ordinary(p, c);
+               break;
+       case '{':               /* okay as ordinary except if digit follows */
+               (void)REQUIRE(!MORE() || !ISDIGIT((UCHAR_T)PEEK()), REG_BADRPT);
+               /* FALLTHROUGH */
+       default:
+               ordinary(p, c);
+               break;
+       }
+
+       if (!MORE())
+               return;
+       c = PEEK();
+       /* we call { a repetition if followed by a digit */
+       if (!( c == '*' || c == '+' || c == '?' ||
+                               (c == '{' && MORE2() && ISDIGIT((UCHAR_T)PEEK2())) ))
+               return;         /* no repetition, we're done */
+       NEXT();
+
+       (void)REQUIRE(!wascaret, REG_BADRPT);
+       switch (c) {
+       case '*':       /* implemented as +? */
+               /* this case does not require the (y|) trick, noKLUDGE */
+               INSERT(OPLUS_, pos);
+               ASTERN(O_PLUS, pos);
+               INSERT(OQUEST_, pos);
+               ASTERN(O_QUEST, pos);
+               break;
+       case '+':
+               INSERT(OPLUS_, pos);
+               ASTERN(O_PLUS, pos);
+               break;
+       case '?':
+               /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+               INSERT(OCH_, pos);              /* offset slightly wrong */
+               ASTERN(OOR1, pos);              /* this one's right */
+               AHEAD(pos);                     /* fix the OCH_ */
+               EMIT(OOR2, 0);                  /* offset very wrong... */
+               AHEAD(THERE());                 /* ...so fix it */
+               ASTERN(O_CH, THERETHERE());
+               break;
+       case '{':
+               count = p_count(p);
+               if (EAT(',')) {
+                       if (ISDIGIT((UCHAR_T)PEEK())) {
+                               count2 = p_count(p);
+                               (void)REQUIRE(count <= count2, REG_BADBR);
+                       } else          /* single number with comma */
+                               count2 = INFINITY;
+               } else          /* just a single number */
+                       count2 = count;
+               repeat(p, pos, count, count2, 0);
+               if (!EAT('}')) {        /* error heuristics */
+                       while (MORE() && PEEK() != '}')
+                               NEXT();
+                       (void)REQUIRE(MORE(), REG_EBRACE);
+                       SETERROR(REG_BADBR);
+               }
+               break;
+       }
+
+       if (!MORE())
+               return;
+       c = PEEK();
+       if (!( c == '*' || c == '+' || c == '?' ||
+                               (c == '{' && MORE2() && ISDIGIT((UCHAR_T)PEEK2())) ) )
+               return;
+       SETERROR(REG_BADRPT);
+}
+
+/*
+ - p_str - string (no metacharacters) "parser"
+ == static void p_str(register struct parse *p);
+ */
+static void
+p_str(register struct parse *p)
+{
+       (void)REQUIRE(MORE(), REG_EMPTY);
+       while (MORE())
+               ordinary(p, GETNEXT());
+}
+
+/*
+ - p_bre - BRE parser top level, anchoring and concatenation
+ == static void p_bre(register struct parse *p, register int end1, \
+ ==    register int end2, size_t reclimit);
+ * Giving end1 as OUT essentially eliminates the end1/end2 check.
+ *
+ * This implementation is a bit of a kludge, in that a trailing $ is first
+ * taken as an ordinary character and then revised to be an anchor.  The
+ * only undesirable side effect is that '$' gets included as a character
+ * category in such cases.  This is fairly harmless; not worth fixing.
+ * The amount of lookahead needed to avoid this kludge is excessive.
+ */
+static void
+p_bre(register struct parse *p, register int end1, register int end2, size_t reclimit)
+                         
+                               /* first terminating character */
+                               /* second terminating character */
+{
+       register sopno start;
+       register int first = 1;                 /* first subexpression? */
+       register int wasdollar = 0;
+
+       if (reclimit++ > RECLIMIT || p->error == REG_ESPACE) {
+               p->error = REG_ESPACE;
+               return;
+       }
+
+       start = HERE();
+
+       if (EAT('^')) {
+               EMIT(OBOL, 0);
+               p->g->iflags |= USEBOL;
+               p->g->nbol++;
+       }
+       while (MORE() && !SEETWO(end1, end2)) {
+               wasdollar = p_simp_re(p, first, reclimit);
+               first = 0;
+       }
+       if (wasdollar) {        /* oops, that was a trailing anchor */
+               DROP(1);
+               EMIT(OEOL, 0);
+               p->g->iflags |= USEEOL;
+               p->g->neol++;
+       }
+
+       (void)REQUIRE(HERE() != start, REG_EMPTY);      /* require nonempty */
+}
+
+/*
+ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
+ == static int p_simp_re(register struct parse *p, int starordinary, size_t reclimit);
+ */
+static int                     /* was the simple RE an unbackslashed $? */
+p_simp_re(register struct parse *p, int starordinary, size_t reclimit)
+                         
+                               /* is a leading * an ordinary character? */
+{
+       register int c;
+       register int count;
+       register int count2;
+       register sopno pos;
+       register int i;
+       register sopno subno;
+       int backsl;
+
+       pos = HERE();           /* repetion op, if any, covers from here */
+
+       assert(MORE());         /* caller should have ensured this */
+       c = GETNEXT();
+       backsl = c == '\\';
+       if (backsl) {
+               (void)REQUIRE(MORE(), REG_EESCAPE);
+               c = (unsigned char)GETNEXT();
+               switch (c) {
+               case '{':
+                       SETERROR(REG_BADRPT);
+                       break;
+               case '(':
+                       p->g->nsub++;
+                       subno = p->g->nsub;
+                       if (subno < NPAREN)
+                               p->pbegin[subno] = HERE();
+                       EMIT(OLPAREN, subno);
+                       /* the MORE here is an error heuristic */
+                       if (MORE() && !SEETWO('\\', ')'))
+                               p_bre(p, '\\', ')', reclimit);
+                       if (subno < NPAREN) {
+                               p->pend[subno] = HERE();
+                               assert(p->pend[subno] != 0);
+                       }
+                       EMIT(ORPAREN, subno);
+                       (void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+                       break;
+               case ')':       /* should not get here -- must be user */
+               case '}':
+                       SETERROR(REG_EPAREN);
+                       break;
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                       i = c - '0';
+                       assert(i < NPAREN);
+                       if (p->pend[i] != 0) {
+                               assert(i <= p->g->nsub);
+                               EMIT(OBACK_, i);
+                               assert(p->pbegin[i] != 0);
+                               assert(p->strip[p->pbegin[i]] == OLPAREN);
+                               assert(p->strip[p->pend[i]] == ORPAREN);
+                               (void) dupl(p, p->pbegin[i]+1, p->pend[i]);
+                               EMIT(O_BACK, i);
+                       } else
+                               SETERROR(REG_ESUBREG);
+                       p->g->backrefs = 1;
+                       break;
+               default:
+                       ordinary(p, c);
+                       break;
+               }
+       } else {
+               switch (c) {
+               case '.':
+                       if (p->g->cflags&REG_NEWLINE)
+                               nonnewline(p);
+                       else
+                               EMIT(OANY, 0);
+                       break;
+               case '[':
+                       p_bracket(p);
+                       break;
+               case '*':
+                       (void)REQUIRE(starordinary, REG_BADRPT);
+                       /* FALLTHROUGH */
+               default:
+                       ordinary(p, c);
+                       break;
+               }
+       }
+
+       if (EAT('*')) {         /* implemented as +? */
+               /* this case does not require the (y|) trick, noKLUDGE */
+               INSERT(OPLUS_, pos);
+               ASTERN(O_PLUS, pos);
+               INSERT(OQUEST_, pos);
+               ASTERN(O_QUEST, pos);
+       } else if (EATTWO('\\', '{')) {
+               count = p_count(p);
+               if (EAT(',')) {
+                       if (MORE() && ISDIGIT((UCHAR_T)PEEK())) {
+                               count2 = p_count(p);
+                               (void)REQUIRE(count <= count2, REG_BADBR);
+                       } else          /* single number with comma */
+                               count2 = INFINITY;
+               } else          /* just a single number */
+                       count2 = count;
+               repeat(p, pos, count, count2, reclimit);
+               if (!EATTWO('\\', '}')) {       /* error heuristics */
+                       while (MORE() && !SEETWO('\\', '}'))
+                               NEXT();
+                       (void)REQUIRE(MORE(), REG_EBRACE);
+                       SETERROR(REG_BADBR);
+               }
+       } else if (!backsl && c == (unsigned char)'$')  /* $ (but not \$) ends it */
+               return(1);
+
+       return(0);
+}
+
+/*
+ - p_count - parse a repetition count
+ == static int p_count(register struct parse *p);
+ */
+static int                     /* the value */
+p_count(register struct parse *p)
+{
+       register int count = 0;
+       register int ndigits = 0;
+
+       while (MORE() && ISDIGIT((UCHAR_T)PEEK()) && count <= DUPMAX) {
+               count = count*10 + (GETNEXT() - '0');
+               ndigits++;
+       }
+
+       (void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+       return(count);
+}
+
+/*
+ - p_bracket - parse a bracketed character list
+ == static void p_bracket(register struct parse *p);
+ *
+ * Note a significant property of this code:  if the allocset() did SETERROR,
+ * no set operations are done.
+ */
+static void
+p_bracket(register struct parse *p)
+{
+       register cset *cs;
+       register int invert = 0;
+       static RCHAR_T bow[] = { '[', ':', '<', ':', ']', ']' };
+       static RCHAR_T eow[] = { '[', ':', '>', ':', ']', ']' };
+
+       cs = allocset(p);
+       if (cs == NULL)
+               return;
+
+       /* Dept of Truly Sickening Special-Case Kludges */
+       if (p->next + 5 < p->end && MEMCMP(p->next, bow, 6) == 0) {
+               EMIT(OBOW, 0);
+               NEXTn(6);
+               return;
+       }
+       if (p->next + 5 < p->end && MEMCMP(p->next, eow, 6) == 0) {
+               EMIT(OEOW, 0);
+               NEXTn(6);
+               return;
+       }
+
+       if (EAT('^'))
+               invert++;       /* make note to invert set at end */
+       if (EAT(']'))
+               CHadd(cs, ']');
+       else if (EAT('-'))
+               CHadd(cs, '-');
+       while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
+               p_b_term(p, cs);
+       if (EAT('-'))
+               CHadd(cs, '-');
+       (void)MUSTEAT(']', REG_EBRACK);
+
+       if (p->error != 0)      /* don't mess things up further */
+               return;
+
+       if (p->g->cflags&REG_ICASE) {
+               register int i;
+               register int ci;
+
+               for (i = p->g->csetsize - 1; i >= 0; i--)
+                       if (CHIN(cs, i) && isalpha(i)) {
+                               ci = othercase(i);
+                               if (ci != i)
+                                       CHadd(cs, ci);
+                       }
+               if (cs->multis != NULL)
+                       mccase(p, cs);
+       }
+       if (invert) {
+               register int i;
+
+               for (i = p->g->csetsize - 1; i >= 0; i--)
+                       if (CHIN(cs, i))
+                               CHsub(cs, i);
+                       else
+                               CHadd(cs, i);
+               if (p->g->cflags&REG_NEWLINE)
+                       CHsub(cs, '\n');
+               if (cs->multis != NULL)
+                       mcinvert(p, cs);
+       }
+
+       assert(cs->multis == NULL);             /* xxx */
+
+       if (nch(p, cs) == 1) {          /* optimize singleton sets */
+               ordinary(p, firstch(p, cs));
+               freeset(p, cs);
+       } else
+               EMIT(OANYOF, freezeset(p, cs));
+}
+
+/*
+ - p_b_term - parse one term of a bracketed character list
+ == static void p_b_term(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_term(register struct parse *p, register cset *cs)
+{
+       register char c;
+       register char start, finish;
+       register int i;
+
+       /* classify what we've got */
+       switch ((MORE()) ? PEEK() : '\0') {
+       case '[':
+               c = (MORE2()) ? PEEK2() : '\0';
+               break;
+       case '-':
+               SETERROR(REG_ERANGE);
+               return;                 /* NOTE RETURN */
+               break;
+       default:
+               c = '\0';
+               break;
+       }
+
+       switch (c) {
+       case ':':               /* character class */
+               NEXT2();
+               (void)REQUIRE(MORE(), REG_EBRACK);
+               c = PEEK();
+               (void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+               p_b_cclass(p, cs);
+               (void)REQUIRE(MORE(), REG_EBRACK);
+               (void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+               break;
+       case '=':               /* equivalence class */
+               NEXT2();
+               (void)REQUIRE(MORE(), REG_EBRACK);
+               c = PEEK();
+               (void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+               p_b_eclass(p, cs);
+               (void)REQUIRE(MORE(), REG_EBRACK);
+               (void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+               break;
+       default:                /* symbol, ordinary character, or range */
+/* xxx revision needed for multichar stuff */
+               start = p_b_symbol(p);
+               if (SEE('-') && MORE2() && PEEK2() != ']') {
+                       /* range */
+                       NEXT();
+                       if (EAT('-'))
+                               finish = '-';
+                       else
+                               finish = p_b_symbol(p);
+               } else
+                       finish = start;
+/* xxx what about signed chars here... */
+               (void)REQUIRE(start <= finish, REG_ERANGE);
+               for (i = start; i <= finish; i++)
+                       CHadd(cs, i);
+               break;
+       }
+}
+
+/*
+ - p_b_cclass - parse a character-class name and deal with it
+ == static void p_b_cclass(register struct parse *p, register cset *cs);
+ */
+static void
+p_b_cclass(register struct parse *p, register cset *cs)
+{
+       register RCHAR_T *sp = p->next;
+       register struct cclass *cp;
+       register size_t len;
+       register const char *u;
+       register char c;
+
+       while (MORE() && isalpha(PEEK()))
+               NEXT();
+       len = p->next - sp;
+       for (cp = cclasses; cp->name != NULL; cp++)
+               if (STRLEN(cp->name) == len && MEMCMP(cp->name, sp, len))
+                       break;
+       if (cp->name == NULL) {
+               /* oops, didn't find it */
+               SETERROR(REG_ECTYPE);
+               return;
+       }
+
+       u = cp->chars;
+       while ((c = *u++) != '\0')
+               CHadd(cs, c);
+       for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
+               MCadd(p, cs, u);
+}
+
+/*
+ - p_b_eclass - parse an equivalence-class name and deal with it
+ == static void p_b_eclass(register struct parse *p, register cset *cs);
+ *
+ * This implementation is incomplete. xxx
+ */
+static void
+p_b_eclass(register struct parse *p, register cset *cs)
+{
+       register char c;
+
+       c = p_b_coll_elem(p, '=');
+       CHadd(cs, c);
+}
+
+/*
+ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
+ == static char p_b_symbol(register struct parse *p);
+ */
+static char                    /* value of symbol */
+p_b_symbol(register struct parse *p)
+{
+       register char value;
+
+       (void)REQUIRE(MORE(), REG_EBRACK);
+       if (!EATTWO('[', '.'))
+               return(GETNEXT());
+
+       /* collating symbol */
+       value = p_b_coll_elem(p, '.');
+       (void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+       return(value);
+}
+
+/*
+ - p_b_coll_elem - parse a collating-element name and look it up
+ == static char p_b_coll_elem(register struct parse *p, int endc);
+ */
+static char                    /* value of collating element */
+p_b_coll_elem(register struct parse *p, int endc)
+                         
+                               /* name ended by endc,']' */
+{
+       register RCHAR_T *sp = p->next;
+       register struct cname *cp;
+       register size_t len;
+
+       while (MORE() && !SEETWO(endc, ']'))
+               NEXT();
+       if (!MORE()) {
+               SETERROR(REG_EBRACK);
+               return(0);
+       }
+       len = p->next - sp;
+       for (cp = cnames; cp->name != NULL; cp++)
+               if (STRLEN(cp->name) == len && MEMCMP(cp->name, sp, len))
+                       return(cp->code);       /* known name */
+       if (len == 1)
+               return(*sp);    /* single character */
+       SETERROR(REG_ECOLLATE);                 /* neither */
+       return(0);
+}
+
+/*
+ - othercase - return the case counterpart of an alphabetic
+ == static char othercase(int ch);
+ */
+static char                    /* if no counterpart, return ch */
+othercase(int ch)
+{
+       assert(isalpha(ch));
+       if (isupper(ch))
+               return(tolower(ch));
+       else if (islower(ch))
+               return(toupper(ch));
+       else                    /* peculiar, but could happen */
+               return(ch);
+}
+
+/*
+ - bothcases - emit a dualcase version of a two-case character
+ == static void bothcases(register struct parse *p, int ch);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+bothcases(register struct parse *p, int ch)
+{
+       register RCHAR_T *oldnext = p->next;
+       register RCHAR_T *oldend = p->end;
+       RCHAR_T bracket[3];
+
+       assert(othercase(ch) != ch);    /* p_bracket() would recurse */
+       p->next = bracket;
+       p->end = bracket+2;
+       bracket[0] = ch;
+       bracket[1] = ']';
+       bracket[2] = '\0';
+       p_bracket(p);
+       assert(p->next == bracket+2);
+       p->next = oldnext;
+       p->end = oldend;
+}
+
+/*
+ - ordinary - emit an ordinary character
+ == static void ordinary(register struct parse *p, register int ch);
+ */
+static void
+ordinary(register struct parse *p, register int ch)
+{
+/*
+       register cat_t *cap = p->g->categories;
+*/
+
+       if ((p->g->cflags&REG_ICASE) && isalpha(ch) && othercase(ch) != ch)
+               bothcases(p, ch);
+       else {
+               EMIT(OCHAR, (UCHAR_T)ch);
+/*
+               if (cap[ch] == 0)
+                       cap[ch] = p->g->ncategories++;
+*/
+       }
+}
+
+/*
+ - nonnewline - emit REG_NEWLINE version of OANY
+ == static void nonnewline(register struct parse *p);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+nonnewline(register struct parse *p)
+{
+       register RCHAR_T *oldnext = p->next;
+       register RCHAR_T *oldend = p->end;
+       RCHAR_T bracket[4];
+
+       p->next = bracket;
+       p->end = bracket+3;
+       bracket[0] = '^';
+       bracket[1] = '\n';
+       bracket[2] = ']';
+       bracket[3] = '\0';
+       p_bracket(p);
+       assert(p->next == bracket+3);
+       p->next = oldnext;
+       p->end = oldend;
+}
+
+/*
+ - repeat - generate code for a bounded repetition, recursively if needed
+ == static void repeat(register struct parse *p, sopno start, int from, int to, size_t reclimit);
+ */
+static void
+repeat(register struct parse *p, sopno start, int from, int to, size_t reclimit)
+                         
+                               /* operand from here to end of strip */
+                               /* repeated from this number */
+                                       /* to this number of times (maybe INFINITY) */
+{
+       register sopno finish;
+#      define  N       2
+#      define  INF     3
+#      define  REP(f, t)       ((f)*8 + (t))
+#      define  MAP(n)  (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
+       register sopno copy;
+
+       if (reclimit++ > RECLIMIT) 
+               p->error = REG_ESPACE;
+       if (p->error)
+               return;
+
+       finish = HERE();
+
+       assert(from <= to);
+
+       switch (REP(MAP(from), MAP(to))) {
+       case REP(0, 0):                 /* must be user doing this */
+               DROP(finish-start);     /* drop the operand */
+               break;
+       case REP(0, 1):                 /* as x{1,1}? */
+       case REP(0, N):                 /* as x{1,n}? */
+       case REP(0, INF):               /* as x{1,}? */
+               /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+               INSERT(OCH_, start);            /* offset is wrong... */
+               repeat(p, start+1, 1, to, reclimit);
+               ASTERN(OOR1, start);
+               AHEAD(start);                   /* ... fix it */
+               EMIT(OOR2, 0);
+               AHEAD(THERE());
+               ASTERN(O_CH, THERETHERE());
+               break;
+       case REP(1, 1):                 /* trivial case */
+               /* done */
+               break;
+       case REP(1, N):                 /* as x?x{1,n-1} */
+               /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+               INSERT(OCH_, start);
+               ASTERN(OOR1, start);
+               AHEAD(start);
+               EMIT(OOR2, 0);                  /* offset very wrong... */
+               AHEAD(THERE());                 /* ...so fix it */
+               ASTERN(O_CH, THERETHERE());
+               copy = dupl(p, start+1, finish+1);
+               assert(copy == finish+4);
+               repeat(p, copy, 1, to-1, reclimit);
+               break;
+       case REP(1, INF):               /* as x+ */
+               INSERT(OPLUS_, start);
+               ASTERN(O_PLUS, start);
+               break;
+       case REP(N, N):                 /* as xx{m-1,n-1} */
+               copy = dupl(p, start, finish);
+               repeat(p, copy, from-1, to-1, reclimit);
+               break;
+       case REP(N, INF):               /* as xx{n-1,INF} */
+               copy = dupl(p, start, finish);
+               repeat(p, copy, from-1, to, reclimit);
+               break;
+       default:                        /* "can't happen" */
+               SETERROR(REG_ASSERT);   /* just in case */
+               break;
+       }
+}
+
+/*
+ - seterr - set an error condition
+ == static int seterr(register struct parse *p, int e);
+ */
+static int                     /* useless but makes type checking happy */
+seterr(register struct parse *p, int e)
+{
+       if (p->error == 0)      /* keep earliest error condition */
+               p->error = e;
+       p->next = nuls;         /* try to bring things to a halt */
+       p->end = nuls;
+       return(0);              /* make the return value well-defined */
+}
+
+/*
+ - allocset - allocate a set of characters for []
+ == static cset *allocset(register struct parse *p);
+ */
+static cset *
+allocset(register struct parse *p)
+{
+       register int no = p->g->ncsets++;
+       register size_t nc;
+       register size_t nbytes;
+       register cset *cs;
+       register size_t css = (size_t)p->g->csetsize;
+       register int i;
+
+       if (no >= p->ncsalloc) {        /* need another column of space */
+               p->ncsalloc += CHAR_BIT;
+               nc = p->ncsalloc;
+               assert(nc % CHAR_BIT == 0);
+               nbytes = nc / CHAR_BIT * css;
+               if (MEMSIZE(p) > MEMLIMIT)
+                       goto oomem;
+               if (p->g->sets == NULL)
+                       p->g->sets = (cset *)malloc(nc * sizeof(cset));
+               else
+                       p->g->sets = (cset *)realloc((char *)p->g->sets,
+                                                       nc * sizeof(cset));
+               if (p->g->setbits == NULL)
+                       p->g->setbits = (uch *)malloc(nbytes);
+               else {
+                       p->g->setbits = (uch *)realloc((char *)p->g->setbits,
+                                                               nbytes);
+                       /* xxx this isn't right if setbits is now NULL */
+                       for (i = 0; i < no; i++)
+                               p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
+               }
+               if (p->g->sets != NULL && p->g->setbits != NULL)
+                       (void) memset((char *)p->g->setbits + (nbytes - css),
+                                                               0, css);
+               else {
+oomem:
+                       no = 0;
+                       SETERROR(REG_ESPACE);
+                       /* caller's responsibility not to do set ops */
+                       return NULL;
+               }
+       }
+
+       cs = &p->g->sets[no];
+       cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);
+       cs->mask = 1 << ((no) % CHAR_BIT);
+       cs->hash = 0;
+       cs->smultis = 0;
+       cs->multis = NULL;
+
+       return(cs);
+}
+
+/*
+ - freeset - free a now-unused set
+ == static void freeset(register struct parse *p, register cset *cs);
+ */
+static void
+freeset(register struct parse *p, register cset *cs)
+{
+       register size_t i;
+       register cset *top = &p->g->sets[p->g->ncsets];
+       register size_t css = (size_t)p->g->csetsize;
+
+       for (i = 0; i < css; i++)
+               CHsub(cs, i);
+       if (cs == top-1)        /* recover only the easy case */
+               p->g->ncsets--;
+}
+
+/*
+ - freezeset - final processing on a set of characters
+ == static int freezeset(register struct parse *p, register cset *cs);
+ *
+ * The main task here is merging identical sets.  This is usually a waste
+ * of time (although the hash code minimizes the overhead), but can win
+ * big if REG_ICASE is being used.  REG_ICASE, by the way, is why the hash
+ * is done using addition rather than xor -- all ASCII [aA] sets xor to
+ * the same value!
+ */
+static int                     /* set number */
+freezeset(register struct parse *p, register cset *cs)
+{
+       register uch h = cs->hash;
+       register size_t i;
+       register cset *top = &p->g->sets[p->g->ncsets];
+       register cset *cs2;
+       register size_t css = (size_t)p->g->csetsize;
+
+       /* look for an earlier one which is the same */
+       for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
+               if (cs2->hash == h && cs2 != cs) {
+                       /* maybe */
+                       for (i = 0; i < css; i++)
+                               if (!!CHIN(cs2, i) != !!CHIN(cs, i))
+                                       break;          /* no */
+                       if (i == css)
+                               break;                  /* yes */
+               }
+
+       if (cs2 < top) {        /* found one */
+               freeset(p, cs);
+               cs = cs2;
+       }
+
+       return((int)(cs - p->g->sets));
+}
+
+/*
+ - firstch - return first character in a set (which must have at least one)
+ == static int firstch(register struct parse *p, register cset *cs);
+ */
+static int                     /* character; there is no "none" value */
+firstch(register struct parse *p, register cset *cs)
+{
+       register size_t i;
+       register size_t css = (size_t)p->g->csetsize;
+
+       for (i = 0; i < css; i++)
+               if (CHIN(cs, i))
+                       return((char)i);
+       assert(never);
+       return(0);              /* arbitrary */
+}
+
+/*
+ - nch - number of characters in a set
+ == static int nch(register struct parse *p, register cset *cs);
+ */
+static int
+nch(register struct parse *p, register cset *cs)
+{
+       register size_t i;
+       register size_t css = (size_t)p->g->csetsize;
+       register int n = 0;
+
+       for (i = 0; i < css; i++)
+               if (CHIN(cs, i))
+                       n++;
+       return(n);
+}
+
+/*
+ - mcadd - add a collating element to a cset
+ == static void mcadd(register struct parse *p, register cset *cs, \
+ ==    register char *cp);
+ */
+static void
+mcadd(register struct parse *p, register cset *cs, register const char *cp)
+{
+       register size_t oldend = cs->smultis;
+
+       cs->smultis += strlen(cp) + 1;
+       if (cs->multis == NULL)
+               cs->multis = malloc(cs->smultis);
+       else
+               cs->multis = realloc(cs->multis, cs->smultis);
+       if (cs->multis == NULL) {
+               SETERROR(REG_ESPACE);
+               return;
+       }
+
+       (void) strcpy(cs->multis + oldend - 1, cp);
+       cs->multis[cs->smultis - 1] = '\0';
+}
+
+#ifdef notdef
+/*
+ - mcsub - subtract a collating element from a cset
+ == static void mcsub(register cset *cs, register char *cp);
+ */
+static void
+mcsub(register cset *cs, register char *cp)
+{
+       register char *fp = mcfind(cs, cp);
+       register size_t len = strlen(fp);
+
+       assert(fp != NULL);
+       (void) memmove(fp, fp + len + 1,
+                               cs->smultis - (fp + len + 1 - cs->multis));
+       cs->smultis -= len;
+
+       if (cs->smultis == 0) {
+               free(cs->multis);
+               cs->multis = NULL;
+               return;
+       }
+
+       cs->multis = realloc(cs->multis, cs->smultis);
+       assert(cs->multis != NULL);
+}
+
+/*
+ - mcin - is a collating element in a cset?
+ == static int mcin(register cset *cs, register char *cp);
+ */
+static int
+mcin(register cset *cs, register char *cp)
+{
+       return(mcfind(cs, cp) != NULL);
+}
+
+/*
+ - mcfind - find a collating element in a cset
+ == static char *mcfind(register cset *cs, register char *cp);
+ */
+static char *
+mcfind(register cset *cs, register char *cp)
+{
+       register char *p;
+
+       if (cs->multis == NULL)
+               return(NULL);
+       for (p = cs->multis; *p != '\0'; p += strlen(p) + 1)
+               if (strcmp(cp, p) == 0)
+                       return(p);
+       return(NULL);
+}
+#endif
+
+/*
+ - mcinvert - invert the list of collating elements in a cset
+ == static void mcinvert(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities.  Implementation
+ * is deferred.
+ */
+static void
+mcinvert(register struct parse *p, register cset *cs)
+{
+       assert(cs->multis == NULL);     /* xxx */
+}
+
+/*
+ - mccase - add case counterparts of the list of collating elements in a cset
+ == static void mccase(register struct parse *p, register cset *cs);
+ *
+ * This would have to know the set of possibilities.  Implementation
+ * is deferred.
+ */
+static void
+mccase(register struct parse *p, register cset *cs)
+{
+       assert(cs->multis == NULL);     /* xxx */
+}
+
+#ifdef notdef
+/*
+ - isinsets - is this character in any sets?
+ == static int isinsets(register struct re_guts *g, int c);
+ */
+static int                     /* predicate */
+isinsets(register struct re_guts *g, int c)
+{
+       register uch *col;
+       register int i;
+       register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+       register unsigned uc = (unsigned char)c;
+
+       for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+               if (col[uc] != 0)
+                       return(1);
+       return(0);
+}
+
+/*
+ - samesets - are these two characters in exactly the same sets?
+ == static int samesets(register struct re_guts *g, int c1, int c2);
+ */
+static int                     /* predicate */
+samesets(register struct re_guts *g, int c1, int c2)
+{
+       register uch *col;
+       register int i;
+       register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
+       register unsigned uc1 = (unsigned char)c1;
+       register unsigned uc2 = (unsigned char)c2;
+
+       for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
+               if (col[uc1] != col[uc2])
+                       return(0);
+       return(1);
+}
+#endif
+
+/*
+ - categorize - sort out character categories
+ == static void categorize(struct parse *p, register struct re_guts *g);
+ */
+static void
+categorize(struct parse *p, register struct re_guts *g)
+{
+#ifdef notdef
+       register cat_t *cats = g->categories;
+       register int c;
+       register int c2;
+       register cat_t cat;
+
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+               if (cats[c] == 0 && isinsets(g, c)) {
+                       cat = g->ncategories++;
+                       cats[c] = cat;
+                       for (c2 = c+1; c2 <= CHAR_MAX; c2++)
+                               if (cats[c2] == 0 && samesets(g, c, c2))
+                                       cats[c2] = cat;
+               }
+#endif
+}
+
+/*
+ - dupl - emit a duplicate of a bunch of sops
+ == static sopno dupl(register struct parse *p, sopno start, sopno finish);
+ */
+static sopno                   /* start of duplicate */
+dupl(register struct parse *p, sopno start, sopno finish)
+                         
+                               /* from here */
+                               /* to this less one */
+{
+       register sopno ret = HERE();
+       register sopno len = finish - start;
+
+       assert(finish >= start);
+       if (len == 0)
+               return(ret);
+       if (!enlarge(p, p->ssize + len))        /* this many unexpected additions */
+               return ret;
+       assert(p->ssize >= p->slen + len);
+       (void) memcpy((char *)(p->strip + p->slen),
+               (char *)(p->strip + start), (size_t)len*sizeof(sop));
+       (void) memcpy((char *)(p->stripdata + p->slen),
+               (char *)(p->stripdata + start), (size_t)len*sizeof(RCHAR_T));
+       p->slen += len;
+       return(ret);
+}
+
+/*
+ - doemit - emit a strip operator
+ == static void doemit(register struct parse *p, sop op, size_t opnd);
+ *
+ * It might seem better to implement this as a macro with a function as
+ * hard-case backup, but it's just too big and messy unless there are
+ * some changes to the data structures.  Maybe later.
+ */
+static void
+doemit(register struct parse *p, sop op, size_t opnd)
+{
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       /* deal with oversize operands ("can't happen", more or less) */
+       assert(opnd < 1);
+
+       /* deal with undersized strip */
+       if (p->slen >= p->ssize)
+               if (!enlarge(p, (p->ssize+1) / 2 * 3))  /* +50% */
+                       return;
+
+       /* finally, it's all reduced to the easy case */
+       p->strip[p->slen] = op;
+       p->stripdata[p->slen] = opnd;
+       p->slen++;
+}
+
+/*
+ - doinsert - insert a sop into the strip
+ == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);
+ */
+static void
+doinsert(register struct parse *p, sop op, size_t opnd, sopno pos)
+{
+       register sopno sn;
+       register sop s;
+       register RCHAR_T d;
+       register int i;
+
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       sn = HERE();
+       EMIT(op, opnd);         /* do checks, ensure space */
+       assert(HERE() == sn+1);
+       s = p->strip[sn];
+       d = p->stripdata[sn];
+
+       /* adjust paren pointers */
+       assert(pos > 0);
+       for (i = 1; i < NPAREN; i++) {
+               if (p->pbegin[i] >= pos) {
+                       p->pbegin[i]++;
+               }
+               if (p->pend[i] >= pos) {
+                       p->pend[i]++;
+               }
+       }
+
+       memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
+                                               (HERE()-pos-1)*sizeof(sop));
+       memmove((char *)&p->stripdata[pos+1], (char *)&p->stripdata[pos],
+                                               (HERE()-pos-1)*sizeof(RCHAR_T));
+       p->strip[pos] = s;
+       p->stripdata[pos] = d;
+}
+
+/*
+ - dofwd - complete a forward reference
+ == static void dofwd(register struct parse *p, sopno pos, sop value);
+ */
+static void
+dofwd(register struct parse *p, register sopno pos, sop value)
+{
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       assert(value < 1);
+       p->stripdata[pos] = value;
+}
+
+/*
+ - enlarge - enlarge the strip
+ == static int enlarge(register struct parse *p, sopno size);
+ */
+static int
+enlarge(register struct parse *p, register sopno size)
+{
+       register sop *sp;
+       register RCHAR_T *dp;
+       sopno osize;
+
+       if (p->ssize >= size)
+               return 1;
+
+       osize = p->ssize;
+       p->ssize = size;
+       if (MEMSIZE(p) > MEMLIMIT)
+               goto oomem;
+       sp = realloc(p->strip, p->ssize * sizeof(sop));
+       if (sp == NULL)
+               goto oomem;
+       p->strip = sp;
+       dp = realloc(p->stripdata, p->ssize * sizeof(RCHAR_T));
+       if (dp == NULL) {
+oomem:
+               p->ssize = osize;
+               SETERROR(REG_ESPACE);
+               return 0;
+       }
+       p->stripdata = dp;
+       return 1;
+}
+
+/*
+ - stripsnug - compact the strip
+ == static void stripsnug(register struct parse *p, register struct re_guts *g);
+ */
+static void
+stripsnug(register struct parse *p, register struct re_guts *g)
+{
+       g->nstates = p->slen;
+       g->strip = (sop *)realloc((char *)p->strip,
+           p->slen * sizeof(sop));
+       if (g->strip == NULL) {
+               SETERROR(REG_ESPACE);
+               g->strip = p->strip;
+       }
+       g->stripdata = (RCHAR_T *)realloc((char *)p->stripdata,
+           p->slen * sizeof(RCHAR_T));
+       if (g->stripdata == NULL) {
+               SETERROR(REG_ESPACE);
+               g->stripdata = p->stripdata;
+       }
+}
+
+/*
+ - findmust - fill in must and mlen with longest mandatory literal string
+ == static void findmust(register struct parse *p, register struct re_guts *g);
+ *
+ * This algorithm could do fancy things like analyzing the operands of |
+ * for common subsequences.  Someday.  This code is simple and finds most
+ * of the interesting cases.
+ *
+ * Note that must and mlen got initialized during setup.
+ */
+static void
+findmust(struct parse *p, register struct re_guts *g)
+{
+       register sop *scans;
+       register RCHAR_T *scand;
+       sop *starts = 0;
+       RCHAR_T *startd = NULL;
+       register sop *newstarts = 0;
+       register RCHAR_T *newstartd = NULL;
+       register sopno newlen;
+       register sop s;
+       register RCHAR_T d;
+       register RCHAR_T *cp;
+       register sopno i;
+
+       /* avoid making error situations worse */
+       if (p->error != 0)
+               return;
+
+       /* find the longest OCHAR sequence in strip */
+       newlen = 0;
+       scans = g->strip + 1;
+       scand = g->stripdata + 1;
+       do {
+               s = *scans++;
+               d = *scand++;
+               switch (s) {
+               case OCHAR:             /* sequence member */
+                       if (newlen == 0) {              /* new sequence */
+                               newstarts = scans - 1;
+                               newstartd = scand - 1;
+                       }
+                       newlen++;
+                       break;
+               case OPLUS_:            /* things that don't break one */
+               case OLPAREN:
+               case ORPAREN:
+                       break;
+               case OQUEST_:           /* things that must be skipped */
+               case OCH_:
+                       scans--;
+                       scand--;
+                       do {
+                               scans += d;
+                               scand += d;
+                               s = *scans;
+                               d = *scand;
+                               /* assert() interferes w debug printouts */
+                               if (s != O_QUEST && s != O_CH && s != OOR2) {
+                                       g->iflags |= BAD;
+                                       return;
+                               }
+                       } while (s != O_QUEST && s != O_CH);
+                       /* fallthrough */
+               default:                /* things that break a sequence */
+                       if (newlen > g->mlen) {         /* ends one */
+                               starts = newstarts;
+                               startd = newstartd;
+                               g->mlen = newlen;
+                       }
+                       newlen = 0;
+                       break;
+               }
+       } while (s != OEND);
+
+       if (g->mlen == 0)               /* there isn't one */
+               return;
+
+       /* turn it into a character string */
+       g->must = malloc(((size_t)g->mlen + 1) * sizeof(RCHAR_T));
+       if (g->must == NULL) {          /* argh; just forget it */
+               g->mlen = 0;
+               return;
+       }
+       cp = g->must;
+       scans = starts;
+       scand = startd;
+       for (i = g->mlen; i > 0; i--) {
+               for (;;) {
+                       s = *scans++;
+                       d = *scand++;
+                       if (s == OCHAR)
+                               break;
+               }
+               assert(cp < g->must + g->mlen);
+               *cp++ = d;
+       }
+       assert(cp == g->must + g->mlen);
+       *cp++ = '\0';           /* just on general principles */
+}
+
+/*
+ - pluscount - count + nesting
+ == static sopno pluscount(register struct parse *p, register struct re_guts *g);
+ */
+static sopno                   /* nesting depth */
+pluscount(struct parse *p, register struct re_guts *g)
+{
+       register sop *scan;
+       register sop s;
+       register sopno plusnest = 0;
+       register sopno maxnest = 0;
+
+       if (p->error != 0)
+               return(0);      /* there may not be an OEND */
+
+       scan = g->strip + 1;
+       do {
+               s = *scan++;
+               switch (s) {
+               case OPLUS_:
+                       plusnest++;
+                       break;
+               case O_PLUS:
+                       if (plusnest > maxnest)
+                               maxnest = plusnest;
+                       plusnest--;
+                       break;
+               }
+       } while (s != OEND);
+       if (plusnest != 0)
+               g->iflags |= BAD;
+       return(maxnest);
+}
diff --git a/dist/nvi/regex/regerror.c b/dist/nvi/regex/regerror.c
new file mode 100644 (file)
index 0000000..0b528d0
--- /dev/null
@@ -0,0 +1,180 @@
+/*     $NetBSD: regerror.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regerror.c  8.3 (Berkeley) 3/19/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regerror.c 8.3 (Berkeley) 3/19/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi __P((const regex_t *preg, char *localbuf));
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+/*
+ = #define     REG_NOMATCH      1
+ = #define     REG_BADPAT       2
+ = #define     REG_ECOLLATE     3
+ = #define     REG_ECTYPE       4
+ = #define     REG_EESCAPE      5
+ = #define     REG_ESUBREG      6
+ = #define     REG_EBRACK       7
+ = #define     REG_EPAREN       8
+ = #define     REG_EBRACE       9
+ = #define     REG_BADBR       10
+ = #define     REG_ERANGE      11
+ = #define     REG_ESPACE      12
+ = #define     REG_BADRPT      13
+ = #define     REG_EMPTY       14
+ = #define     REG_ASSERT      15
+ = #define     REG_INVARG      16
+ = #define     REG_ATOI        255     // convert name to number (!)
+ = #define     REG_ITOA        0400    // convert number to name (!)
+ */
+static struct rerr {
+       int code;
+       const char *name;
+       const char *explain;
+} rerrs[] = {
+       { REG_NOMATCH,  "REG_NOMATCH",  "regexec() failed to match" },
+       { REG_BADPAT,   "REG_BADPAT",   "invalid regular expression" },
+       { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" },
+       { REG_ECTYPE,   "REG_ECTYPE",   "invalid character class" },
+       { REG_EESCAPE,  "REG_EESCAPE",  "trailing backslash (\\)" },
+       { REG_ESUBREG,  "REG_ESUBREG",  "invalid backreference number" },
+       { REG_EBRACK,   "REG_EBRACK",   "brackets ([ ]) not balanced" },
+       { REG_EPAREN,   "REG_EPAREN",   "parentheses not balanced" },
+       { REG_EBRACE,   "REG_EBRACE",   "braces not balanced" },
+       { REG_BADBR,    "REG_BADBR",    "invalid repetition count(s)" },
+       { REG_ERANGE,   "REG_ERANGE",   "invalid character range" },
+       { REG_ESPACE,   "REG_ESPACE",   "out of memory" },
+       { REG_BADRPT,   "REG_BADRPT",   "repetition-operator operand invalid" },
+       { REG_EMPTY,    "REG_EMPTY",    "empty (sub)expression" },
+       { REG_ASSERT,   "REG_ASSERT",   "\"can't happen\" -- you found a bug" },
+       { REG_INVARG,   "REG_INVARG",   "invalid argument to regex routine" },
+       { 0,            "",             "*** unknown regexp error code ***" },
+};
+
+/*
+ - regerror - the interface to error numbers
+ = extern size_t regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+size_t
+regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+       register struct rerr *r;
+       register size_t len;
+       register int target = errcode &~ REG_ITOA;
+       register const char *s;
+       char convbuf[50];
+
+       if (errcode == REG_ATOI)
+               s = regatoi(preg, convbuf);
+       else {
+               for (r = rerrs; r->code != 0; r++)
+                       if (r->code == target)
+                               break;
+       
+               if (errcode&REG_ITOA) {
+                       if (r->code != 0)
+                               (void) strcpy(convbuf, r->name);
+                       else
+                               sprintf(convbuf, "REG_0x%x", target);
+                       assert(strlen(convbuf) < sizeof(convbuf));
+                       s = convbuf;
+               } else
+                       s = r->explain;
+       }
+
+       len = strlen(s) + 1;
+       if (errbuf_size > 0) {
+               if (errbuf_size > len)
+                       (void) strcpy(errbuf, s);
+               else {
+                       (void) strncpy(errbuf, s, errbuf_size-1);
+                       errbuf[errbuf_size-1] = '\0';
+               }
+       }
+
+       return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(const regex_t *preg, char *localbuf)
+{
+#if 0 /* we don't seem to use this and it gives a warning. */
+       register struct rerr *r;
+       register size_t siz;
+       register char *p;
+
+       for (r = rerrs; r->code != 0; r++)
+               if (strcmp(r->name, preg->re_endp) == 0)
+                       break;
+       if (r->code == 0)
+               return("0");
+
+       sprintf(localbuf, "%d", r->code);
+#else
+       *localbuf = '\0';
+#endif
+       return(localbuf);
+}
diff --git a/dist/nvi/regex/regex.3 b/dist/nvi/regex/regex.3
new file mode 100644 (file)
index 0000000..2c17254
--- /dev/null
@@ -0,0 +1,540 @@
+.\"    $NetBSD: regex.3,v 1.1.1.2 2008/05/18 14:31:38 aymeric Exp $
+.\"
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer of the University of Toronto.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)regex.3     8.2 (Berkeley) 3/16/94
+.\"
+.TH REGEX 3 "March 16, 1994"
+.de ZR
+.\" one other place knows this name:  the SEE ALSO section
+.IR re_format (7) \\$1
+..
+.SH NAME
+regcomp, regexec, regerror, regfree \- regular-expression library
+.SH SYNOPSIS
+.ft B
+.\".na
+#include <sys/types.h>
+.br
+#include <regex.h>
+.HP 10
+int regcomp(regex_t\ *preg, const\ char\ *pattern, int\ cflags);
+.HP
+int\ regexec(const\ regex_t\ *preg, const\ char\ *string,
+size_t\ nmatch, regmatch_t\ pmatch[], int\ eflags);
+.HP
+size_t\ regerror(int\ errcode, const\ regex_t\ *preg,
+char\ *errbuf, size_t\ errbuf_size);
+.HP
+void\ regfree(regex_t\ *preg);
+.\".ad
+.ft
+.SH DESCRIPTION
+These routines implement POSIX 1003.2 regular expressions (``RE''s);
+see
+.ZR .
+.I Regcomp
+compiles an RE written as a string into an internal form,
+.I regexec
+matches that internal form against a string and reports results,
+.I regerror
+transforms error codes from either into human-readable messages,
+and
+.I regfree
+frees any dynamically-allocated storage used by the internal form
+of an RE.
+.PP
+The header
+.I <regex.h>
+declares two structure types,
+.I regex_t
+and
+.IR regmatch_t ,
+the former for compiled internal forms and the latter for match reporting.
+It also declares the four functions,
+a type
+.IR regoff_t ,
+and a number of constants with names starting with ``REG_''.
+.PP
+.I Regcomp
+compiles the regular expression contained in the
+.I pattern
+string,
+subject to the flags in
+.IR cflags ,
+and places the results in the
+.I regex_t
+structure pointed to by
+.IR preg .
+.I Cflags
+is the bitwise OR of zero or more of the following flags:
+.IP REG_EXTENDED \w'REG_EXTENDED'u+2n
+Compile modern (``extended'') REs,
+rather than the obsolete (``basic'') REs that
+are the default.
+.IP REG_BASIC
+This is a synonym for 0,
+provided as a counterpart to REG_EXTENDED to improve readability.
+.IP REG_NOSPEC
+Compile with recognition of all special characters turned off.
+All characters are thus considered ordinary,
+so the ``RE'' is a literal string.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+REG_EXTENDED and REG_NOSPEC may not be used
+in the same call to
+.IR regcomp .
+.IP REG_ICASE
+Compile for matching that ignores upper/lower case distinctions.
+See
+.ZR .
+.IP REG_NOSUB
+Compile for matching that need only report success or failure,
+not what was matched.
+.IP REG_NEWLINE
+Compile for newline-sensitive matching.
+By default, newline is a completely ordinary character with no special
+meaning in either REs or strings.
+With this flag,
+`[^' bracket expressions and `.' never match newline,
+a `^' anchor matches the null string after any newline in the string
+in addition to its normal function,
+and the `$' anchor matches the null string before any newline in the
+string in addition to its normal function.
+.IP REG_PEND
+The regular expression ends,
+not at the first NUL,
+but just before the character pointed to by the
+.I re_endp
+member of the structure pointed to by
+.IR preg .
+The
+.I re_endp
+member is of type
+.IR const\ char\ * .
+This flag permits inclusion of NULs in the RE;
+they are considered ordinary characters.
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+.PP
+When successful,
+.I regcomp
+returns 0 and fills in the structure pointed to by
+.IR preg .
+One member of that structure
+(other than
+.IR re_endp )
+is publicized:
+.IR re_nsub ,
+of type
+.IR size_t ,
+contains the number of parenthesized subexpressions within the RE
+(except that the value of this member is undefined if the
+REG_NOSUB flag was used).
+If
+.I regcomp
+fails, it returns a non-zero error code;
+see DIAGNOSTICS.
+.PP
+.I Regexec
+matches the compiled RE pointed to by
+.I preg
+against the
+.IR string ,
+subject to the flags in
+.IR eflags ,
+and reports results using
+.IR nmatch ,
+.IR pmatch ,
+and the returned value.
+The RE must have been compiled by a previous invocation of
+.IR regcomp .
+The compiled form is not altered during execution of
+.IR regexec ,
+so a single compiled RE can be used simultaneously by multiple threads.
+.PP
+By default,
+the NUL-terminated string pointed to by
+.I string
+is considered to be the text of an entire line, minus any terminating
+newline.
+The
+.I eflags
+argument is the bitwise OR of zero or more of the following flags:
+.IP REG_NOTBOL \w'REG_STARTEND'u+2n
+The first character of
+the string
+is not the beginning of a line, so the `^' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_NOTEOL
+The NUL terminating
+the string
+does not end a line, so the `$' anchor should not match before it.
+This does not affect the behavior of newlines under REG_NEWLINE.
+.IP REG_STARTEND
+The string is considered to start at
+\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_so\fR
+and to have a terminating NUL located at
+\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_eo\fR
+(there need not actually be a NUL at that location),
+regardless of the value of
+.IR nmatch .
+See below for the definition of
+.IR pmatch
+and
+.IR nmatch .
+This is an extension,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Note that a non-zero \fIrm_so\fR does not imply REG_NOTBOL;
+REG_STARTEND affects only the location of the string,
+not how it is matched.
+.PP
+See
+.ZR
+for a discussion of what is matched in situations where an RE or a
+portion thereof could match any of several substrings of
+.IR string .
+.PP
+Normally,
+.I regexec
+returns 0 for success and the non-zero code REG_NOMATCH for failure.
+Other non-zero error codes may be returned in exceptional situations;
+see DIAGNOSTICS.
+.PP
+If REG_NOSUB was specified in the compilation of the RE,
+or if
+.I nmatch
+is 0,
+.I regexec
+ignores the
+.I pmatch
+argument (but see below for the case where REG_STARTEND is specified).
+Otherwise,
+.I pmatch
+points to an array of
+.I nmatch
+structures of type
+.IR regmatch_t .
+Such a structure has at least the members
+.I rm_so
+and
+.IR rm_eo ,
+both of type
+.I regoff_t
+(a signed arithmetic type at least as large as an
+.I off_t
+and a
+.IR ssize_t ),
+containing respectively the offset of the first character of a substring
+and the offset of the first character after the end of the substring.
+Offsets are measured from the beginning of the
+.I string
+argument given to
+.IR regexec .
+An empty substring is denoted by equal offsets,
+both indicating the character following the empty substring.
+.PP
+The 0th member of the
+.I pmatch
+array is filled in to indicate what substring of
+.I string
+was matched by the entire RE.
+Remaining members report what substring was matched by parenthesized
+subexpressions within the RE;
+member
+.I i
+reports subexpression
+.IR i ,
+with subexpressions counted (starting at 1) by the order of their opening
+parentheses in the RE, left to right.
+Unused entries in the array\(emcorresponding either to subexpressions that
+did not participate in the match at all, or to subexpressions that do not
+exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fIre_nsub\fR)\(emhave both
+.I rm_so
+and
+.I rm_eo
+set to \-1.
+If a subexpression participated in the match several times,
+the reported substring is the last one it matched.
+(Note, as an example in particular, that when the RE `(b*)+' matches `bbb',
+the parenthesized subexpression matches each of the three `b's and then
+an infinite number of empty strings following the last `b',
+so the reported substring is one of the empties.)
+.PP
+If REG_STARTEND is specified,
+.I pmatch
+must point to at least one
+.I regmatch_t
+(even if
+.I nmatch
+is 0 or REG_NOSUB was specified),
+to hold the input offsets for REG_STARTEND.
+Use for output is still entirely controlled by
+.IR nmatch ;
+if
+.I nmatch
+is 0 or REG_NOSUB was specified,
+the value of
+.IR pmatch [0]
+will not be changed by a successful
+.IR regexec .
+.PP
+.I Regerror
+maps a non-zero
+.I errcode
+from either
+.I regcomp
+or
+.I regexec
+to a human-readable, printable message.
+If
+.I preg
+is non-NULL,
+the error code should have arisen from use of
+the
+.I regex_t
+pointed to by
+.IR preg ,
+and if the error code came from
+.IR regcomp ,
+it should have been the result from the most recent
+.I regcomp
+using that
+.IR regex_t .
+.RI ( Regerror
+may be able to supply a more detailed message using information
+from the
+.IR regex_t .)
+.I Regerror
+places the NUL-terminated message into the buffer pointed to by
+.IR errbuf ,
+limiting the length (including the NUL) to at most
+.I errbuf_size
+bytes.
+If the whole message won't fit,
+as much of it as will fit before the terminating NUL is supplied.
+In any case,
+the returned value is the size of buffer needed to hold the whole
+message (including terminating NUL).
+If
+.I errbuf_size
+is 0,
+.I errbuf
+is ignored but the return value is still correct.
+.PP
+If the
+.I errcode
+given to
+.I regerror
+is first ORed with REG_ITOA,
+the ``message'' that results is the printable name of the error code,
+e.g. ``REG_NOMATCH'',
+rather than an explanation thereof.
+If
+.I errcode
+is REG_ATOI,
+then
+.I preg
+shall be non-NULL and the
+.I re_endp
+member of the structure it points to
+must point to the printable name of an error code;
+in this case, the result in
+.I errbuf
+is the decimal digits of
+the numeric value of the error code
+(0 if the name is not recognized).
+REG_ITOA and REG_ATOI are intended primarily as debugging facilities;
+they are extensions,
+compatible with but not specified by POSIX 1003.2,
+and should be used with
+caution in software intended to be portable to other systems.
+Be warned also that they are considered experimental and changes are possible.
+.PP
+.I Regfree
+frees any dynamically-allocated storage associated with the compiled RE
+pointed to by
+.IR preg .
+The remaining
+.I regex_t
+is no longer a valid compiled RE
+and the effect of supplying it to
+.I regexec
+or
+.I regerror
+is undefined.
+.PP
+None of these functions references global variables except for tables
+of constants;
+all are safe for use from multiple threads if the arguments are safe.
+.SH IMPLEMENTATION CHOICES
+There are a number of decisions that 1003.2 leaves up to the implementor,
+either by explicitly saying ``undefined'' or by virtue of them being
+forbidden by the RE grammar.
+This implementation treats them as follows.
+.PP
+See
+.ZR
+for a discussion of the definition of case-independent matching.
+.PP
+There is no particular limit on the length of REs,
+except insofar as memory is limited.
+Memory usage is approximately linear in RE size, and largely insensitive
+to RE complexity, except for bounded repetitions.
+See BUGS for one short RE using them
+that will run almost any system out of memory.
+.PP
+A backslashed character other than one specifically given a magic meaning
+by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs)
+is taken as an ordinary character.
+.PP
+Any unmatched [ is a REG_EBRACK error.
+.PP
+Equivalence classes cannot begin or end bracket-expression ranges.
+The endpoint of one range cannot begin another.
+.PP
+RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255.
+.PP
+A repetition operator (?, *, +, or bounds) cannot follow another
+repetition operator.
+A repetition operator cannot begin an expression or subexpression
+or follow `^' or `|'.
+.PP
+`|' cannot appear first or last in a (sub)expression or after another `|',
+i.e. an operand of `|' cannot be an empty subexpression.
+An empty parenthesized subexpression, `()', is legal and matches an
+empty (sub)string.
+An empty string is not a legal RE.
+.PP
+A `{' followed by a digit is considered the beginning of bounds for a
+bounded repetition, which must then follow the syntax for bounds.
+A `{' \fInot\fR followed by a digit is considered an ordinary character.
+.PP
+`^' and `$' beginning and ending subexpressions in obsolete (``basic'')
+REs are anchors, not ordinary characters.
+.SH SEE ALSO
+grep(1), re_format(7)
+.PP
+POSIX 1003.2, sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.SH DIAGNOSTICS
+Non-zero error codes from
+.I regcomp
+and
+.I regexec
+include the following:
+.PP
+.nf
+.ta \w'REG_ECOLLATE'u+3n
+REG_NOMATCH    regexec() failed to match
+REG_BADPAT     invalid regular expression
+REG_ECOLLATE   invalid collating element
+REG_ECTYPE     invalid character class
+REG_EESCAPE    \e applied to unescapable character
+REG_ESUBREG    invalid backreference number
+REG_EBRACK     brackets [ ] not balanced
+REG_EPAREN     parentheses ( ) not balanced
+REG_EBRACE     braces { } not balanced
+REG_BADBR      invalid repetition count(s) in { }
+REG_ERANGE     invalid character range in [ ]
+REG_ESPACE     ran out of memory
+REG_BADRPT     ?, *, or + operand invalid
+REG_EMPTY      empty (sub)expression
+REG_ASSERT     ``can't happen''\(emyou found a bug
+REG_INVARG     invalid argument, e.g. negative-length string
+.fi
+.SH HISTORY
+Originally written by Henry Spencer at University of Toronto.
+Altered for inclusion in the 4.4BSD distribution.
+.SH BUGS
+This is an alpha release with known defects.
+Please report problems.
+.PP
+There is one known functionality bug.
+The implementation of internationalization is incomplete:
+the locale is always assumed to be the default one of 1003.2,
+and only the collating elements etc. of that locale are available.
+.PP
+The back-reference code is subtle and doubts linger about its correctness
+in complex cases.
+.PP
+.I Regexec
+performance is poor.
+This will improve with later releases.
+.I Nmatch
+exceeding 0 is expensive;
+.I nmatch
+exceeding 1 is worse.
+.I Regexec
+is largely insensitive to RE complexity \fIexcept\fR that back
+references are massively expensive.
+RE length does matter; in particular, there is a strong speed bonus
+for keeping RE length under about 30 characters,
+with most special characters counting roughly double.
+.PP
+.I Regcomp
+implements bounded repetitions by macro expansion,
+which is costly in time and space if counts are large
+or bounded repetitions are nested.
+An RE like, say,
+`((((a{1,100}){1,100}){1,100}){1,100}){1,100}'
+will (eventually) run almost any existing machine out of swap space.
+.PP
+There are suspected problems with response to obscure error conditions.
+Notably,
+certain kinds of internal overflow,
+produced only by truly enormous REs or by multiply nested bounded repetitions,
+are probably not handled well.
+.PP
+Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is
+a special character only in the presence of a previous unmatched `('.
+This can't be fixed until the spec is fixed.
+.PP
+The standard's definition of back references is vague.
+For example, does
+`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?
+Until the standard is clarified,
+behavior in such cases should not be relied on.
+.PP
+The implementation of word-boundary matching is a bit of a kludge,
+and bugs may lurk in combinations of word-boundary matching and anchoring.
diff --git a/dist/nvi/regex/regex.h b/dist/nvi/regex/regex.h
new file mode 100644 (file)
index 0000000..10c5c93
--- /dev/null
@@ -0,0 +1,110 @@
+/*     $NetBSD: regex.h,v 1.1.1.2 2008/05/18 14:31:38 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992 Henry Spencer.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regex.h     8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _REGEX_H_
+#define        _REGEX_H_
+
+#ifdef __REGEX_PRIVATE
+#include "config.h"
+#include "port.h"
+#include "../common/multibyte.h"
+#endif
+
+/* types */
+typedef off_t regoff_t;
+
+typedef struct {
+       int re_magic;
+       size_t re_nsub;         /* number of parenthesized subexpressions */
+       const RCHAR_T *re_endp; /* end pointer for REG_PEND */
+       struct re_guts *re_g;   /* none of your business :-) */
+} regex_t;
+
+typedef struct {
+       regoff_t rm_so;         /* start of match */
+       regoff_t rm_eo;         /* end of match */
+} regmatch_t;
+
+/* regcomp() flags */
+#define        REG_BASIC       0000
+#define        REG_EXTENDED    0001
+#define        REG_ICASE       0002
+#define        REG_NOSUB       0004
+#define        REG_NEWLINE     0010
+#define        REG_NOSPEC      0020
+#define        REG_PEND        0040
+#define        REG_DUMP        0200
+
+/* regerror() flags */
+#define        REG_NOMATCH      1
+#define        REG_BADPAT       2
+#define        REG_ECOLLATE     3
+#define        REG_ECTYPE       4
+#define        REG_EESCAPE      5
+#define        REG_ESUBREG      6
+#define        REG_EBRACK       7
+#define        REG_EPAREN       8
+#define        REG_EBRACE       9
+#define        REG_BADBR       10
+#define        REG_ERANGE      11
+#define        REG_ESPACE      12
+#define        REG_BADRPT      13
+#define        REG_EMPTY       14
+#define        REG_ASSERT      15
+#define        REG_INVARG      16
+#define        REG_ATOI        255     /* convert name to number (!) */
+#define        REG_ITOA        0400    /* convert number to name (!) */
+
+/* regexec() flags */
+#define        REG_NOTBOL      00001
+#define        REG_NOTEOL      00002
+#define        REG_STARTEND    00004
+#define        REG_TRACE       00400   /* tracing of execution */
+#define        REG_LARGE       01000   /* force large representation */
+#define        REG_BACKR       02000   /* force use of backref code */
+
+int    regcomp __P((regex_t *, const RCHAR_T *, int));
+size_t regerror __P((int, const regex_t *, char *, size_t));
+int    regexec __P((const regex_t *,
+           const RCHAR_T *, size_t, regmatch_t [], int));
+void   regfree __P((regex_t *));
+
+#endif /* !_REGEX_H_ */
diff --git a/dist/nvi/regex/regex2.h b/dist/nvi/regex/regex2.h
new file mode 100644 (file)
index 0000000..7c93528
--- /dev/null
@@ -0,0 +1,174 @@
+/*     $NetBSD: regex2.h,v 1.5 2011/11/23 15:43:39 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regex2.h    8.3 (Berkeley) 3/16/94
+ */
+
+/*
+ * First, the stuff that ends up in the outside-world include file
+ = typedef off_t regoff_t;
+ = typedef struct {
+ =     int re_magic;
+ =     size_t re_nsub;         // number of parenthesized subexpressions
+ =     const char *re_endp;    // end pointer for REG_PEND
+ =     struct re_guts *re_g;   // none of your business :-)
+ = } regex_t;
+ = typedef struct {
+ =     regoff_t rm_so;         // start of match
+ =     regoff_t rm_eo;         // end of match
+ = } regmatch_t;
+ */
+/*
+ * internals of regex_t
+ */
+#define        MAGIC1  ((('r'^0200)<<8) | 'e')
+
+/*
+ * The internal representation is a *strip*, a sequence of
+ * operators ending with an endmarker.  (Some terminology etc. is a
+ * historical relic of earlier versions which used multiple strips.)
+ * Certain oddities in the representation are there to permit running
+ * the machinery backwards; in particular, any deviation from sequential
+ * flow must be marked at both its source and its destination.  Some
+ * fine points:
+ *
+ * - OPLUS_ and O_PLUS are *inside* the loop they create.
+ * - OQUEST_ and O_QUEST are *outside* the bypass they create.
+ * - OCH_ and O_CH are *outside* the multi-way branch they create, while
+ *   OOR1 and OOR2 are respectively the end and the beginning of one of
+ *   the branches.  Note that there is an implicit OOR2 following OCH_
+ *   and an implicit OOR1 preceding O_CH.
+ *
+ * In state representations, an operator's bit is on to signify a state
+ * immediately *preceding* "execution" of that operator.
+ */
+typedef char sop;      /* strip operator */
+typedef size_t sopno;
+/* operators                      meaning      operand                 */
+/*                                             (back, fwd are offsets) */
+#define        OEND    (1)             /* endmarker    -                       */
+#define        OCHAR   (2)             /* character    unsigned char           */
+#define        OBOL    (3)             /* left anchor  -                       */
+#define        OEOL    (4)             /* right anchor -                       */
+#define        OANY    (5)             /* .            -                       */
+#define        OANYOF  (6)             /* [...]        set number              */
+#define        OBACK_  (7)             /* begin \d     paren number            */
+#define        O_BACK  (8)             /* end \d       paren number            */
+#define        OPLUS_  (9)             /* + prefix     fwd to suffix           */
+#define        O_PLUS  (10)            /* + suffix     back to prefix          */
+#define        OQUEST_ (11)            /* ? prefix     fwd to suffix           */
+#define        O_QUEST (12)            /* ? suffix     back to prefix          */
+#define        OLPAREN (13)            /* (            fwd to )                */
+#define        ORPAREN (14)            /* )            back to (               */
+#define        OCH_    (15)            /* begin choice fwd to OOR2             */
+#define        OOR1    (16)            /* | pt. 1      back to OOR1 or OCH_    */
+#define        OOR2    (17)            /* | pt. 2      fwd to OOR2 or O_CH     */
+#define        O_CH    (18)            /* end choice   back to OOR1            */
+#define        OBOW    (19)            /* begin word   -                       */
+#define        OEOW    (20)            /* end word     -                       */
+
+/*
+ * Structure for [] character-set representation.  Character sets are
+ * done as bit vectors, grouped 8 to a byte vector for compactness.
+ * The individual set therefore has both a pointer to the byte vector
+ * and a mask to pick out the relevant bit of each byte.  A hash code
+ * simplifies testing whether two sets could be identical.
+ *
+ * This will get trickier for multicharacter collating elements.  As
+ * preliminary hooks for dealing with such things, we also carry along
+ * a string of multi-character elements, and decide the size of the
+ * vectors at run time.
+ */
+typedef struct {
+       uch *ptr;               /* -> uch [csetsize] */
+       uch mask;               /* bit within array */
+       uch hash;               /* hash code */
+       size_t smultis;
+       char *multis;           /* -> char[smulti]  ab\0cd\0ef\0\0 */
+} cset;
+/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
+#define        CHadd(cs, c)    ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
+#define        CHsub(cs, c)    ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
+#define        CHIN(cs, c)     ((cs)->ptr[(uch)(c)] & (cs)->mask)
+#define        MCadd(p, cs, cp)        mcadd(p, cs, cp)        /* regcomp() internal fns */
+#define        MCsub(p, cs, cp)        mcsub(p, cs, cp)
+#define        MCin(p, cs, cp) mcin(p, cs, cp)
+
+/* stuff for character categories */
+typedef RCHAR_T cat_t;
+
+/*
+ * main compiled-expression structure
+ */
+struct re_guts {
+       int magic;
+#              define  MAGIC2  ((('R'^0200)<<8)|'E')
+       sop *strip;             /* malloced area for strip */
+       RCHAR_T *stripdata;     /* malloced area for stripdata */
+       size_t csetsize;        /* number of bits in a cset vector */
+       size_t ncsets;          /* number of csets in use */
+       cset *sets;             /* -> cset [ncsets] */
+       uch *setbits;           /* -> uch[csetsize][ncsets/CHAR_BIT] */
+       int cflags;             /* copy of regcomp() cflags argument */
+       sopno nstates;          /* = number of sops */
+       sopno firststate;       /* the initial OEND (normally 0) */
+       sopno laststate;        /* the final OEND */
+       int iflags;             /* internal flags */
+#              define  USEBOL  01      /* used ^ */
+#              define  USEEOL  02      /* used $ */
+#              define  BAD     04      /* something wrong */
+       size_t nbol;            /* number of ^ used */
+       size_t neol;            /* number of $ used */
+#if 0
+       size_t ncategories;     /* how many character categories */
+       cat_t *categories;      /* ->catspace[-CHAR_MIN] */
+#endif
+       RCHAR_T *must;          /* match must contain this string */
+       size_t mlen;            /* length of must */
+       size_t nsub;            /* copy of re_nsub */
+       int backrefs;           /* does it use back references? */
+       sopno nplus;            /* how deep does it nest +s? */
+       /* catspace must be last */
+#if 0
+       cat_t catspace[1];      /* actually [NC] */
+#endif
+};
+
+/* misc utilities */
+#define OUT    REOF    /* a non-character value */
+#define        ISWORD(c) ((c) == '_' || (ISGRAPH((UCHAR_T)c) && !ISPUNCT((UCHAR_T)c)))
diff --git a/dist/nvi/regex/regexec.c b/dist/nvi/regex/regexec.c
new file mode 100644 (file)
index 0000000..f3d3e06
--- /dev/null
@@ -0,0 +1,180 @@
+/*     $NetBSD: regexec.c,v 1.4 2009/10/31 20:11:53 dsl Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regexec.c   8.2 (Berkeley) 3/16/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regexec.c  8.2 (Berkeley) 3/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * the outer shell of regexec()
+ *
+ * This file includes engine.c *twice*, after muchos fiddling with the
+ * macros that code uses.  This lets the same code operate on two different
+ * representations for state sets.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+#ifdef notdef
+static int nope = 0;           /* for use in asserts; shuts lint up */
+#endif
+
+/* macros for manipulating states, small version */
+#define        states  int
+#define        states1 int             /* for later use in regexec() decision */
+#define        CLEAR(v)        ((v) = 0)
+#define        SET0(v, n)      ((v) &= ~(1 << (n)))
+#define        SET1(v, n)      ((v) |= 1 << (n))
+#define        ISSET(v, n)     ((v) & (1 << (n)))
+#define        ASSIGN(d, s)    ((d) = (s))
+#define        EQ(a, b)        ((a) == (b))
+#define        STATEVARS       int dummy       /* dummy version */
+#define        STATESETUP(m, n)        /* nothing */
+#define        STATETEARDOWN(m)        /* nothing */
+#define        SETUP(v)        ((v) = 0)
+#define        onestate        int
+#define        INIT(o, n)      ((o) = (unsigned)1 << (n))
+#define        INC(o)  ((o) <<= 1)
+#define        ISSTATEIN(v, o) ((v) & (o))
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define        FWD(dst, src, n)        ((dst) |= ((unsigned)(src)&(here)) << (n))
+#define        BACK(dst, src, n)       ((dst) |= ((unsigned)(src)&(here)) >> (n))
+#define        ISSETBACK(v, n) ((v) & ((unsigned)here >> (n)))
+/* function names */
+#define SNAMES                 /* engine.c looks after details */
+
+#include "engine.c"
+
+/* now undo things */
+#undef states
+#undef CLEAR
+#undef SET0
+#undef SET1
+#undef ISSET
+#undef ASSIGN
+#undef EQ
+#undef STATEVARS
+#undef STATESETUP
+#undef STATETEARDOWN
+#undef SETUP
+#undef onestate
+#undef INIT
+#undef INC
+#undef ISSTATEIN
+#undef FWD
+#undef BACK
+#undef ISSETBACK
+#undef SNAMES
+
+/* macros for manipulating states, large version */
+#define        states  char *
+#define        CLEAR(v)        memset(v, 0, m->g->nstates)
+#define        SET0(v, n)      ((v)[n] = 0)
+#define        SET1(v, n)      ((v)[n] = 1)
+#define        ISSET(v, n)     ((v)[n])
+#define        ASSIGN(d, s)    memcpy(d, s, m->g->nstates)
+#define        EQ(a, b)        (memcmp(a, b, m->g->nstates) == 0)
+#define        STATEVARS       int vn; char *space
+#define        STATESETUP(m, nv)       { (m)->space = malloc((nv)*(m)->g->nstates); \
+                               if ((m)->space == NULL) return(REG_ESPACE); \
+                               (m)->vn = 0; }
+#define        STATETEARDOWN(m)        { free((m)->space); }
+#define        SETUP(v)        ((v) = &m->space[m->vn++ * m->g->nstates])
+#define        onestate        int
+#define        INIT(o, n)      ((o) = (n))
+#define        INC(o)  ((o)++)
+#define        ISSTATEIN(v, o) ((v)[o])
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define        FWD(dst, src, n)        ((dst)[here+(n)] |= (src)[here])
+#define        BACK(dst, src, n)       ((dst)[here-(n)] |= (src)[here])
+#define        ISSETBACK(v, n) ((v)[here - (n)])
+/* function names */
+#define        LNAMES                  /* flag */
+
+#include "engine.c"
+
+/*
+ - regexec - interface for matching
+ = extern int regexec(const regex_t *, const char *, size_t, \
+ =                                     regmatch_t [], int);
+ = #define     REG_NOTBOL      00001
+ = #define     REG_NOTEOL      00002
+ = #define     REG_STARTEND    00004
+ = #define     REG_TRACE       00400   // tracing of execution
+ = #define     REG_LARGE       01000   // force large representation
+ = #define     REG_BACKR       02000   // force use of backref code
+ *
+ * We put this here so we can exploit knowledge of the state representation
+ * when choosing which matcher to call.  Also, by this point the matchers
+ * have been prototyped.
+ */
+int                            /* 0 success, REG_NOMATCH failure */
+regexec(const regex_t *preg, const RCHAR_T *string, size_t nmatch, regmatch_t *pmatch, int eflags)
+{
+       register struct re_guts *g = preg->re_g;
+#ifdef REDEBUG
+#      define  GOODFLAGS(f)    (f)
+#else
+#      define  GOODFLAGS(f)    ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
+#endif
+
+       if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
+               return(REG_BADPAT);
+       assert(!(g->iflags&BAD));
+       if (g->iflags&BAD)              /* backstop for no-debug case */
+               return(REG_BADPAT);
+       eflags = GOODFLAGS(eflags);
+
+       if (g->nstates <= (int)(CHAR_BIT*sizeof(states1)) && !(eflags&REG_LARGE))
+               return(smatcher(g, (RCHAR_T *)__UNCONST(string), nmatch, pmatch, eflags));
+       else
+               return(lmatcher(g, (RCHAR_T *)__UNCONST(string), nmatch, pmatch, eflags));
+}
diff --git a/dist/nvi/regex/regfree.c b/dist/nvi/regex/regfree.c
new file mode 100644 (file)
index 0000000..61df17c
--- /dev/null
@@ -0,0 +1,83 @@
+/*     $NetBSD: regfree.c,v 1.2 2009/01/02 00:32:11 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)regfree.c   8.2 (Berkeley) 3/16/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regfree.c  8.2 (Berkeley) 3/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+/*
+ - regfree - free everything
+ = extern void regfree(regex_t *);
+ */
+void
+regfree(regex_t *preg)
+{
+       register struct re_guts *g;
+
+       if (preg->re_magic != MAGIC1)   /* oops */
+               return;                 /* nice to complain, but hard */
+
+       g = preg->re_g;
+       if (g == NULL || g->magic != MAGIC2)    /* oops again */
+               return;
+       preg->re_magic = 0;             /* mark it invalid */
+       g->magic = 0;                   /* mark it invalid */
+
+       if (g->strip != NULL)
+               free((char *)g->strip);
+       if (g->stripdata != NULL)
+               free((char *)g->stripdata);
+       if (g->sets != NULL)
+               free((char *)g->sets);
+       if (g->setbits != NULL)
+               free((char *)g->setbits);
+       if (g->must != NULL)
+               free(g->must);
+       free((char *)g);
+}
diff --git a/dist/nvi/regex/utils.h b/dist/nvi/regex/utils.h
new file mode 100644 (file)
index 0000000..4a6f57a
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: utils.h,v 1.1.1.2 2008/05/18 14:31:39 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer of the University of Toronto.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)utils.h     8.2 (Berkeley) 3/16/94
+ */
+
+/* utility definitions */
+#define        DUPMAX          _POSIX2_RE_DUP_MAX      /* xxx is this right? */
+#define        INFINITY        (DUPMAX + 1)
+#define        NC              (CHAR_MAX - CHAR_MIN + 1)
+typedef unsigned char uch;
+
+/* switch off assertions (if not already off) if no REDEBUG */
+#ifndef REDEBUG
+#ifndef NDEBUG
+#define        NDEBUG  /* no assertions please */
+#endif
+#endif
+#include <assert.h>
+
+/* for old systems with bcopy() but no memmove() */
+#ifdef USEBCOPY
+#define        memmove(d, s, c)        bcopy(s, d, c)
+#endif
diff --git a/dist/nvi/tcl_api/extern.h b/dist/nvi/tcl_api/extern.h
new file mode 100644 (file)
index 0000000..c3ce610
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: extern.h,v 1.1.1.1 2008/05/18 14:31:39 aymeric Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int tcl_init __P((GS *));
diff --git a/dist/nvi/tcl_api/tcl.c b/dist/nvi/tcl_api/tcl.c
new file mode 100644 (file)
index 0000000..a2ddaf7
--- /dev/null
@@ -0,0 +1,854 @@
+/*     $NetBSD: tcl.c,v 1.1.1.2 2008/05/18 14:31:39 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995
+ *     Keith Bostic.  All rights reserved.
+ * Copyright (c) 1995
+ *     George V. Neville-Neil. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: tcl.c,v 8.19 2001/08/24 12:17:27 skimo Exp (Berkeley) Date: 2001/08/24 12:17:27";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "extern.h"
+
+static int  getint __P((Tcl_Interp *, char *, char *, int *));
+static int  getscreenid __P((Tcl_Interp *, SCR **, char *, char *));
+static void msghandler __P((SCR *, mtype_t, char *, size_t));
+
+extern GS *__global_list;                      /* XXX */
+
+/*
+ * INITMESSAGE --
+ *     Macros to point messages at the Tcl message handler.
+ */
+#define        INITMESSAGE(sp)                                                 \
+       scr_msg = sp->wp->scr_msg;                                      \
+       sp->wp->scr_msg = msghandler;
+#define        ENDMESSAGE(sp)                                                  \
+       sp->wp->scr_msg = scr_msg;
+
+/*
+ * tcl_fscreen --
+ *     Return the screen id associated with file name.
+ *
+ * Tcl Command: viFindScreen
+ * Usage: viFindScreen file
+ */
+static int
+tcl_fscreen(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+
+       if (argc != 2) {
+               Tcl_SetResult(interp, "Usage: viFindScreen file", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, NULL, argv[1]))
+               return (TCL_ERROR);
+
+       (void)sprintf(interp->result, "%d", sp->id);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_aline --
+ *     -- Append the string text after the line in lineNumber.
+ *
+ * Tcl Command: viAppendLine
+ * Usage: viAppendLine screenId lineNumber text
+ */
+static int
+tcl_aline(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int lno, rval;
+
+       if (argc != 4) {
+               Tcl_SetResult(interp,
+                   "Usage: viAppendLine screenId lineNumber text", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL) ||
+           getint(interp, "line number", argv[2], &lno))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_aline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_dline --
+ *     Delete lineNum.
+ *
+ * Tcl Command: viDelLine
+ * Usage: viDelLine screenId lineNum
+ */
+static int
+tcl_dline(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int lno, rval;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viDelLine screenId lineNumber", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL) ||
+           getint(interp, "line number", argv[2], &lno))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_dline(sp, (db_recno_t)lno);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_gline --
+ *     Return lineNumber.
+ *
+ * Tcl Command: viGetLine
+ * Usage: viGetLine screenId lineNumber
+ */
+static int
+tcl_gline(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       size_t len;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int lno, rval;
+       char *line, *p;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viGetLine screenId lineNumber", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+       if (getscreenid(interp, &sp, argv[1], NULL) ||
+           getint(interp, "line number", argv[2], &lno))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_gline(sp, (db_recno_t)lno, &p, &len);
+       ENDMESSAGE(sp);
+
+       if (rval)
+               return (TCL_ERROR);
+
+       if ((line = malloc(len + 1)) == NULL)
+               exit(1);                                /* XXX */
+       memmove(line, p, len);
+       line[len] = '\0';
+       Tcl_SetResult(interp, line, TCL_DYNAMIC);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_iline --
+ *     Insert the string text after the line in lineNumber.
+ *
+ * Tcl Command: viInsertLine
+ * Usage: viInsertLine screenId lineNumber text
+ */
+static int
+tcl_iline(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int lno, rval;
+
+       if (argc != 4) {
+               Tcl_SetResult(interp,
+                   "Usage: viInsertLine screenId lineNumber text", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL) ||
+           getint(interp, "line number", argv[2], &lno))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_iline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_lline --
+ *     Return the last line in the screen.
+ *
+ * Tcl Command: viLastLine
+ * Usage: viLastLine screenId
+ */
+static int
+tcl_lline(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       db_recno_t last;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       if (argc != 2) {
+               Tcl_SetResult(interp, "Usage: viLastLine screenId", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_lline(sp, &last);
+       ENDMESSAGE(sp);
+       if (rval)
+               return (TCL_ERROR);
+
+       (void)sprintf(interp->result, "%lu", (unsigned long)last);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_sline --
+ *     Set lineNumber to the text supplied.
+ *
+ * Tcl Command: viSetLine
+ * Usage: viSetLine screenId lineNumber text
+ */
+static int
+tcl_sline(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int lno, rval;
+
+       if (argc != 4) {
+               Tcl_SetResult(interp,
+                   "Usage: viSetLine screenId lineNumber text", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL) ||
+           getint(interp, "line number", argv[2], &lno))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_sline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_getmark --
+ *     Return the mark's cursor position as a list with two elements.
+ *     {line, column}.
+ *
+ * Tcl Command: viGetMark
+ * Usage: viGetMark screenId mark
+ */
+static int
+tcl_getmark(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       MARK cursor;
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char buf[20];
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viGetMark screenId mark", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_getmark(sp, (int)argv[2][0], &cursor);
+       ENDMESSAGE(sp);
+
+       if (rval)
+               return (TCL_ERROR);
+
+       (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
+       Tcl_AppendElement(interp, buf);
+       (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
+       Tcl_AppendElement(interp, buf);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_setmark --
+ *     Set the mark to the line and column numbers supplied.
+ *
+ * Tcl Command: viSetMark
+ * Usage: viSetMark screenId mark line column
+ */
+static int
+tcl_setmark(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       MARK cursor;
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int i, rval;
+
+       if (argc != 5) {
+               Tcl_SetResult(interp,
+                   "Usage: viSetMark screenId mark line column", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       if (getint(interp, "line number", argv[3], &i))
+               return (TCL_ERROR);
+       cursor.lno = i;
+       if (getint(interp, "column number", argv[4], &i))
+               return (TCL_ERROR);
+       cursor.cno = i;
+       INITMESSAGE(sp);
+       rval = api_setmark(sp, (int)argv[2][0], &cursor);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_getcursor --
+ *     Return the current cursor position as a list with two elements.
+ *     {line, column}.
+ *
+ * Tcl Command: viGetCursor
+ * Usage: viGetCursor screenId
+ */
+static int
+tcl_getcursor(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       MARK cursor;
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char buf[20];
+
+       if (argc != 2) {
+               Tcl_SetResult(interp,
+                   "Usage: viGetCursor screenId", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_getcursor(sp, &cursor);
+       ENDMESSAGE(sp);
+
+       if (rval)
+               return (TCL_ERROR);
+
+       (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
+       Tcl_AppendElement(interp, buf);
+       (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
+       Tcl_AppendElement(interp, buf);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_setcursor --
+ *     Set the cursor to the line and column numbers supplied.
+ *
+ * Tcl Command: viSetCursor
+ * Usage: viSetCursor screenId line column
+ */
+static int
+tcl_setcursor(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       MARK cursor;
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int i, rval;
+
+       if (argc != 4) {
+               Tcl_SetResult(interp,
+                   "Usage: viSetCursor screenId line column", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       if (getint(interp, "screen id", argv[2], &i))
+               return (TCL_ERROR);
+       cursor.lno = i;
+       if (getint(interp, "screen id", argv[3], &i))
+               return (TCL_ERROR);
+       cursor.cno = i;
+       INITMESSAGE(sp);
+       rval = api_setcursor(sp, &cursor);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_msg --
+ *     Set the message line to text.
+ *
+ * Tcl Command: viMsg
+ * Usage: viMsg screenId text
+ */
+static int
+tcl_msg(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp, "Usage: viMsg screenId text", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       api_imessage(sp, argv[2]);
+
+       return (TCL_OK);
+}
+
+/*
+ * tcl_iscreen --
+ *     Create a new screen.  If a filename is specified then the screen
+ *     is opened with that file.
+ *
+ * Tcl Command: viNewScreen
+ * Usage: viNewScreen screenId [file]
+ */
+static int
+tcl_iscreen(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp, *nsp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       if (argc != 2 && argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viNewScreen screenId [file]", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_edit(sp, argv[2], &nsp, 1);
+       ENDMESSAGE(sp);
+
+       if (rval)
+               return (TCL_ERROR);
+
+       (void)sprintf(interp->result, "%d", nsp->id);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_escreen --
+ *     End a screen.
+ *
+ * Tcl Command: viEndScreen
+ * Usage: viEndScreen screenId
+ */
+static int
+tcl_escreen(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       if (argc != 2) {
+               Tcl_SetResult(interp,
+                    "Usage: viEndScreen screenId", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_escreen(sp);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_swscreen --
+ *     Change the current focus to screen.
+ *
+ * Tcl Command: viSwitchScreen
+ * Usage: viSwitchScreen screenId screenId
+ */
+static int
+tcl_swscreen(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp, *new;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viSwitchScreen cur_screenId new_screenId",
+                   TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       if (getscreenid(interp, &new, argv[2], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_swscreen(sp, new);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_map --
+ *     Associate a key with a tcl procedure.
+ *
+ * Tcl Command: viMapKey
+ * Usage: viMapKey screenId key tclproc
+ */
+static int
+tcl_map(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char command[256];
+
+       if (argc != 4) {
+               Tcl_SetResult(interp,
+                   "Usage: viMapKey screenId key tclproc", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       (void)snprintf(command, sizeof(command), ":tcl %s\n", argv[3]);
+       rval = api_map(sp, argv[2], command, strlen(command));
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_unmap --
+ *     Unmap a key.
+ *
+ * Tcl Command: viUnmapKey
+ * Usage: viUnmMapKey screenId key
+ */
+static int
+tcl_unmap(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viUnmapKey screenId key", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_unmap(sp, argv[2]);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_opts_set --
+ *     Set an option.
+ *
+ * Tcl Command: viSetOpt
+ * Usage: viSetOpt screenId command
+ */
+static int
+tcl_opts_set(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *setting;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viSetOpt screenId command", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       /*rval = api_opts_set(sp, argv[2]);*/
+       MALLOC(sp, setting, char *, strlen(argv[2])+6);
+       strcpy(setting, ":set ");
+       strcpy(setting+5, argv[2]);
+       rval=api_run_str(sp, setting);
+       free(setting);
+       ENDMESSAGE(sp);
+
+       return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_opts_get --
+       Return the value of an option.
+ *     
+ * Tcl Command: viGetOpt
+ * Usage: viGetOpt screenId option
+ */
+static int
+tcl_opts_get(clientData, interp, argc, argv)
+       ClientData clientData;
+       Tcl_Interp *interp;
+       int argc;
+       char **argv;
+{
+       SCR *sp;
+       void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+       int rval;
+       char *value;
+
+       if (argc != 3) {
+               Tcl_SetResult(interp,
+                   "Usage: viGetOpt screenId option", TCL_STATIC);
+               return (TCL_ERROR);
+       }
+
+       if (getscreenid(interp, &sp, argv[1], NULL))
+               return (TCL_ERROR);
+       INITMESSAGE(sp);
+       rval = api_opts_get(sp, argv[2], &value, NULL);
+       ENDMESSAGE(sp);
+       if (rval)
+               return (TCL_ERROR);
+
+       Tcl_SetResult(interp, value, TCL_DYNAMIC);
+       return (TCL_OK);
+}
+
+/*
+ * tcl_init --
+ *     Create the TCL commands used by nvi.
+ *
+ * PUBLIC: int tcl_init __P((GS *));
+ */
+int
+tcl_init(gp)
+       GS *gp;
+{
+       gp->tcl_interp = Tcl_CreateInterp();
+       if (Tcl_Init(gp->tcl_interp) == TCL_ERROR)
+               return (1);
+
+#define        TCC(name, function) {                                           \
+       Tcl_CreateCommand(gp->tcl_interp, name, function,               \
+           (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);               \
+}
+       TCC("viAppendLine", tcl_aline);
+       TCC("viDelLine", tcl_dline);
+       TCC("viEndScreen", tcl_escreen);
+       TCC("viFindScreen", tcl_fscreen);
+       TCC("viGetCursor", tcl_getcursor);
+       TCC("viGetLine", tcl_gline);
+       TCC("viGetMark", tcl_getmark);
+       TCC("viGetOpt", tcl_opts_get);
+       TCC("viInsertLine", tcl_iline);
+       TCC("viLastLine", tcl_lline);
+       TCC("viMapKey", tcl_map);
+       TCC("viMsg", tcl_msg);
+       TCC("viNewScreen", tcl_iscreen);
+       TCC("viSetCursor", tcl_setcursor);
+       TCC("viSetLine", tcl_sline);
+       TCC("viSetMark", tcl_setmark);
+       TCC("viSetOpt", tcl_opts_set);
+       TCC("viSwitchScreen", tcl_swscreen);
+       TCC("viUnmapKey", tcl_unmap);
+
+       return (0);
+}
+
+/*
+ * getscreenid --
+ *     Get the specified screen pointer.
+ *
+ * XXX
+ * This is fatal.  We can't post a message into vi that we're unable to find
+ * the screen without first finding the screen... So, this must be the first
+ * thing a Tcl routine does, and, if it fails, the last as well.
+ */
+static int 
+getscreenid(interp, spp, id, name)
+       Tcl_Interp *interp;
+       SCR **spp;
+       char *id, *name;
+{
+       int scr_no;
+       char buf[64];
+
+       if (id != NULL && getint(interp, "screen id", id, &scr_no))
+               return (1);
+       if ((*spp = api_fscreen(scr_no, name)) == NULL) {
+               (void)snprintf(buf, sizeof(buf),
+                   "unknown screen id: %s", name == NULL ? id : name);
+               Tcl_SetResult(interp, buf, TCL_VOLATILE);
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * getint --
+ *     Get a Tcl integer.
+ *
+ * XXX
+ * This code assumes that both db_recno_t and size_t are larger than ints.
+ */
+static int
+getint(interp, msg, s, intp)
+       Tcl_Interp *interp;
+       char *msg, *s;
+       int *intp;
+{
+       char buf[64];
+
+       if (Tcl_GetInt(interp, s, intp) == TCL_ERROR)
+               return (1);
+       if (*intp < 0) {
+               (void)snprintf(buf, sizeof(buf),
+                   "illegal %s %s: may not be negative", msg, s);
+               Tcl_SetResult(interp, buf, TCL_VOLATILE);
+               return (1);
+       }
+       return (0);
+}
+
+/*
+ * msghandler --
+ *     Tcl message routine so that error messages are processed in
+ *     Tcl, not in nvi.
+ */
+static void
+msghandler(sp, mtype, msg, len)
+       SCR *sp;
+       mtype_t mtype;
+       char *msg;
+       size_t len;
+{
+       /* Replace the trailing <newline> with an EOS. */
+       msg[len - 1] = '\0';
+
+       Tcl_SetResult(sp->gp->tcl_interp, msg, TCL_VOLATILE);
+}
diff --git a/dist/nvi/tcl_scripts/errors.tcl b/dist/nvi/tcl_scripts/errors.tcl
new file mode 100644 (file)
index 0000000..9bc4407
--- /dev/null
@@ -0,0 +1,44 @@
+#      Id: errors.tcl,v 8.2 1995/11/18 12:59:07 bostic Exp (Berkeley) Date: 1995/11/18 12:59:07
+#
+# File: errors.tcl
+#
+# Author: George V. Neville-Neil
+#
+# Purpose: This file contains vi/tcl code that allows a vi user to parse
+# compiler errors and warnings from a make.out file.
+
+proc findErr {} {
+       global errScreen
+       global currFile
+       global fileScreen
+       set errLine [lindex [viGetCursor $errScreen] 0]
+       set currLine [split [viGetLine $errScreen $errLine] :]
+       set currFile [lindex $currLine 0]
+       set fileScreen [viNewScreen $errScreen $currFile]
+       viSetCursor $fileScreen [lindex $currLine 1] 1
+       viMapKey $viScreenId \ 5 nextErr
+}
+
+proc nextErr {} {
+       global errScreen
+       global fileScreen
+       global currFile
+       set errLine [lindex [viGetCursor $errScreen] 0]
+       set currLine [split [viGetLine $errScreen $errLine] :]
+       if {[string match $currFile [lindex $currLine 0]]} {
+               viSetCursor $fileScreen [lindex $currLine 1] 0
+               viSwitchScreen $fileScreen
+       } else {
+               viEndScreen $fileScreen
+               set currFile [lindex $currLine 0]
+               set fileScreen[viNewScreen $errScreen $currFile]
+               viSetCursor $fileScreen [lindex $currLine 1] 0
+       }
+}
+
+proc initErr {} {
+       global viScreenId
+       global errScreen
+       set errScreen [viNewScreen $viScreenId make.out]
+       viMapKey $viScreenId \ 5 findErr
+}
diff --git a/dist/nvi/tcl_scripts/gnats.tcl b/dist/nvi/tcl_scripts/gnats.tcl
new file mode 100644 (file)
index 0000000..bdd7d83
--- /dev/null
@@ -0,0 +1,95 @@
+#      Id: gnats.tcl,v 8.2 1995/11/18 12:59:07 bostic Exp (Berkeley) Date: 1995/11/18 12:59:07
+#
+proc init {catFile} {
+       global viScreenId
+       global categories
+       set categories {}
+        set categoriesFile [open $catFile r]
+       while {[gets $categoriesFile line] >= 0} {
+               lappend categories $line
+       }
+       close $categoriesFile
+       viMsg $viScreenId $categories
+       viMapKey $viScreenId \ e next
+}
+
+proc next {} {
+       global viScreenId
+       set cursor [viGetCursor $viScreenId]
+       set lineNum [lindex $cursor 0]
+       set line [viGetLine $viScreenId $lineNum]
+       viMsg $viScreenId [lindex $line 0]
+       if {[lindex $line 0] == ">Confidential:"} {
+               confNext $lineNum $line
+       } elseif {[lindex $line 0] == ">Severity:"} {
+               sevNext $lineNum $line
+       } elseif {[lindex $line 0] == ">Priority:"} {
+               priNext $lineNum $line
+       } elseif {[lindex $line 0] == ">Class:"} {
+               classNext $lineNum $line
+       } elseif {[lindex $line 0] == ">Category:"} {
+               catNext $lineNum $line
+       }
+}
+
+proc confNext {lineNum line} {
+       global viScreenId
+       viMsg $viScreenId [lindex $line 1]
+       if {[lindex $line 1] == "yes"} {
+               viSetLine $viScreenId $lineNum ">Confidential: no"
+       } else {
+               viSetLine $viScreenId $lineNum ">Confidential: yes"
+       }
+}
+
+proc sevNext {lineNum line} {
+       global viScreenId
+       viMsg $viScreenId [lindex $line 1]
+       if {[lindex $line 1] == "non-critical"} {
+               viSetLine $viScreenId $lineNum ">Severity: serious"
+       } elseif {[lindex $line 1] == "serious"} {
+               viSetLine $viScreenId $lineNum ">Severity: critical"
+       } elseif {[lindex $line 1] == "critical"} {
+               viSetLine $viScreenId $lineNum ">Severity: non-critical"
+       }
+}
+
+proc priNext {lineNum line} {
+       global viScreenId
+       viMsg $viScreenId [lindex $line 1]
+       if {[lindex $line 1] == "low"} {
+               viSetLine $viScreenId $lineNum ">Priority: medium"
+       } elseif {[lindex $line 1] == "medium"} {
+               viSetLine $viScreenId $lineNum ">Priority: high"
+       } elseif {[lindex $line 1] == "high"} {
+               viSetLine $viScreenId $lineNum ">Priority: low"
+       }
+}
+
+proc classNext {lineNum line} {
+       global viScreenId
+       viMsg $viScreenId [lindex $line 1]
+       if {[lindex $line 1] == "sw-bug"} {
+               viSetLine $viScreenId $lineNum ">Class: doc-bug"
+       } elseif {[lindex $line 1] == "doc-bug"} {
+               viSetLine $viScreenId $lineNum ">Class: change-request"
+       } elseif {[lindex $line 1] == "change-request"} {
+               viSetLine $viScreenId $lineNum ">Class: support"
+       } elseif {[lindex $line 1] == "support"} {
+               viSetLine $viScreenId $lineNum ">Class: sw-bug"
+       }
+}
+
+proc catNext {lineNum line} {
+       global viScreenId
+       global categories
+       viMsg $viScreenId [lindex $line 1]
+       set curr [lsearch -exact $categories [lindex $line 1]]
+       if {$curr == -1} {
+               set curr 0
+       }
+       viMsg $viScreenId $curr
+       viSetLine $viScreenId $lineNum ">Class: [lindex $categories $curr]"
+}
+
+init abekas
diff --git a/dist/nvi/tcl_scripts/mailprocs.tcl b/dist/nvi/tcl_scripts/mailprocs.tcl
new file mode 100644 (file)
index 0000000..5ead7a5
--- /dev/null
@@ -0,0 +1,115 @@
+#      Id: mailprocs.tcl,v 8.3 1996/04/29 12:31:35 bostic Exp (Berkeley) Date: 1996/04/29 12:31:35
+#
+proc validLine {} {
+       global viScreenId
+       set line [viGetLine $viScreenId [lindex [viGetCursor $viScreenId] 0]]
+       if {[string compare [lindex [split $line :] 0]  "To"] == 0} {
+               set addrs [lindex [split $line :] 1]
+               foreach name [split $addrs ,] {
+                       isValid [string trim $name]
+               }
+       }
+}
+
+proc valid {target} {
+       set found 0
+       set aliasFile [open "~/Mail/aliases" r]
+       while {[gets $aliasFile line] >= 0} {
+               set name [lindex [split $line :] 0]
+               set address [lindex [split $line :] 1]
+               if {[string compare $target $name] == 0} {
+                       set found 1
+                       break
+               }
+       }
+       close $aliasFile
+       if {$found == 1} {
+               return $address
+       } else {
+               return $found
+       }
+}
+
+proc isValid {target} {
+       global viScreenId
+       set address [valid $target]
+       if {$address != 0} {
+               viMsg $viScreenId "$target is [string trim $address]"
+       } else {
+               viMsg $viScreenId "$target not found"
+       }
+}
+
+proc isAliasedLine {} {
+       global viScreenId
+       set line [viGetLine $viScreenId [lindex [viGetCursor $viScreenId] 0]]
+       if {[string match [lindex [split $line :] 0] "*To"] == 0} {
+               set addrs [lindex [split $line :] 1]
+               foreach name [split $addrs ,] {
+                       isAliased [string trim $name]
+               }
+       }
+}
+
+proc aliased {target} {
+       set found 0
+       set aliasFile [open "~/Mail/aliases" r]
+       while {[gets $aliasFile line] >= 0} {
+               set name [lindex [split $line :] 0]
+               set address [lindex [split $line :] 1]
+               if {[string compare $target [string trim $address]] == 0} {
+                       set found 1
+                       break
+               }
+       }
+       close $aliasFile
+
+       return $found
+}
+
+proc isAliased {target} {
+       global viScreenId
+       set found [aliased $target]
+
+       if {$found} {
+               viMsg $viScreenId "$target is aliased to [string trim $name]"
+       } else {
+               viMsg $viScreenId "$target not aliased"
+       }
+}
+
+proc appendAlias {target address} {
+       if {![aliased $target]} {
+               set aliasFile [open "~/Mail/aliases" a]
+               puts $aliasFile "$target: $address"
+       }
+       close $aliasFile
+}
+
+proc expand {} {
+       global viScreenId
+       set row [lindex [viGetCursor $viScreenId] 0]]
+       set column [lindex [viGetCursor $viScreenId] 1]]
+       set line [viGetLine $viScreenId $row]
+       while {$column < [string length $line] && \
+               [string index $line $column] != ' '} {
+               append $target [string index $line $column]
+               incr $column
+       }
+       set found [isValid $target]
+}
+
+proc cite {} {
+       global viScreenId
+       global viStartLine
+       global viStopLine
+       for {set i $viStartLine} {$i <= $viStopLine} {incr i} {
+               set newLine "> "
+               append newLine [viGetLine $viScreenId $i]
+               viSetLine $viScreenId $i $newLine
+       }
+}
+
+global viScreenId
+viMapKey $viScreenId \ 1 isAliasedLine
+viMapKey $viScreenId \ 2 validLine
diff --git a/dist/nvi/tcl_scripts/wc.tcl b/dist/nvi/tcl_scripts/wc.tcl
new file mode 100644 (file)
index 0000000..357c654
--- /dev/null
@@ -0,0 +1,16 @@
+#      Id: wc.tcl,v 8.2 1995/11/18 12:59:12 bostic Exp (Berkeley) Date: 1995/11/18 12:59:12
+#
+proc wc {} {
+       global viScreenId
+       global viStartLine
+       global viStopLine
+
+       set lines [viLastLine $viScreenId]
+       set output ""
+       set words 0
+       for {set i $viStartLine} {$i <= $viStopLine} {incr i} {
+               set outLine [split [string trim [viGetLine $viScreenId $i]]]
+               set words [expr $words + [llength $outLine]]
+       }
+       viMsg $viScreenId "$words words"
+}
diff --git a/dist/nvi/vi/extern.h b/dist/nvi/vi/extern.h
new file mode 100644 (file)
index 0000000..312b475
--- /dev/null
@@ -0,0 +1,150 @@
+/*     $NetBSD: extern.h,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/* Do not edit: automatically built by build/distrib. */
+int cs_init __P((SCR *, VCS *));
+int cs_next __P((SCR *, VCS *));
+int cs_fspace __P((SCR *, VCS *));
+int cs_fblank __P((SCR *, VCS *));
+int cs_prev __P((SCR *, VCS *));
+int cs_bblank __P((SCR *, VCS *));
+int v_at __P((SCR *, VICMD *));
+int v_chrepeat __P((SCR *, VICMD *));
+int v_chrrepeat __P((SCR *, VICMD *));
+int v_cht __P((SCR *, VICMD *));
+int v_chf __P((SCR *, VICMD *));
+int v_chT __P((SCR *, VICMD *));
+int v_chF __P((SCR *, VICMD *));
+int v_delete __P((SCR *, VICMD *));
+int v_erepaint __P((SCR *, EVENT *));
+int v_event __P((SCR *, VICMD *));
+int v_again __P((SCR *, VICMD *));
+int v_exmode __P((SCR *, VICMD *));
+int v_join __P((SCR *, VICMD *));
+int v_shiftl __P((SCR *, VICMD *));
+int v_shiftr __P((SCR *, VICMD *));
+int v_suspend __P((SCR *, VICMD *));
+int v_switch __P((SCR *, VICMD *));
+int v_tagpush __P((SCR *, VICMD *));
+int v_tagpop __P((SCR *, VICMD *));
+int v_filter __P((SCR *, VICMD *));
+int v_exec_ex __P((SCR *, VICMD *, EXCMD *));
+int v_ex __P((SCR *, VICMD *));
+int v_ecl_exec __P((SCR *));
+int v_increment __P((SCR *, VICMD *));
+int v_screen_copy __P((SCR *, SCR *));
+int v_screen_end __P((SCR *));
+int v_optchange __P((SCR *, int, const char *, u_long *));
+int v_iA __P((SCR *, VICMD *));
+int v_ia __P((SCR *, VICMD *));
+int v_iI __P((SCR *, VICMD *));
+int v_ii __P((SCR *, VICMD *));
+int v_iO __P((SCR *, VICMD *));
+int v_io __P((SCR *, VICMD *));
+int v_change __P((SCR *, VICMD *));
+int v_Replace __P((SCR *, VICMD *));
+int v_subst __P((SCR *, VICMD *));
+int v_left __P((SCR *, VICMD *));
+int v_cfirst __P((SCR *, VICMD *));
+int v_first __P((SCR *, VICMD *));
+int v_ncol __P((SCR *, VICMD *));
+int v_zero __P((SCR *, VICMD *));
+int v_mark __P((SCR *, VICMD *));
+int v_bmark __P((SCR *, VICMD *));
+int v_fmark __P((SCR *, VICMD *));
+int v_emark __P((SCR *, VICMD *));
+int v_match __P((SCR *, VICMD *));
+int v_paragraphf __P((SCR *, VICMD *));
+int v_paragraphb __P((SCR *, VICMD *));
+int v_buildps __P((SCR *, const char *, const char *));
+int v_Put __P((SCR *, VICMD *));
+int v_put __P((SCR *, VICMD *));
+int v_redraw __P((SCR *, VICMD *));
+int v_replace __P((SCR *, VICMD *));
+int v_right __P((SCR *, VICMD *));
+int v_dollar __P((SCR *, VICMD *));
+int v_screen __P((SCR *, VICMD *));
+int v_lgoto __P((SCR *, VICMD *));
+int v_home __P((SCR *, VICMD *));
+int v_middle __P((SCR *, VICMD *));
+int v_bottom __P((SCR *, VICMD *));
+int v_up __P((SCR *, VICMD *));
+int v_cr __P((SCR *, VICMD *));
+int v_down __P((SCR *, VICMD *));
+int v_hpageup __P((SCR *, VICMD *));
+int v_hpagedown __P((SCR *, VICMD *));
+int v_pagedown __P((SCR *, VICMD *));
+int v_pageup __P((SCR *, VICMD *));
+int v_lineup __P((SCR *, VICMD *));
+int v_linedown __P((SCR *, VICMD *));
+int v_searchb __P((SCR *, VICMD *));
+int v_searchf __P((SCR *, VICMD *));
+int v_searchN __P((SCR *, VICMD *));
+int v_searchn __P((SCR *, VICMD *));
+int v_searchw __P((SCR *, VICMD *));
+int v_esearch __P((SCR *, VICMD *));
+int v_correct __P((SCR *, VICMD *, int));
+int v_sectionf __P((SCR *, VICMD *));
+int v_sectionb __P((SCR *, VICMD *));
+int v_sentencef __P((SCR *, VICMD *));
+int v_sentenceb __P((SCR *, VICMD *));
+int v_status __P((SCR *, VICMD *));
+int v_tcmd __P((SCR *, VICMD *, ARG_CHAR_T, u_int));
+int v_txt __P((SCR *, VICMD *, MARK *,
+   const CHAR_T *, size_t, ARG_CHAR_T, db_recno_t, u_long, u_int32_t));
+int v_txt_auto __P((SCR *, db_recno_t, TEXT *, size_t, TEXT *));
+int v_ulcase __P((SCR *, VICMD *));
+int v_mulcase __P((SCR *, VICMD *));
+int v_Undo __P((SCR *, VICMD *));
+int v_undo __P((SCR *, VICMD *));
+void v_eof __P((SCR *, MARK *));
+void v_eol __P((SCR *, MARK *));
+void v_nomove __P((SCR *));
+void v_sof __P((SCR *, MARK *));
+void v_sol __P((SCR *));
+int v_isempty __P((CHAR_T *, size_t));
+void v_emsg __P((SCR *, const char *, vim_t));
+int v_wordW __P((SCR *, VICMD *));
+int v_wordw __P((SCR *, VICMD *));
+int v_wordE __P((SCR *, VICMD *));
+int v_worde __P((SCR *, VICMD *));
+int v_wordB __P((SCR *, VICMD *));
+int v_wordb __P((SCR *, VICMD *));
+int v_xchar __P((SCR *, VICMD *));
+int v_Xchar __P((SCR *, VICMD *));
+int v_yank __P((SCR *, VICMD *));
+int v_z __P((SCR *, VICMD *));
+int vs_crel __P((SCR *, long));
+int v_zexit __P((SCR *, VICMD *));
+int vi __P((SCR **));
+int v_curword __P((SCR *));
+int vs_line __P((SCR *, SMAP *, size_t *, size_t *));
+int vs_number __P((SCR *));
+void vs_busy __P((SCR *, const char *, busy_t));
+void vs_home __P((SCR *));
+void vs_update __P((SCR *, const char *, const CHAR_T *));
+void vs_msg __P((SCR *, mtype_t, char *, size_t));
+int vs_ex_resolve __P((SCR *, int *));
+int vs_resolve __P((SCR *, SCR *, int));
+int vs_refresh __P((SCR *, int));
+int vs_column __P((SCR *, size_t *));
+size_t vs_screens __P((SCR *, db_recno_t, size_t *));
+size_t vs_columns __P((SCR *, CHAR_T *, db_recno_t, size_t *, size_t *));
+size_t vs_rcm __P((SCR *, db_recno_t, int));
+size_t vs_colpos __P((SCR *, db_recno_t, size_t));
+int vs_change __P((SCR *, db_recno_t, lnop_t));
+int vs_sm_fill __P((SCR *, db_recno_t, pos_t));
+int vs_sm_scroll __P((SCR *, MARK *, db_recno_t, scroll_t));
+int vs_sm_1up __P((SCR *));
+int vs_sm_1down __P((SCR *));
+int vs_sm_next __P((SCR *, SMAP *, SMAP *));
+int vs_sm_prev __P((SCR *, SMAP *, SMAP *));
+int vs_sm_cursor __P((SCR *, SMAP **));
+int vs_sm_position __P((SCR *, MARK *, u_long, pos_t));
+db_recno_t vs_sm_nlines __P((SCR *, SMAP *, db_recno_t, size_t));
+int vs_split __P((SCR *, SCR *, int));
+int vs_vsplit __P((SCR *, SCR *));
+int vs_discard __P((SCR *, SCR **));
+int vs_fg __P((SCR *, SCR **, CHAR_T *, int));
+int vs_bg __P((SCR *));
+int vs_swap __P((SCR *, SCR **, const char *));
+int vs_resize __P((SCR *, long, adj_t));
diff --git a/dist/nvi/vi/getc.c b/dist/nvi/vi/getc.c
new file mode 100644 (file)
index 0000000..b02dd9a
--- /dev/null
@@ -0,0 +1,224 @@
+/*     $NetBSD: getc.c,v 1.5 2012/01/21 19:29:41 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: getc.c,v 10.12 2001/06/25 15:19:30 skimo Exp (Berkeley) Date: 2001/06/25 15:19:30";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * Character stream routines --
+ *     These routines return the file a character at a time.  There are two
+ *     special cases.  First, the end of a line, end of a file, start of a
+ *     file and empty lines are returned as special cases, and no character
+ *     is returned.  Second, empty lines include lines that have only white
+ *     space in them, because the vi search functions don't care about white
+ *     space, and this makes it easier for them to be consistent.
+ */
+
+/*
+ * cs_init --
+ *     Initialize character stream routines.
+ *
+ * PUBLIC: int cs_init __P((SCR *, VCS *));
+ */
+int
+cs_init(SCR *sp, VCS *csp)
+{
+       int isempty;
+
+       if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) {
+               if (isempty)
+                       msgq(sp, M_BERR, "177|Empty file");
+               return (1);
+       }
+       if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
+               csp->cs_cno = 0;
+               csp->cs_flags = CS_EMP;
+       } else {
+               csp->cs_flags = 0;
+               csp->cs_ch = csp->cs_bp[csp->cs_cno];
+       }
+       return (0);
+}
+
+/*
+ * cs_next --
+ *     Retrieve the next character.
+ *
+ * PUBLIC: int cs_next __P((SCR *, VCS *));
+ */
+int
+cs_next(SCR *sp, VCS *csp)
+{
+       CHAR_T *p;
+
+       switch (csp->cs_flags) {
+       case CS_EMP:                            /* EMP; get next line. */
+       case CS_EOL:                            /* EOL; get next line. */
+               if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) {
+                       --csp->cs_lno;
+                       csp->cs_flags = CS_EOF;
+               } else {
+                       csp->cs_bp = p;
+                       if (csp->cs_len == 0 ||
+                           v_isempty(csp->cs_bp, csp->cs_len)) {
+                               csp->cs_cno = 0;
+                               csp->cs_flags = CS_EMP;
+                       } else {
+                               csp->cs_flags = 0;
+                               csp->cs_ch = csp->cs_bp[csp->cs_cno = 0];
+                       }
+               }
+               break;
+       case 0:
+               if (csp->cs_cno == csp->cs_len - 1)
+                       csp->cs_flags = CS_EOL;
+               else
+                       csp->cs_ch = csp->cs_bp[++csp->cs_cno];
+               break;
+       case CS_EOF:                            /* EOF. */
+               break;
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       return (0);
+}
+
+/*
+ * cs_fspace --
+ *     If on a space, eat forward until something other than a
+ *     whitespace character.
+ *
+ * XXX
+ * Semantics of checking the current character were coded for the fword()
+ * function -- once the other word routines are converted, they may have
+ * to change.
+ *
+ * PUBLIC: int cs_fspace __P((SCR *, VCS *));
+ */
+int
+cs_fspace(SCR *sp, VCS *csp)
+{
+       if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch))
+               return (0);
+       for (;;) {
+               if (cs_next(sp, csp))
+                       return (1);
+               if (csp->cs_flags != 0 || !ISBLANK2(csp->cs_ch))
+                       break;
+       }
+       return (0);
+}
+
+/*
+ * cs_fblank --
+ *     Eat forward to the next non-whitespace character.
+ *
+ * PUBLIC: int cs_fblank __P((SCR *, VCS *));
+ */
+int
+cs_fblank(SCR *sp, VCS *csp)
+{
+       for (;;) {
+               if (cs_next(sp, csp))
+                       return (1);
+               if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
+                   (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch)))
+                       continue;
+               break;
+       }
+       return (0);
+}
+
+/*
+ * cs_prev --
+ *     Retrieve the previous character.
+ *
+ * PUBLIC: int cs_prev __P((SCR *, VCS *));
+ */
+int
+cs_prev(SCR *sp, VCS *csp)
+{
+       switch (csp->cs_flags) {
+       case CS_EMP:                            /* EMP; get previous line. */
+       case CS_EOL:                            /* EOL; get previous line. */
+               if (csp->cs_lno == 1) {         /* SOF. */
+                       csp->cs_flags = CS_SOF;
+                       break;
+               }
+               if (db_get(sp,                  /* The line should exist. */
+                   --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) {
+                       ++csp->cs_lno;
+                       return (1);
+               }
+               if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
+                       csp->cs_cno = 0;
+                       csp->cs_flags = CS_EMP;
+               } else {
+                       csp->cs_flags = 0;
+                       csp->cs_cno = csp->cs_len - 1;
+                       csp->cs_ch = csp->cs_bp[csp->cs_cno];
+               }
+               break;
+       case CS_EOF:                            /* EOF: get previous char. */
+       case 0:
+               if (csp->cs_cno == 0)
+                       if (csp->cs_lno == 1)
+                               csp->cs_flags = CS_SOF;
+                       else
+                               csp->cs_flags = CS_EOL;
+               else
+                       csp->cs_ch = csp->cs_bp[--csp->cs_cno];
+               break;
+       case CS_SOF:                            /* SOF. */
+               break;
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+       return (0);
+}
+
+/*
+ * cs_bblank --
+ *     Eat backward to the next non-whitespace character.
+ *
+ * PUBLIC: int cs_bblank __P((SCR *, VCS *));
+ */
+int
+cs_bblank(SCR *sp, VCS *csp)
+{
+       for (;;) {
+               if (cs_prev(sp, csp))
+                       return (1);
+               if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
+                   (csp->cs_flags == 0 && ISBLANK2(csp->cs_ch)))
+                       continue;
+               break;
+       }
+       return (0);
+}
diff --git a/dist/nvi/vi/v_at.c b/dist/nvi/vi/v_at.c
new file mode 100644 (file)
index 0000000..5ff291c
--- /dev/null
@@ -0,0 +1,117 @@
+/*     $NetBSD: v_at.c,v 1.4 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_at.c,v 10.11 2001/06/25 15:19:30 skimo Exp (Berkeley) Date: 2001/06/25 15:19:30";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_at -- @
+ *     Execute a buffer.
+ *
+ * PUBLIC: int v_at __P((SCR *, VICMD *));
+ */
+int
+v_at(SCR *sp, VICMD *vp)
+{
+       CB *cbp;
+       ARG_CHAR_T name;
+       TEXT *tp;
+       size_t len;
+       char nbuf[20];
+       CHAR_T wbuf[20];
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /*
+        * !!!
+        * Historically, [@*]<carriage-return> and [@*][@*] executed the most
+        * recently executed buffer in ex mode.  In vi mode, only @@ repeated
+        * the last buffer.  We change historic practice and make @* work from
+        * vi mode as well, it's simpler and more consistent.
+        *
+        * My intent is that *[buffer] will, in the future, pass the buffer to
+        * whatever interpreter is loaded.
+        */
+       name = F_ISSET(vp, VC_BUFFER) ? vp->buffer : '@';
+       if (name == '@' || name == '*') {
+               if (!F_ISSET(sp, SC_AT_SET)) {
+                       ex_emsg(sp, NULL, EXM_NOPREVBUF);
+                       return (1);
+               }
+               name = sp->at_lbuf;
+       }
+       F_SET(sp, SC_AT_SET);
+
+       CBNAME(sp, cbp, name);
+       if (cbp == NULL) {
+               ex_emsg(sp, (char *)KEY_NAME(sp, name), EXM_EMPTYBUF);
+               return (1);
+       }
+
+       /* Save for reuse. */
+       sp->at_lbuf = name;
+
+       /*
+        * The buffer is executed in vi mode, while in vi mode, so simply
+        * push it onto the terminal queue and continue.
+        *
+        * !!!
+        * Historic practice is that if the buffer was cut in line mode,
+        * <newlines> were appended to each line as it was pushed onto
+        * the stack.  If the buffer was cut in character mode, <newlines>
+        * were appended to all lines but the last one.
+        *
+        * XXX
+        * Historic practice is that execution of an @ buffer could be
+        * undone by a single 'u' command, i.e. the changes were grouped
+        * together.  We don't get this right; I'm waiting for the new DB
+        * logging code to be available.
+        */
+       for (tp = cbp->textq.cqh_last;
+           tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) {
+               static CHAR_T nl[] = { '\n', 0 };
+               if (((F_ISSET(cbp, CB_LMODE) ||
+                   tp->q.cqe_next != (void *)&cbp->textq) &&
+                   v_event_push(sp, NULL, nl, 1, 0)) ||
+                   v_event_push(sp, NULL, tp->lb, tp->len, 0))
+                       return (1);
+       }
+
+       /*
+        * !!!
+        * If any count was supplied, it applies to the first command in the
+        * at buffer.
+        */
+       if (F_ISSET(vp, VC_C1SET)) {
+               len = snprintf(nbuf, sizeof(nbuf), "%lu", vp->count);
+               CHAR2INT(sp, nbuf, len, wp, wlen);
+               MEMCPYW(wbuf, wp, wlen);
+               if (v_event_push(sp, NULL, wp, wlen, 0))
+                       return (1);
+       }
+       return (0);
+}
diff --git a/dist/nvi/vi/v_ch.c b/dist/nvi/vi/v_ch.c
new file mode 100644 (file)
index 0000000..efb79af
--- /dev/null
@@ -0,0 +1,284 @@
+/*     $NetBSD: v_ch.c,v 1.2 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_ch.c,v 10.10 2001/06/25 15:19:30 skimo Exp (Berkeley) Date: 2001/06/25 15:19:30";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static void notfound __P((SCR *, ARG_CHAR_T));
+static void noprev __P((SCR *));
+
+/*
+ * v_chrepeat -- [count];
+ *     Repeat the last F, f, T or t search.
+ *
+ * PUBLIC: int v_chrepeat __P((SCR *, VICMD *));
+ */
+int
+v_chrepeat(SCR *sp, VICMD *vp)
+{
+       vp->character = VIP(sp)->lastckey;
+
+       switch (VIP(sp)->csearchdir) {
+       case CNOTSET:
+               noprev(sp);
+               return (1);
+       case FSEARCH:
+               return (v_chF(sp, vp));
+       case fSEARCH:
+               return (v_chf(sp, vp));
+       case TSEARCH:
+               return (v_chT(sp, vp));
+       case tSEARCH:
+               return (v_cht(sp, vp));
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
+
+/*
+ * v_chrrepeat -- [count],
+ *     Repeat the last F, f, T or t search in the reverse direction.
+ *
+ * PUBLIC: int v_chrrepeat __P((SCR *, VICMD *));
+ */
+int
+v_chrrepeat(SCR *sp, VICMD *vp)
+{
+       cdir_t savedir;
+       int rval;
+
+       vp->character = VIP(sp)->lastckey;
+       savedir = VIP(sp)->csearchdir;
+
+       switch (VIP(sp)->csearchdir) {
+       case CNOTSET:
+               noprev(sp);
+               return (1);
+       case FSEARCH:
+               rval = v_chf(sp, vp);
+               break;
+       case fSEARCH:
+               rval = v_chF(sp, vp);
+               break;
+       case TSEARCH:
+               rval = v_cht(sp, vp);
+               break;
+       case tSEARCH:
+               rval = v_chT(sp, vp);
+               break;
+       default:
+               abort();
+       }
+       VIP(sp)->csearchdir = savedir;
+       return (rval);
+}
+
+/*
+ * v_cht -- [count]tc
+ *     Search forward in the line for the character before the next
+ *     occurrence of the specified character.
+ *
+ * PUBLIC: int v_cht __P((SCR *, VICMD *));
+ */
+int
+v_cht(SCR *sp, VICMD *vp)
+{
+       if (v_chf(sp, vp))
+               return (1);
+
+       /*
+        * v_chf places the cursor on the character, where the 't'
+        * command wants it to its left.  We know this is safe since
+        * we had to move right for v_chf() to have succeeded.
+        */
+       --vp->m_stop.cno;
+
+       /*
+        * Make any necessary correction to the motion decision made
+        * by the v_chf routine.
+        */
+       if (!ISMOTION(vp))
+               vp->m_final = vp->m_stop;
+
+       VIP(sp)->csearchdir = tSEARCH;
+       return (0);
+}
+
+/*
+ * v_chf -- [count]fc
+ *     Search forward in the line for the next occurrence of the
+ *     specified character.
+ *
+ * PUBLIC: int v_chf __P((SCR *, VICMD *));
+ */
+int
+v_chf(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       u_long cnt;
+       int isempty;
+       ARG_CHAR_T key;
+       CHAR_T *endp, *p, *startp;
+
+       /*
+        * !!!
+        * If it's a dot command, it doesn't reset the key for which we're
+        * searching, e.g. in "df1|f2|.|;", the ';' searches for a '2'.
+        */
+       key = vp->character;
+       if (!F_ISSET(vp, VC_ISDOT))
+               VIP(sp)->lastckey = key;
+       VIP(sp)->csearchdir = fSEARCH;
+
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (isempty)
+                       goto empty;
+               return (1);
+       }
+
+       if (len == 0) {
+empty:         notfound(sp, key);
+               return (1);
+       }
+
+       endp = (startp = p) + len;
+       p += vp->m_start.cno;
+       for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
+               while (++p < endp && *p != key);
+               if (p == endp) {
+                       notfound(sp, key);
+                       return (1);
+               }
+       }
+
+       vp->m_stop.cno = p - startp;
+
+       /*
+        * Non-motion commands move to the end of the range.
+        * Delete and yank stay at the start, ignore others.
+        */
+       vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_chT -- [count]Tc
+ *     Search backward in the line for the character after the next
+ *     occurrence of the specified character.
+ *
+ * PUBLIC: int v_chT __P((SCR *, VICMD *));
+ */
+int
+v_chT(SCR *sp, VICMD *vp)
+{
+       if (v_chF(sp, vp))
+               return (1);
+
+       /*
+        * v_chF places the cursor on the character, where the 'T'
+        * command wants it to its right.  We know this is safe since
+        * we had to move left for v_chF() to have succeeded.
+        */
+       ++vp->m_stop.cno;
+       vp->m_final = vp->m_stop;
+
+       VIP(sp)->csearchdir = TSEARCH;
+       return (0);
+}
+
+/*
+ * v_chF -- [count]Fc
+ *     Search backward in the line for the next occurrence of the
+ *     specified character.
+ *
+ * PUBLIC: int v_chF __P((SCR *, VICMD *));
+ */
+int
+v_chF(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       u_long cnt;
+       int isempty;
+       ARG_CHAR_T key;
+       CHAR_T *endp, *p;
+
+       /*
+        * !!!
+        * If it's a dot command, it doesn't reset the key for which
+        * we're searching, e.g. in "df1|f2|.|;", the ';' searches
+        * for a '2'.
+        */
+       key = vp->character;
+       if (!F_ISSET(vp, VC_ISDOT))
+               VIP(sp)->lastckey = key;
+       VIP(sp)->csearchdir = FSEARCH;
+
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (isempty)
+                       goto empty;
+               return (1);
+       }
+
+       if (len == 0) {
+empty:         notfound(sp, key);
+               return (1);
+       }
+
+       endp = p - 1;
+       p += vp->m_start.cno;
+       for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
+               while (--p > endp && *p != key);
+               if (p == endp) {
+                       notfound(sp, key);
+                       return (1);
+               }
+       }
+
+       vp->m_stop.cno = (p - endp) - 1;
+
+       /*
+        * All commands move to the end of the range.  Motion commands
+        * adjust the starting point to the character before the current
+        * one.
+        */
+       vp->m_final = vp->m_stop;
+       if (ISMOTION(vp))
+               --vp->m_start.cno;
+       return (0);
+}
+
+static void
+noprev(SCR *sp)
+{
+       msgq(sp, M_BERR, "178|No previous F, f, T or t search");
+}
+
+static void
+notfound(SCR *sp, ARG_CHAR_T ch)
+{
+       msgq(sp, M_BERR, "179|%s not found", KEY_NAME(sp, ch));
+}
diff --git a/dist/nvi/vi/v_cmd.c b/dist/nvi/vi/v_cmd.c
new file mode 100644 (file)
index 0000000..933dae2
--- /dev/null
@@ -0,0 +1,508 @@
+/*     $NetBSD: v_cmd.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_cmd.c,v 10.9 1996/03/28 15:18:39 bostic Exp (Berkeley) Date: 1996/03/28 15:18:39";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+#define VINULLKEY { NULL, 0, NULL, NULL }
+/*
+ * This array maps keystrokes to vi command functions.  It is known
+ * in ex/ex_usage.c that it takes four columns to name a vi character.
+ */
+VIKEYS const vikeys [MAXVIKEY + 1] = {
+/* 000 NUL -- The code in vi.c expects key 0 to be undefined. */
+       VINULLKEY,
+/* 001  ^A */
+       {v_searchw,     V_ABS|V_CNT|V_MOVE|V_KEYW|VM_CUTREQ|VM_RCM_SET,
+           "[count]^A",
+           "^A search forward for cursor word"},
+/* 002  ^B */
+       {v_pageup,      V_CNT|VM_RCM_SET,
+           "[count]^B",
+           "^B scroll up by screens"},
+/* 003  ^C */
+       {NULL,          0,
+           "^C",
+           "^C interrupt an operation (e.g. read, write, search)"},
+/* 004  ^D */
+       {v_hpagedown,   V_CNT|VM_RCM_SET,
+           "[count]^D",
+           "^D scroll down by half screens (setting count)"},
+/* 005  ^E */
+       {v_linedown,    V_CNT,
+           "[count]^E",
+           "^E scroll down by lines"},
+/* 006  ^F */
+       {v_pagedown,    V_CNT|VM_RCM_SET,
+           "[count]^F",
+           "^F scroll down by screens"},
+/* 007  ^G */
+       {v_status,      0,
+           "^G",
+           "^G file status"},
+/* 010  ^H */
+       {v_left,        V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]^H",
+           "^H move left by characters"},
+/* 011  ^I */
+       VINULLKEY,
+/* 012  ^J */
+       {v_down,        V_CNT|V_MOVE|VM_LMODE|VM_RCM,
+           "[count]^J",
+           "^J move down by lines"},
+/* 013  ^K */
+       VINULLKEY,
+/* 014  ^L */
+       {v_redraw,      0,
+           "^L",
+           "^L redraw screen"},
+/* 015  ^M */
+       {v_cr,          V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
+           "[count]^M",
+           "^M move down by lines (to first non-blank)"},
+/* 016  ^N */
+       {v_down,        V_CNT|V_MOVE|VM_LMODE|VM_RCM,
+           "[count]^N",
+           "^N move down by lines"},
+/* 017  ^O */
+       VINULLKEY,
+/* 020  ^P */
+       {v_up,          V_CNT|V_MOVE|VM_LMODE|VM_RCM,
+           "[count]^P",
+           "^P move up by lines"},
+/* 021  ^Q -- same as ^V if not used for hardware flow control. */
+       VINULLKEY,
+/* 022  ^R */
+       {v_redraw,      0,
+           "^R",
+           "^R redraw screen"},
+/* 023  ^S -- not available, used for hardware flow control. */
+       VINULLKEY,
+/* 024  ^T */
+       {v_tagpop,      V_ABS|VM_RCM_SET,
+           "^T",
+           "^T tag pop"},
+/* 025  ^U */
+       {v_hpageup,     V_CNT|VM_RCM_SET,
+           "[count]^U",
+           "^U half page up (set count)"},
+/* 026  ^V */
+       {NULL,          0,
+           "^V",
+           "^V input a literal character"},
+/* 027  ^W */
+       {v_screen,      0,
+           "^W",
+           "^W move to next screen"},
+/* 030  ^X */
+       VINULLKEY,
+/* 031  ^Y */
+       {v_lineup,      V_CNT,
+           "[count]^Y",
+           "^Y page up by lines"},
+/* 032  ^Z */
+       {v_suspend,     V_SECURE,
+           "^Z",
+           "^Z suspend editor"},
+/* 033  ^[ */
+       {NULL,          0,
+           "^[ <escape>",
+           "^[ <escape> exit input mode, cancel partial commands"},
+/* 034  ^\ */
+       {v_exmode,      0,
+           "^\\",
+           " ^\\ switch to ex mode"},
+/* 035  ^] */
+       {v_tagpush,     V_ABS|V_KEYW|VM_RCM_SET,
+           "^]",
+           "^] tag push cursor word"},
+/* 036  ^^ */
+       {v_switch,      0,
+           "^^",
+           "^^ switch to previous file"},
+/* 037  ^_ */
+       VINULLKEY,
+/* 040 ' ' */
+       {v_right,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]' '",
+           "   <space> move right by columns"},
+/* 041   ! */
+       {v_filter,      V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET,
+           "[count]![count]motion command(s)",
+           " ! filter through command(s) to motion"},
+/* 042   " */
+       VINULLKEY,
+/* 043   # */
+       {v_increment,   V_CHAR|V_CNT|V_DOT|VM_RCM_SET,
+           "[count]# +|-|#",
+           " # number increment/decrement"},
+/* 044   $ */
+       {v_dollar,      V_CNT|V_MOVE|VM_RCM_SETLAST,
+           " [count]$",
+           " $ move to last column"},
+/* 045   % */
+       {v_match,       V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "%",
+           " % move to match"},
+/* 046   & */
+       {v_again,       0,
+           "&",
+           " & repeat substitution"},
+/* 047   ' */
+       {v_fmark,       V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET,
+           "'['a-z]",
+           " ' move to mark (to first non-blank)"},
+/* 050   ( */
+       {v_sentenceb,   V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "[count](",
+           " ( move back sentence"},
+/* 051   ) */
+       {v_sentencef,   V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "[count])",
+           " ) move forward sentence"},
+/* 052   * */
+       VINULLKEY,
+/* 053   + */
+       {v_down,        V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
+           "[count]+",
+           " + move down by lines (to first non-blank)"},
+/* 054   , */
+       {v_chrrepeat,   V_CNT|V_MOVE|VM_RCM_SET,
+           "[count],",
+           " , reverse last F, f, T or t search"},
+/* 055   - */
+       {v_up,          V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
+           "[count]-",
+           " - move up by lines (to first non-blank)"},
+/* 056   . */
+       {NULL,          0,
+           ".",
+           " . repeat the last command"},
+/* 057   / */
+       {v_searchf,     V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "/RE[/ offset]",
+           " / search forward"},
+/* 060   0 */
+       {v_zero,        V_MOVE|VM_RCM_SET,
+           "0",
+           " 0 move to first character"},
+/* 061   1 */
+       VINULLKEY,
+/* 062   2 */
+       VINULLKEY,
+/* 063   3 */
+       VINULLKEY,
+/* 064   4 */
+       VINULLKEY,
+/* 065   5 */
+       VINULLKEY,
+/* 066   6 */
+       VINULLKEY,
+/* 067   7 */
+       VINULLKEY,
+/* 070   8 */
+       VINULLKEY,
+/* 071   9 */
+       VINULLKEY,
+/* 072   : */
+       {v_ex,          0,
+           ":command [| command] ...",
+           " : ex command"},
+/* 073   ; */
+       {v_chrepeat,    V_CNT|V_MOVE|VM_RCM_SET,
+           "[count];",
+           " ; repeat last F, f, T or t search"},
+/* 074   < */
+       {v_shiftl,      V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
+           "[count]<[count]motion",
+           " < shift lines left to motion"},
+/* 075   = */
+       VINULLKEY,
+/* 076   > */
+       {v_shiftr,      V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
+           "[count]>[count]motion",
+           " > shift lines right to motion"},
+/* 077   ? */
+       {v_searchb,     V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "?RE[? offset]",
+           " ? search backward"},
+/* 100   @ */
+       {v_at,          V_CNT|V_RBUF|VM_RCM_SET,
+           "@buffer",
+           " @ execute buffer"},
+/* 101   A */
+       {v_iA,          V_CNT|V_DOT|VM_RCM_SET,
+           "[count]A",
+           " A append to the line"},
+/* 102   B */
+       {v_wordB,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]B",
+           " B move back bigword"},
+/* 103   C */
+       {NULL,          0,
+           "[buffer][count]C",
+           " C change to end-of-line"},
+/* 104   D */
+       {NULL,          0,
+           "[buffer]D",
+           " D delete to end-of-line"},
+/* 105   E */
+       {v_wordE,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]E",
+           " E move to end of bigword"},
+/* 106   F */
+       {v_chF,         V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]F character",
+           " F character in line backward search"},
+/* 107   G */
+       {v_lgoto,       V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETFNB,
+           "[count]G",
+           " G move to line"},
+/* 110   H */
+       {v_home,        V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
+           "[count]H",
+           " H move to count lines from screen top"},
+/* 111   I */
+       {v_iI,          V_CNT|V_DOT|VM_RCM_SET,
+           "[count]I",
+           " I insert before first nonblank"},
+/* 112   J */
+       {v_join,        V_CNT|V_DOT|VM_RCM_SET,
+           "[count]J",
+           " J join lines"},
+/* 113   K */
+       VINULLKEY,
+/* 114   L */
+       {v_bottom,      V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
+           "[count]L",
+           " L move to screen bottom"},
+/* 115   M */
+       {v_middle,      V_ABS_L|V_CNT|V_MOVE|VM_LMODE|VM_RCM_SETNNB,
+           "M",
+           " M move to screen middle"},
+/* 116   N */
+       {v_searchN,     V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "n",
+           " N reverse last search"},
+/* 117   O */
+       {v_iO,          V_CNT|V_DOT|VM_RCM_SET,
+           "[count]O",
+           " O insert above line"},
+/* 120   P */
+       {v_Put,         V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
+           "[buffer]P",
+           " P insert before cursor from buffer"},
+/* 121   Q */
+       {v_exmode,      0,
+           "Q",
+           " Q switch to ex mode"},
+/* 122   R */
+       {v_Replace,     V_CNT|V_DOT|VM_RCM_SET,
+           "[count]R",
+           " R replace characters"},
+/* 123   S */
+       {NULL,          0,
+           "[buffer][count]S",
+           " S substitute for the line(s)"},
+/* 124   T */
+       {v_chT,         V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]T character",
+           " T before character in line backward search"},
+/* 125   U */
+       {v_Undo,        VM_RCM_SET,
+           "U",
+           " U Restore the current line"},
+/* 126   V */
+       VINULLKEY,
+/* 127   W */
+       {v_wordW,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]W",
+           " W move to next bigword"},
+/* 130   X */
+       {v_Xchar,       V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
+           "[buffer][count]X",
+           " X delete character before cursor"},
+/* 131   Y */
+       {NULL,          0,
+           "[buffer][count]Y",
+           " Y copy line"},
+/* 132   Z */
+       {v_zexit,       0,
+           "ZZ",
+           "ZZ save file and exit"},
+/* 133   [ */
+       {v_sectionb,    V_ABS|V_CNT|V_MOVE|VM_RCM_SET,
+           "[[",
+           "[[ move back section"},
+/* 134   \ */
+       VINULLKEY,
+/* 135   ] */
+       {v_sectionf,    V_ABS|V_CNT|V_MOVE|VM_RCM_SET,
+           "]]",
+           "]] move forward section"},
+/* 136   ^ */
+       /*
+        * DON'T set the VM_RCM_SETFNB flag, the function has to do the work
+        * anyway, in case it's a motion component.  DO set VM_RCM_SET, so
+        * that any motion that's part of a command is preserved.
+        */
+       {v_first,       V_CNT|V_MOVE|VM_RCM_SET,
+           "^",
+           " ^ move to first non-blank"},
+/* 137   _ */
+       /*
+        * Needs both to set the VM_RCM_SETFNB flag, and to do the work
+        * in the function, in case it's a delete.
+        */
+       {v_cfirst,      V_CNT|V_MOVE|VM_RCM_SETFNB,
+           "_",
+           " _ move to first non-blank"},
+/* 140   ` */
+       {v_bmark,       V_ABS_C|V_CHAR|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "`[`a-z]",
+           " ` move to mark"},
+/* 141   a */
+       {v_ia,          V_CNT|V_DOT|VM_RCM_SET,
+           "[count]a",
+           " a append after cursor"},
+/* 142   b */
+       {v_wordb,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]b",
+           " b move back word"},
+/* 143   c */
+       {v_change,      V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
+           "[buffer][count]c[count]motion",
+           " c change to motion"},
+/* 144   d */
+       {v_delete,      V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
+           "[buffer][count]d[count]motion",
+           " d delete to motion"},
+/* 145   e */
+       {v_worde,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]e",
+           " e move to end of word"},
+/* 146   f */
+       {v_chf,         V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]f character",
+           " f character in line forward search"},
+/* 147   g */
+       VINULLKEY,
+/* 150   h */
+       {v_left,        V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]h",
+           " h move left by columns"},
+/* 151   i */
+       {v_ii,          V_CNT|V_DOT|VM_RCM_SET,
+           "[count]i",
+           " i insert before cursor"},
+/* 152   j */
+       {v_down,        V_CNT|V_MOVE|VM_LMODE|VM_RCM,
+           "[count]j",
+           " j move down by lines"},
+/* 153   k */
+       {v_up,          V_CNT|V_MOVE|VM_LMODE|VM_RCM,
+           "[count]k",
+           " k move up by lines"},
+/* 154   l */
+       {v_right,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]l",
+           " l move right by columns"},
+/* 155   m */
+       {v_mark,        V_CHAR,
+           "m[a-z]",
+           " m set mark"},
+/* 156   n */
+       {v_searchn,     V_ABS_C|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "n",
+           " n repeat last search"},
+/* 157   o */
+       {v_io,          V_CNT|V_DOT|VM_RCM_SET,
+           "[count]o",
+           " o append after line"},
+/* 160   p */
+       {v_put,         V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
+           "[buffer]p",
+           " p insert after cursor from buffer"},
+/* 161   q */
+       VINULLKEY,
+/* 162   r */
+       {v_replace,     V_CNT|V_DOT|VM_RCM_SET,
+           "[count]r character",
+           " r replace character"},
+/* 163   s */
+       {v_subst,       V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
+           "[buffer][count]s",
+           " s substitute character"},
+/* 164   t */
+       {v_cht,         V_CHAR|V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]t character",
+           " t before character in line forward search"},
+/* 165   u */
+       /*
+        * DON'T set the V_DOT flag, it' more complicated than that.
+        * See vi/vi.c for details.
+        */
+       {v_undo,        VM_RCM_SET,
+           "u",
+           " u undo last change"},
+/* 166   v */
+       VINULLKEY,
+/* 167   w */
+       {v_wordw,       V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]w",
+           " w move to next word"},
+/* 170   x */
+       {v_xchar,       V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
+           "[buffer][count]x",
+           " x delete character"},
+/* 171   y */
+       {v_yank,        V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
+           "[buffer][count]y[count]motion",
+           " y copy text to motion into a cut buffer"},
+/* 172   z */
+       /*
+        * DON'T set the V_CHAR flag, the char isn't required,
+        * so it's handled specially in getcmd().
+        */
+       {v_z,           V_ABS_L|V_CNT|VM_RCM_SETFNB,
+           "[line]z[window_size][-|.|+|^|<CR>]",
+           " z reposition the screen"},
+/* 173   { */
+       {v_paragraphb,  V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "[count]{",
+           " { move back paragraph"},
+/* 174   | */
+       {v_ncol,        V_CNT|V_MOVE|VM_RCM_SET,
+           "[count]|",
+           " | move to column"},
+/* 175   } */
+       {v_paragraphf,  V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
+           "[count]}",
+           " } move forward paragraph"},
+/* 176   ~ */
+       {v_ulcase,      V_CNT|V_DOT|VM_RCM_SET,
+           "[count]~",
+           " ~ reverse case"},
+};
diff --git a/dist/nvi/vi/v_delete.c b/dist/nvi/vi/v_delete.c
new file mode 100644 (file)
index 0000000..2af51ff
--- /dev/null
@@ -0,0 +1,107 @@
+/*     $NetBSD: v_delete.c,v 1.1.1.2 2008/05/18 14:31:40 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_delete.c,v 10.11 2001/06/25 15:19:31 skimo Exp (Berkeley) Date: 2001/06/25 15:19:31";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_delete -- [buffer][count]d[count]motion
+ *            [buffer][count]D
+ *     Delete a range of text.
+ *
+ * PUBLIC: int v_delete __P((SCR *, VICMD *));
+ */
+int
+v_delete(SCR *sp, VICMD *vp)
+{
+       db_recno_t nlines;
+       size_t len;
+       int lmode;
+
+       lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
+
+       /* Yank the lines. */
+       if (cut(sp, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+           &vp->m_start, &vp->m_stop,
+           lmode | (F_ISSET(vp, VM_CUTREQ) ? CUT_NUMREQ : CUT_NUMOPT)))
+               return (1);
+
+       /* Delete the lines. */
+       if (del(sp, &vp->m_start, &vp->m_stop, lmode))
+               return (1);
+
+       /*
+        * Check for deletion of the entire file.  Try to check a close
+        * by line so we don't go to the end of the file unnecessarily.
+        */
+       if (!db_exist(sp, vp->m_final.lno + 1)) {
+               if (db_last(sp, &nlines))
+                       return (1);
+               if (nlines == 0) {
+                       vp->m_final.lno = 1;
+                       vp->m_final.cno = 0;
+                       return (0);
+               }
+       }
+
+       /*
+        * One special correction, in case we've deleted the current line or
+        * character.  We check it here instead of checking in every command
+        * that can be a motion component.
+        */
+       if (db_get(sp, vp->m_final.lno, 0, NULL, &len)) {
+               if (db_get(sp, nlines, DBG_FATAL, NULL, &len))
+                       return (1);
+               vp->m_final.lno = nlines;
+       }
+
+       /*
+        * !!!
+        * Cursor movements, other than those caused by a line mode command
+        * moving to another line, historically reset the relative position.
+        *
+        * This currently matches the check made in v_yank(), I'm hoping that
+        * they should be consistent...
+        */  
+       if (!F_ISSET(vp, VM_LMODE)) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SET);
+
+               /* Make sure the set cursor position exists. */
+               if (vp->m_final.cno >= len)
+                       vp->m_final.cno = len ? len - 1 : 0;
+       }
+
+       /*
+        * !!!
+        * The "dd" command moved to the first non-blank; "d<motion>"
+        * didn't.
+        */
+       if (F_ISSET(vp, VM_LDOUBLE)) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SETFNB);
+       }
+       return (0);
+}
diff --git a/dist/nvi/vi/v_event.c b/dist/nvi/vi/v_event.c
new file mode 100644 (file)
index 0000000..38a7fac
--- /dev/null
@@ -0,0 +1,448 @@
+/*     $NetBSD: v_event.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_event.c,v 8.21 2001/06/25 15:19:31 skimo Exp (Berkeley) Date: 2001/06/25 15:19:31";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ipc/ip.h"
+#include "vi.h"
+
+/*
+ * v_c_settop --
+ *     Scrollbar position.
+ */
+static int
+v_c_settop(SCR *sp, VICMD *vp)
+{
+       SMAP *smp;
+       size_t x = 0, y = LASTLINE(sp); /* Future: change to -1 to not
+                                        * display the cursor
+                                        */
+       size_t tx, ty = -1;
+
+       /*
+        * We want to scroll the screen, without changing the cursor position.
+        * So, we fill the screen map and then flush it to the screen.  Then,
+        * set the VIP_S_REFRESH flag so the main vi loop doesn't update the
+        * screen.  When the next real command happens, the refresh code will
+        * notice that the screen map is way wrong and fix it.
+        *
+        * XXX
+        * There may be a serious performance problem here -- we're doing no
+        * optimization whatsoever, which means that we're copying the entire
+        * screen out to the X11 screen code on each change.
+        */
+       if (vs_sm_fill(sp, vp->ev.e_lno, P_TOP))
+               return (1);
+       for (smp = HMAP; smp <= TMAP; ++smp) {
+                SMAP_FLUSH(smp);
+               if (vs_line(sp, smp, &ty, &tx))
+                       return (1);
+               if (ty != (size_t)-1) {
+                       y = ty;
+                       x = tx;
+               }
+        }
+       (void)sp->gp->scr_move(sp, y, x);
+
+       F_SET(VIP(sp), VIP_S_REFRESH);
+
+       return (sp->gp->scr_refresh(sp, 0));
+}
+
+/*
+ * v_edit --
+ *     Edit command.
+ */
+static int
+v_edit(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
+       argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_editopt --
+ *     Set an option value.
+ */
+static int
+v_editopt(SCR *sp, VICMD *vp)
+{
+       int rval;
+       const char *np;
+       size_t nlen;
+       char *p2;
+
+       INT2CHAR(sp, vp->ev.e_str2, STRLEN(vp->ev.e_str2)+1, np, nlen);
+       p2 = strdup(np);
+       rval = api_opts_set(sp, vp->ev.e_str1, p2, 
+                           vp->ev.e_val1, vp->ev.e_val1);
+       if (sp->gp->scr_reply != NULL)
+               (void)sp->gp->scr_reply(sp, rval, NULL);
+       free(p2);
+       return (rval);
+}
+
+/*
+ * v_editsplit --
+ *     Edit in a split screen.
+ */
+static int
+v_editsplit(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
+       F_SET(&cmd, E_NEWSCREEN);
+       argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tag --
+ *     Tag command.
+ */
+static int
+v_tag(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       if (v_curword(sp))
+               return (1);
+
+       ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
+       argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tagas --
+ *     Tag on the supplied string.
+ */
+static int
+v_tagas(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
+       argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tagsplit --
+ *     Tag in a split screen.
+ */
+static int
+v_tagsplit(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       if (v_curword(sp))
+               return (1);
+
+       ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
+       F_SET(&cmd, E_NEWSCREEN);
+       argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_quit --
+ *     Quit command.
+ */
+static int
+v_quit(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_erepaint --
+ *     Repaint selected lines from the screen.
+ *
+ * PUBLIC: int v_erepaint __P((SCR *, EVENT *));
+ */
+int
+v_erepaint(SCR *sp, EVENT *evp)
+{
+       SMAP *smp;
+
+       for (; evp->e_flno <= evp->e_tlno; ++evp->e_flno) {
+               smp = HMAP + evp->e_flno - 1;
+               SMAP_FLUSH(smp);
+               if (vs_line(sp, smp, NULL, NULL))
+                       return (1);
+       }
+       return (0);
+}
+
+/*
+ * v_sel_end --
+ *     End selection.
+ */
+static int
+v_sel_end(SCR *sp, EVENT *evp)
+{
+       SMAP *smp;
+       VI_PRIVATE *vip;
+
+       smp = HMAP + evp->e_lno;
+       if (smp > TMAP) {
+               /* XXX */
+               return (1);
+       }
+
+       vip = VIP(sp);
+       vip->sel.lno = smp->lno;
+       vip->sel.cno =
+           vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols);
+       return (0);
+}
+
+/*
+ * v_sel_start --
+ *     Start selection.
+ */
+static int
+v_sel_start(SCR *sp, EVENT *evp)
+{
+       SMAP *smp;
+       VI_PRIVATE *vip;
+
+       smp = HMAP + evp->e_lno;
+       if (smp > TMAP) {
+               /* XXX */
+               return (1);
+       }
+
+       vip = VIP(sp);
+       vip->sel.lno = smp->lno;
+       vip->sel.cno =
+           vs_colpos(sp, smp->lno, evp->e_cno + (smp->soff - 1) * sp->cols);
+       return (0);
+}
+
+/*
+ * v_wq --
+ *     Write and quit command.
+ */
+static int
+v_wq(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_WQ, 0, OOBLNO, OOBLNO, 0);
+
+       cmd.addr1.lno = 1;
+       if (db_last(sp, &cmd.addr2.lno))
+               return (1);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_write --
+ *     Write command.
+ */
+static int
+v_write(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);
+
+       cmd.addr1.lno = 1;
+       if (db_last(sp, &cmd.addr2.lno))
+               return (1);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_writeas --
+ *     Write command.
+ */
+static int
+v_writeas(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);
+       argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
+
+       cmd.addr1.lno = 1;
+       if (db_last(sp, &cmd.addr2.lno))
+               return (1);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_event --
+ *     Find the event associated with a function.
+ *
+ * PUBLIC: int v_event __P((SCR *, VICMD *));
+ */
+int
+v_event(SCR *sp, VICMD *vp)
+{
+       /* This array maps events to vi command functions. */
+#define VIKEYDEF(a, b) { a, b, NULL, NULL }
+       static VIKEYS const vievents[] = {
+#define        V_C_SETTOP       0                              /* VI_C_SETTOP */
+               VIKEYDEF(v_c_settop,    0),
+#define        V_EDIT           1                              /* VI_EDIT */
+               VIKEYDEF(v_edit,        0),
+#define        V_EDITOPT        2                              /* VI_EDITOPT */
+               VIKEYDEF(v_editopt,     0),
+#define        V_EDITSPLIT      3                              /* VI_EDITSPLIT */
+               VIKEYDEF(v_editsplit,   0),
+#define        V_EMARK          4                              /* VI_MOUSE_MOVE */
+               VIKEYDEF(v_emark,       V_ABS_L|V_MOVE),
+#define        V_QUIT           5                              /* VI_QUIT */
+               VIKEYDEF(v_quit,        0),
+#define        V_SEARCH         6                              /* VI_SEARCH */
+               VIKEYDEF(v_esearch,     V_ABS_L|V_MOVE),
+#define        V_TAG            7                              /* VI_TAG */
+               VIKEYDEF(v_tag, 0),
+#define        V_TAGAS  8                                      /* VI_TAGAS */
+               VIKEYDEF(v_tagas,       0),
+#define        V_TAGSPLIT       9                              /* VI_TAGSPLIT */
+               VIKEYDEF(v_tagsplit,    0),
+#define        V_WQ            10                              /* VI_WQ */
+               VIKEYDEF(v_wq,          0),
+#define        V_WRITE 11                                      /* VI_WRITE */
+               VIKEYDEF(v_write,       0),
+#define        V_WRITEAS       12                              /* VI_WRITEAS */
+               VIKEYDEF(v_writeas,     0),
+       };
+
+       switch (vp->ev.e_ipcom) {
+       case VI_C_BOL:
+               vp->kp = &vikeys['0'];
+               break;
+       case VI_C_BOTTOM:
+               vp->kp = &vikeys['G'];
+               break;
+       case VI_C_DEL:
+               vp->kp = &vikeys['x'];
+               break;
+       case VI_C_DOWN:
+               F_SET(vp, VC_C1SET);
+               vp->count = vp->ev.e_lno;
+               vp->kp = &vikeys['\012'];
+               break;
+       case VI_C_EOL:
+               vp->kp = &vikeys['$'];
+               break;
+       case VI_C_INSERT:
+               vp->kp = &vikeys['i'];
+               break;
+       case VI_C_LEFT:
+               vp->kp = &vikeys['\010'];
+               break;
+       case VI_C_PGDOWN:
+               F_SET(vp, VC_C1SET);
+               vp->count = vp->ev.e_lno;
+               vp->kp = &vikeys['\006'];
+               break;
+       case VI_C_PGUP:
+               F_SET(vp, VC_C1SET);
+               vp->count = vp->ev.e_lno;
+               vp->kp = &vikeys['\002'];
+               break;
+       case VI_C_RIGHT:
+               vp->kp = &vikeys['\040'];
+               break;
+       case VI_C_SEARCH:
+               vp->kp = &vievents[V_SEARCH];
+               break;
+       case VI_C_SETTOP:
+               vp->kp = &vievents[V_C_SETTOP];
+               break;
+       case VI_C_TOP:
+               F_SET(vp, VC_C1SET);
+               vp->count = 1;
+               vp->kp = &vikeys['G'];
+               break;
+       case VI_C_UP:
+               F_SET(vp, VC_C1SET);
+               vp->count = vp->ev.e_lno;
+               vp->kp = &vikeys['\020'];
+               break;
+       case VI_EDIT:
+               vp->kp = &vievents[V_EDIT];
+               break;
+       case VI_EDITOPT:
+               vp->kp = &vievents[V_EDITOPT];
+               break;
+       case VI_EDITSPLIT:
+               vp->kp = &vievents[V_EDITSPLIT];
+               break;
+       case VI_MOUSE_MOVE:
+               vp->kp = &vievents[V_EMARK];
+               break;
+       case VI_SEL_END:
+               v_sel_end(sp, &vp->ev);
+               /* XXX RETURN IGNORE */
+               break;
+       case VI_SEL_START:
+               v_sel_start(sp, &vp->ev);
+               /* XXX RETURN IGNORE */
+               break;
+       case VI_QUIT:
+               vp->kp = &vievents[V_QUIT];
+               break;
+       case VI_TAG:
+               vp->kp = &vievents[V_TAG];
+               break;
+       case VI_TAGAS:
+               vp->kp = &vievents[V_TAGAS];
+               break;
+       case VI_TAGSPLIT:
+               vp->kp = &vievents[V_TAGSPLIT];
+               break;
+       case VI_UNDO:
+               vp->kp = &vikeys['u'];
+               break;
+       case VI_WQ:
+               vp->kp = &vievents[V_WQ];
+               break;
+       case VI_WRITE:
+               vp->kp = &vievents[V_WRITE];
+               break;
+       case VI_WRITEAS:
+               vp->kp = &vievents[V_WRITEAS];
+               break;
+       default:
+               return (1);
+       }
+       return (0);
+}
diff --git a/dist/nvi/vi/v_ex.c b/dist/nvi/vi/v_ex.c
new file mode 100644 (file)
index 0000000..2bc7c0f
--- /dev/null
@@ -0,0 +1,664 @@
+/*     $NetBSD: v_ex.c,v 1.4 2009/08/11 21:24:49 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_ex.c,v 10.60 2003/07/19 21:04:00 skimo Exp (Berkeley) Date: 2003/07/19 21:04:00";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int v_ecl __P((SCR *));
+static int v_ecl_init __P((SCR *));
+static int v_ecl_log __P((SCR *, TEXT *));
+static int v_ex_done __P((SCR *, VICMD *));
+
+/*
+ * v_again -- &
+ *     Repeat the previous substitution.
+ *
+ * PUBLIC: int v_again __P((SCR *, VICMD *));
+ */
+int
+v_again(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       static CHAR_T nul[] = { 0 };
+
+       ex_cinit(sp, &cmd, C_SUBAGAIN, 2, vp->m_start.lno, vp->m_start.lno, 1);
+       argv_exp0(sp, &cmd, nul, 1);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_exmode -- Q
+ *     Switch the editor into EX mode.
+ *
+ * PUBLIC: int v_exmode __P((SCR *, VICMD *));
+ */
+int
+v_exmode(SCR *sp, VICMD *vp)
+{
+       GS *gp;
+
+       gp = sp->gp;
+
+       /* Try and switch screens -- the screen may not permit it. */
+       if (gp->scr_screen(sp, SC_EX)) {
+               msgq(sp, M_ERR,
+                   "207|The Q command requires the ex terminal interface");
+               return (1);
+       }
+       (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
+
+       /* Save the current cursor position. */
+       sp->frp->lno = sp->lno;
+       sp->frp->cno = sp->cno;
+       F_SET(sp->frp, FR_CURSORSET);
+
+       /* Switch to ex mode. */
+       F_CLR(sp, SC_VI | SC_SCR_VI);
+       F_SET(sp, SC_EX);
+
+       /* Move out of the vi screen. */
+       (void)ex_puts(sp, "\n");
+
+       return (0);
+}
+
+/*
+ * v_join -- [count]J
+ *     Join lines together.
+ *
+ * PUBLIC: int v_join __P((SCR *, VICMD *));
+ */
+int
+v_join(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       int lno;
+
+       /*
+        * YASC.
+        * The general rule is that '#J' joins # lines, counting the current
+        * line.  However, 'J' and '1J' are the same as '2J', i.e. join the
+        * current and next lines.  This doesn't map well into the ex command
+        * (which takes two line numbers), so we handle it here.  Note that
+        * we never test for EOF -- historically going past the end of file
+        * worked just fine.
+        */
+       lno = vp->m_start.lno + 1;
+       if (F_ISSET(vp, VC_C1SET) && vp->count > 2)
+               lno = vp->m_start.lno + (vp->count - 1);
+
+       ex_cinit(sp, &cmd, C_JOIN, 2, vp->m_start.lno, lno, 0);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_shiftl -- [count]<motion
+ *     Shift lines left.
+ *
+ * PUBLIC: int v_shiftl __P((SCR *, VICMD *));
+ */
+int
+v_shiftl(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       static CHAR_T lt[] = {'<', 0};
+
+       ex_cinit(sp, &cmd, C_SHIFTL, 2, vp->m_start.lno, vp->m_stop.lno, 0);
+       argv_exp0(sp, &cmd, lt, 2);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_shiftr -- [count]>motion
+ *     Shift lines right.
+ *
+ * PUBLIC: int v_shiftr __P((SCR *, VICMD *));
+ */
+int
+v_shiftr(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       static CHAR_T gt[] = {'>', 0};
+
+       ex_cinit(sp, &cmd, C_SHIFTR, 2, vp->m_start.lno, vp->m_stop.lno, 0);
+       argv_exp0(sp, &cmd, gt, 2);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_suspend -- ^Z
+ *     Suspend vi.
+ *
+ * PUBLIC: int v_suspend __P((SCR *, VICMD *));
+ */
+int
+v_suspend(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       static CHAR_T suspend[] = {'s', 'u', 's', 'p', 'e', 'n', 'd', 0};
+
+       ex_cinit(sp, &cmd, C_STOP, 0, OOBLNO, OOBLNO, 0);
+       argv_exp0(sp, &cmd, suspend, sizeof(suspend)/sizeof(CHAR_T));
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_switch -- ^^
+ *     Switch to the previous file.
+ *
+ * PUBLIC: int v_switch __P((SCR *, VICMD *));
+ */
+int
+v_switch(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       char *name;
+       const CHAR_T *wp;
+       size_t wlen;
+
+       /*
+        * Try the alternate file name, then the previous file
+        * name.  Use the real name, not the user's current name.
+        */
+       if ((name = sp->alt_name) == NULL) {
+               msgq(sp, M_ERR, "180|No previous file to edit");
+               return (1);
+       }
+
+       /* If autowrite is set, write out the file. */
+       if (file_m1(sp, 0, FS_ALL))
+               return (1);
+
+       ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
+       CHAR2INT(sp, name, strlen(name) + 1, wp, wlen);
+       argv_exp0(sp, &cmd, wp, wlen);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tagpush -- ^[
+ *     Do a tag search on the cursor keyword.
+ *
+ * PUBLIC: int v_tagpush __P((SCR *, VICMD *));
+ */
+int
+v_tagpush(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+#ifdef GTAGS
+       if (O_ISSET(sp, O_GTAGSMODE) && vp->m_start.cno == 0)
+               ex_cinit(sp, &cmd, C_RTAG, 0, OOBLNO, 0, 0);
+       else
+#endif
+       ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, 0, 0);
+       argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw) + 1);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tagpop -- ^T
+ *     Pop the tags stack.
+ *
+ * PUBLIC: int v_tagpop __P((SCR *, VICMD *));
+ */
+int
+v_tagpop(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+
+       ex_cinit(sp, &cmd, C_TAGPOP, 0, OOBLNO, 0, 0);
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_filter -- [count]!motion command(s)
+ *     Run range through shell commands, replacing text.
+ *
+ * PUBLIC: int v_filter __P((SCR *, VICMD *));
+ */
+int
+v_filter(SCR *sp, VICMD *vp)
+{
+       EXCMD cmd;
+       TEXT *tp;
+
+       /*
+        * !!!
+        * Historical vi permitted "!!" in an empty file, and it's handled
+        * as a special case in the ex_bang routine.  Don't modify this setup
+        * without understanding that one.  In particular, note that we're
+        * manipulating the ex argument structures behind ex's back.
+        *
+        * !!!
+        * Historical vi did not permit the '!' command to be associated with
+        * a non-line oriented motion command, in general, although it did
+        * with search commands.  So, !f; and !w would fail, but !/;<CR>
+        * would succeed, even if they all moved to the same location in the
+        * current line.  I don't see any reason to disallow '!' using any of
+        * the possible motion commands.
+        *
+        * !!!
+        * Historical vi ran the last bang command if N or n was used as the
+        * search motion.
+        */
+       if (F_ISSET(vp, VC_ISDOT) ||
+           ISCMD(vp->rkp, 'N') || ISCMD(vp->rkp, 'n')) {
+               static CHAR_T bang[] = {'!', 0};
+               ex_cinit(sp,
+                   &cmd, C_BANG, 2, vp->m_start.lno, vp->m_stop.lno, 0);
+               EXP(sp)->argsoff = 0;                   /* XXX */
+
+               if (argv_exp1(sp, &cmd, bang, 1, 1))
+                       return (1);
+               cmd.argc = EXP(sp)->argsoff;            /* XXX */
+               cmd.argv = EXP(sp)->args;               /* XXX */
+               return (v_exec_ex(sp, vp, &cmd));
+       }
+
+       /* Get the command from the user. */
+       if (v_tcmd(sp, vp,
+           '!', TXT_BS | TXT_CR | TXT_ESCAPE | TXT_FILEC | TXT_PROMPT))
+               return (1);
+
+       /*
+        * Check to see if the user changed their mind.
+        *
+        * !!!
+        * Entering <escape> on an empty line was historically an error,
+        * this implementation doesn't bother.
+        */
+       tp = sp->tiq.cqh_first;
+       if (tp->term != TERM_OK) {
+               vp->m_final.lno = sp->lno;
+               vp->m_final.cno = sp->cno;
+               return (0);
+       }
+
+       /* Home the cursor. */
+       vs_home(sp);
+
+       ex_cinit(sp, &cmd, C_BANG, 2, vp->m_start.lno, vp->m_stop.lno, 0);
+       EXP(sp)->argsoff = 0;                   /* XXX */
+
+       if (argv_exp1(sp, &cmd, tp->lb + 1, tp->len - 1, 1))
+               return (1);
+       cmd.argc = EXP(sp)->argsoff;            /* XXX */
+       cmd.argv = EXP(sp)->args;               /* XXX */
+       return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_exec_ex --
+ *     Execute an ex command.
+ *
+ * PUBLIC: int v_exec_ex __P((SCR *, VICMD *, EXCMD *));
+ */
+int
+v_exec_ex(SCR *sp, VICMD *vp, EXCMD *exp)
+{
+       int rval;
+
+       rval = exp->cmd->fn(sp, exp);
+       return (v_ex_done(sp, vp) || rval);
+}
+
+/*
+ * v_ex -- :
+ *     Execute a colon command line.
+ *
+ * PUBLIC: int v_ex __P((SCR *, VICMD *));
+ */
+int
+v_ex(SCR *sp, VICMD *vp)
+{
+       WIN *wp;
+       TEXT *tp;
+       int do_cedit, do_resolution, ifcontinue;
+
+       wp = sp->wp;
+
+       /*
+        * !!!
+        * If we put out more than a single line of messages, or ex trashes
+        * the screen, the user may continue entering ex commands.  We find
+        * this out when we do the screen/message resolution.  We can't enter
+        * completely into ex mode however, because the user can elect to
+        * return into vi mode by entering any key, i.e. we have to be in raw
+        * mode.
+        */
+       for (do_cedit = do_resolution = 0;;) {
+               /*
+                * !!!
+                * There may already be an ex command waiting to run.  If
+                * so, we continue with it.
+                */
+               if (!EXCMD_RUNNING(wp)) {
+                       /* Get a command. */
+                       if (v_tcmd(sp, vp, ':',
+                           TXT_BS | TXT_CEDIT | TXT_FILEC | TXT_PROMPT))
+                               return (1);
+                       tp = sp->tiq.cqh_first;
+
+                       /*
+                        * If the user entered a single <esc>, they want to
+                        * edit their colon command history.  If they already
+                        * entered some text, move it into the edit history.
+                        */
+                       if (tp->term == TERM_CEDIT) {
+                               if (tp->len > 1 && v_ecl_log(sp, tp))
+                                       return (1);
+                               do_cedit = 1;
+                               break;
+                       }
+
+                       /* If the user didn't enter anything, return. */
+                       if (tp->term == TERM_BS)
+                               break;
+
+                       /* Log the command. */
+                       if (O_STR(sp, O_CEDIT) != NULL)
+                               (void)v_ecl_log(sp, tp);
+
+                       /* Push a command on the command stack. */
+                       if (ex_run_str(sp, NULL, tp->lb, tp->len, 0, 1))
+                               return (1);
+               }
+
+               /* Home the cursor. */
+               vs_home(sp);
+
+               /*
+                * !!!
+                * If the editor wrote the screen behind curses back, put out
+                * a <newline> so that we don't overwrite the user's command
+                * with its output or the next want-to-continue? message.  This
+                * doesn't belong here, but I can't find another place to put
+                * it.  See, we resolved the output from the last ex command,
+                * and the user entered another one.  This is the only place
+                * where we have control before the ex command writes output.
+                * We could get control in vs_msg(), but we have no way to know
+                * if command didn't put out any output when we try and resolve
+                * this command.  This fixes a bug where combinations of ex
+                * commands, e.g. ":set<CR>:!date<CR>:set" didn't look right.
+                */
+               if (F_ISSET(sp, SC_SCR_EXWROTE))
+                       (void)putchar('\n');
+
+               /* Call the ex parser. */
+               (void)ex_cmd(sp);
+
+               /* Flush ex messages. */
+               (void)ex_fflush(sp);
+
+               /* Resolve any messages. */
+               if (vs_ex_resolve(sp, &ifcontinue))
+                       return (1);
+
+               /*
+                * Continue or return.  If continuing, make sure that we
+                * eventually do resolution.
+                */
+               if (!ifcontinue)
+                       break;
+               do_resolution = 1;
+
+               /* If we're continuing, it's a new command. */
+               ++sp->ccnt;
+       }
+
+       /*
+        * If the user previously continued an ex command, we have to do
+        * resolution to clean up the screen.  Don't wait, we already did
+        * that.
+        */
+       if (do_resolution) {
+               F_SET(sp, SC_EX_WAIT_NO);
+               if (vs_ex_resolve(sp, &ifcontinue))
+                       return (1);
+       }
+
+       /* Cleanup from the ex command. */
+       if (v_ex_done(sp, vp))
+               return (1);
+
+       /* The user may want to edit their colon command history. */
+       if (do_cedit)
+               return (v_ecl(sp));
+
+       return (0);
+}
+
+/*
+ * v_ex_done --
+ *     Cleanup from an ex command.
+ */
+static int
+v_ex_done(SCR *sp, VICMD *vp)
+{
+       size_t len;
+
+       /*
+        * The only cursor modifications are real, however, the underlying
+        * line may have changed; don't trust anything.  This code has been
+        * a remarkably fertile place for bugs.  Do a reality check on a
+        * cursor value, and make sure it's okay.  If necessary, change it.
+        * Ex keeps track of the line number, but it cares less about the
+        * column and it may have disappeared.
+        *
+        * Don't trust ANYTHING.
+        *
+        * XXX
+        * Ex will soon have to start handling the column correctly; see
+        * the POSIX 1003.2 standard.
+        */
+       if (db_eget(sp, sp->lno, NULL, &len, NULL)) {
+               sp->lno = 1;
+               sp->cno = 0;
+       } else if (sp->cno >= len)
+               sp->cno = len ? len - 1 : 0;
+
+       vp->m_final.lno = sp->lno;
+       vp->m_final.cno = sp->cno;
+
+       /*
+        * Don't re-adjust the cursor after executing an ex command,
+        * and ex movements are permanent.
+        */
+       F_CLR(vp, VM_RCM_MASK);
+       F_SET(vp, VM_RCM_SET);
+
+       return (0);
+}
+
+/*
+ * v_ecl --
+ *     Start an edit window on the colon command-line commands.
+ */
+static int
+v_ecl(SCR *sp)
+{
+       GS *gp;
+       WIN *wp;
+       SCR *new;
+
+       /* Initialize the screen, if necessary. */
+       gp = sp->gp;
+       wp = sp->wp;
+       if (wp->ccl_sp == NULL && v_ecl_init(sp))
+               return (1);
+
+       /* Get a new screen. */
+       if (screen_init(gp, sp, &new))
+               return (1);
+       if (vs_split(sp, new, 1)) {
+               (void)screen_end(new);
+               return (1);
+       }
+
+       /* Attach to the screen. */
+       new->ep = wp->ccl_sp->ep;
+       ++new->ep->refcnt;
+       CIRCLEQ_INSERT_HEAD(&new->ep->scrq, new, eq);
+
+       new->frp = wp->ccl_sp->frp;
+       new->frp->flags = sp->frp->flags;
+       new->conv = wp->ccl_sp->conv;
+
+       /* Move the cursor to the end. */
+       (void)db_last(new, &new->lno);
+       if (new->lno == 0)
+               new->lno = 1;
+
+       /* Remember the originating window. */
+       sp->ccl_parent = sp;
+
+       /* It's a special window. */
+       F_SET(new, SC_COMEDIT);
+
+       /* Don't encode on writing to DB. */
+       o_set(new, O_FILEENCODING, OS_STRDUP, "WCHAR_T", 0);
+
+       /* Set up the switch. */
+       sp->nextdisp = new;
+       F_SET(sp, SC_SSWITCH);
+       return (0);
+}
+
+/*
+ * v_ecl_exec --
+ *     Execute a command from a colon command-line window.
+ *
+ * PUBLIC: int v_ecl_exec __P((SCR *));
+ */
+int
+v_ecl_exec(SCR *sp)
+{
+       size_t len;
+       CHAR_T *p;
+
+       if (db_get(sp, sp->lno, 0, &p, &len) && sp->lno == 1) {
+               v_emsg(sp, NULL, VIM_EMPTY);
+               return (1);
+       }
+       if (len == 0) {
+               msgq(sp, M_BERR, "307|No ex command to execute");
+               return (1);
+       }
+       
+       /* Push the command on the command stack. */
+       if (ex_run_str(sp, NULL, p, len, 0, 0))
+               return (1);
+
+       /* Set up the switch. */
+       sp->nextdisp = sp->ccl_parent;
+       F_SET(sp, SC_EXIT);
+       return (0);
+}
+
+/*
+ * v_ecl_log --
+ *     Log a command into the colon command-line log file.
+ */
+static int
+v_ecl_log(SCR *sp, TEXT *tp)
+{
+       db_recno_t lno;
+       int rval;
+       CHAR_T *p;
+       size_t len;
+       SCR *ccl_sp;
+
+       /* Initialize the screen, if necessary. */
+       if (sp->wp->ccl_sp == NULL && v_ecl_init(sp))
+               return (1);
+
+       ccl_sp = sp->wp->ccl_sp;
+
+       /*
+        * Don't log colon command window commands into the colon command
+        * window...
+        */
+       if (sp->ep == ccl_sp->ep)
+               return (0);
+
+       if (db_last(ccl_sp, &lno)) {
+               return (1);
+       }
+       /* Don't log line that is identical to previous one */
+       if (lno > 0 &&
+           !db_get(ccl_sp, lno, 0, &p, &len) &&
+           len == tp->len &&
+           !MEMCMP(tp->lb, p, len))
+               rval = 0;
+       else {
+               rval = db_append(ccl_sp, 0, lno, tp->lb, tp->len);
+               /* XXXX end "transaction" on ccl */
+               /* Is this still necessary now that we no longer hijack sp ? */
+               log_cursor(ccl_sp);
+       }
+
+       return (rval);
+}
+
+/*
+ * v_ecl_init --
+ *     Initialize the colon command-line log file.
+ */
+static int
+v_ecl_init(SCR *sp)
+{
+       FREF *frp;
+       GS *gp;
+       WIN *wp;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       /* Get a temporary file. */
+       if ((frp = file_add(sp, NULL)) == NULL)
+               return (1);
+
+       /*
+        * XXX
+        * Create a screen -- the file initialization code wants one.
+        */
+       if (screen_init(gp, sp, &wp->ccl_sp))
+               return (1);
+       conv_enc(wp->ccl_sp, O_FILEENCODING, "WCHAR_T");
+       if (file_init(wp->ccl_sp, frp, NULL, 0)) {
+               (void)screen_end(wp->ccl_sp);
+               wp->ccl_sp = 0;
+               return (1);
+       }
+
+       /* The underlying file isn't recoverable. */
+       F_CLR(wp->ccl_sp->ep, F_RCV_ON);
+
+       return (0);
+}
diff --git a/dist/nvi/vi/v_increment.c b/dist/nvi/vi/v_increment.c
new file mode 100644 (file)
index 0000000..676b48c
--- /dev/null
@@ -0,0 +1,266 @@
+/*     $NetBSD: v_increment.c,v 1.5 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_increment.c,v 10.16 2001/06/25 15:19:31 skimo Exp (Berkeley) Date: 2001/06/25 15:19:31";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static const CHAR_T * const fmt[] = {
+#define        DEC     0
+       L("%ld"),
+#define        SDEC    1
+       L("%+ld"),
+#define        HEXC    2
+       L("0X%0*lX"),
+#define        HEXL    3
+       L("0x%0*lx"),
+#define        OCTAL   4
+       L("%#0*lo"),
+};
+
+static void inc_err __P((SCR *, enum nresult));
+
+/*
+ * v_increment -- [count]#[#+-]
+ *     Increment/decrement a keyword number.
+ *
+ * PUBLIC: int v_increment __P((SCR *, VICMD *));
+ */
+int
+v_increment(SCR *sp, VICMD *vp)
+{
+       enum nresult nret;
+       u_long ulval, change;
+       long ltmp, lval;
+       size_t beg, blen, end, len, nlen, wlen;
+       int base, isempty, rval;
+       const CHAR_T *ntype;
+       CHAR_T nbuf[100];
+       CHAR_T *bp, *p, *t;
+
+       /* Validate the operator. */
+       if (vp->character == '#')
+               vp->character = '+';
+       if (vp->character != '+' && vp->character != '-') {
+               v_emsg(sp, vp->kp->usage, VIM_USAGE);
+               return (1);
+       }
+
+       /* If new value set, save it off, but it has to fit in a long. */
+       if (F_ISSET(vp, VC_C1SET)) {
+               if (vp->count > LONG_MAX) {
+                       inc_err(sp, NUM_OVER);
+                       return (1);
+               }
+               change = vp->count;
+       } else
+               change = 1;
+
+       /* Get the line. */
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (isempty)
+                       goto nonum;
+               return (1);
+       }
+
+       /*
+        * Skip any leading space before the number.  Getting a cursor word
+        * implies moving the cursor to its beginning, if we moved, refresh
+        * now.
+        */
+       for (beg = vp->m_start.cno; beg < len && ISSPACE((UCHAR_T)p[beg]); ++beg);
+       if (beg >= len)
+               goto nonum;
+       if (beg != vp->m_start.cno) {
+               sp->cno = beg;
+               (void)vs_refresh(sp, 0);
+       }
+
+#undef isoctal
+#define        isoctal(c)      ((c) >= '0' && (c) <= '7')
+
+       /*
+        * Look for 0[Xx], or leading + or - signs, guess at the base.
+        * The character after that must be a number.  Wlen is set to
+        * the remaining characters in the line that could be part of
+        * the number.
+        */
+       wlen = len - beg;
+       if (p[beg] == '0' && wlen > 2 &&
+           (p[beg + 1] == 'X' || p[beg + 1] == 'x')) {
+               base = 16;
+               end = beg + 2;
+               if (!ISXDIGIT((UCHAR_T)p[end]))
+                       goto decimal;
+               ntype = p[beg + 1] == 'X' ? fmt[HEXC] : fmt[HEXL];
+       } else if (p[beg] == '0' && wlen > 1) {
+               base = 8;
+               end = beg + 1;
+               if (!isoctal((UCHAR_T)p[end]))
+                       goto decimal;
+               ntype = fmt[OCTAL];
+       } else if (wlen >= 1 && (p[beg] == '+' || p[beg] == '-')) {
+               base = 10;
+               end = beg + 1;
+               ntype = fmt[SDEC];
+               if (!ISDIGIT((UCHAR_T)p[end]))
+                       goto nonum;
+       } else {
+decimal:       base = 10;
+               end = beg;
+               ntype = fmt[DEC];
+               if (!ISDIGIT((UCHAR_T)p[end])) {
+nonum:                 msgq(sp, M_ERR, "181|Cursor not in a number");
+                       return (1);
+               }
+       }
+
+       /* Find the end of the word, possibly correcting the base. */
+       while (++end < len) {
+               switch (base) {
+               case 8:
+                       if (isoctal((UCHAR_T)p[end]))
+                               continue;
+                       if (p[end] == '8' || p[end] == '9') {
+                               base = 10;
+                               ntype = fmt[DEC];
+                               continue;
+                       }
+                       break;
+               case 10:
+                       if (ISDIGIT((UCHAR_T)p[end]))
+                               continue;
+                       break;
+               case 16:
+                       if (ISXDIGIT((UCHAR_T)p[end]))
+                               continue;
+                       break;
+               default:
+                       abort();
+                       /* NOTREACHED */
+               }
+               break;
+       }
+       wlen = (end - beg);
+
+       /*
+        * XXX
+        * If the line was at the end of the buffer, we have to copy it
+        * so we can guarantee that it's NULL-terminated.  We make the
+        * buffer big enough to fit the line changes as well, and only
+        * allocate once.
+        */
+       GET_SPACE_RETW(sp, bp, blen, len + 50);
+       if (end == len) {
+               MEMMOVEW(bp, &p[beg], wlen);
+               bp[wlen] = '\0';
+               t = bp;
+       } else
+               t = &p[beg];
+
+       /*
+        * Octal or hex deal in unsigned longs, everything else is done
+        * in signed longs.
+        */
+       if (base == 10) {
+               if ((nret = nget_slong(sp, &lval, t, NULL, 10)) != NUM_OK)
+                       goto err;
+               ltmp = vp->character == '-' ? -change : change;
+               if (lval > 0 && ltmp > 0 &&
+                   !NPFITS(LONG_MAX, (unsigned long)lval, (unsigned long)ltmp)) {
+                       nret = NUM_OVER;
+                       goto err;
+               }
+               if (lval < 0 && ltmp < 0 && !NNFITS(LONG_MIN, lval, ltmp)) {
+                       nret = NUM_UNDER;
+                       goto err;
+               }
+               lval += ltmp;
+               /* If we cross 0, signed numbers lose their sign. */
+               if (lval == 0 && ntype == fmt[SDEC])
+                       ntype = fmt[DEC];
+               nlen = SPRINTF(nbuf, sizeof(nbuf), ntype, lval);
+       } else {
+               if ((nret = nget_uslong(sp, &ulval, t, NULL, base)) != NUM_OK)
+                       goto err;
+               if (vp->character == '+') {
+                       if (!NPFITS(ULONG_MAX, ulval, change)) {
+                               nret = NUM_OVER;
+                               goto err;
+                       }
+                       ulval += change;
+               } else {
+                       if (ulval < change) {
+                               nret = NUM_UNDER;
+                               goto err;
+                       }
+                       ulval -= change;
+               }
+
+               /* Correct for literal "0[Xx]" in format. */
+               if (base == 16)
+                       wlen -= 2;
+
+               nlen = SPRINTF(nbuf, sizeof(nbuf), ntype, wlen, ulval);
+       }
+
+       /* Build the new line. */
+       MEMMOVEW(bp, p, beg);
+       MEMMOVEW(bp + beg, nbuf, nlen);
+       MEMMOVEW(bp + beg + nlen, p + end, len - beg - (end - beg));
+       len = beg + nlen + (len - beg - (end - beg));
+
+       nret = NUM_OK;
+       rval = db_set(sp, vp->m_start.lno, bp, len);
+
+       if (0) {
+err:           rval = 1;
+               inc_err(sp, nret);
+       }
+       if (bp != NULL)
+               FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
+
+static void
+inc_err(SCR *sp, enum nresult nret)
+{
+       switch (nret) {
+       case NUM_ERR:
+               break;
+       case NUM_OK:
+               abort();
+               /* NOREACHED */
+       case NUM_OVER:
+               msgq(sp, M_ERR, "182|Resulting number too large");
+               break;
+       case NUM_UNDER:
+               msgq(sp, M_ERR, "183|Resulting number too small");
+               break;
+       }
+}
diff --git a/dist/nvi/vi/v_init.c b/dist/nvi/vi/v_init.c
new file mode 100644 (file)
index 0000000..476afe3
--- /dev/null
@@ -0,0 +1,122 @@
+/*     $NetBSD: v_init.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_init.c,v 10.9 2001/06/25 15:19:31 skimo Exp (Berkeley) Date: 2001/06/25 15:19:31";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_screen_copy --
+ *     Copy vi screen.
+ *
+ * PUBLIC: int v_screen_copy __P((SCR *, SCR *));
+ */
+int
+v_screen_copy(SCR *orig, SCR *sp)
+{
+       VI_PRIVATE *ovip, *nvip;
+
+       /* Create the private vi structure. */
+       CALLOC_RET(orig, nvip, VI_PRIVATE *, 1, sizeof(VI_PRIVATE));
+       sp->vi_private = nvip;
+
+       /* Invalidate the line size cache. */
+       VI_SCR_CFLUSH(nvip);
+
+       if (orig == NULL) {
+               nvip->csearchdir = CNOTSET;
+       } else {
+               ovip = VIP(orig);
+
+               /* User can replay the last input, but nothing else. */
+               if (ovip->rep_len != 0) {
+                       MALLOC_RET(orig, nvip->rep, EVENT *, ovip->rep_len);
+                       memmove(nvip->rep, ovip->rep, ovip->rep_len);
+                       nvip->rep_len = ovip->rep_len;
+               }
+
+               /* Copy the paragraph/section information. */
+               if (ovip->ps != NULL && (nvip->ps =
+                   v_strdup(sp, ovip->ps, strlen(ovip->ps))) == NULL)
+                       return (1);
+
+               nvip->lastckey = ovip->lastckey;
+               nvip->csearchdir = ovip->csearchdir;
+
+               nvip->srows = ovip->srows;
+       }
+       return (0);
+}
+
+/*
+ * v_screen_end --
+ *     End a vi screen.
+ *
+ * PUBLIC: int v_screen_end __P((SCR *));
+ */
+int
+v_screen_end(SCR *sp)
+{
+       VI_PRIVATE *vip;
+
+       if ((vip = VIP(sp)) == NULL)
+               return (0);
+       if (vip->keyw != NULL)
+               free(vip->keyw);
+       if (vip->rep != NULL)
+               free(vip->rep);
+       if (vip->ps != NULL)
+               free(vip->ps);
+
+       if (HMAP != NULL)
+               free(HMAP);
+
+       free(vip);
+       sp->vi_private = NULL;
+
+       return (0);
+}
+
+/*
+ * v_optchange --
+ *     Handle change of options for vi.
+ *
+ * PUBLIC: int v_optchange __P((SCR *, int, const char *, u_long *));
+ */
+int
+v_optchange(SCR *sp, int offset, const char *str, u_long *valp)
+{
+       switch (offset) {
+       case O_PARAGRAPHS:
+               return (v_buildps(sp, str, O_STR(sp, O_SECTIONS)));
+       case O_SECTIONS:
+               return (v_buildps(sp, O_STR(sp, O_PARAGRAPHS), str));
+       case O_WINDOW:
+               return (vs_crel(sp, *valp));
+       }
+       return (0);
+}
diff --git a/dist/nvi/vi/v_itxt.c b/dist/nvi/vi/v_itxt.c
new file mode 100644 (file)
index 0000000..c94d64e
--- /dev/null
@@ -0,0 +1,517 @@
+/*     $NetBSD: v_itxt.c,v 1.1.1.2 2008/05/18 14:31:42 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_itxt.c,v 10.21 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * !!!
+ * Repeated input in the historic vi is mostly wrong and this isn't very
+ * backward compatible.  For example, if the user entered "3Aab\ncd" in
+ * the historic vi, the "ab" was repeated 3 times, and the "\ncd" was then
+ * appended to the result.  There was also a hack which I don't remember
+ * right now, where "3o" would open 3 lines and then let the user fill them
+ * in, to make screen movements on 300 baud modems more tolerable.  I don't
+ * think it's going to be missed.
+ *
+ * !!!
+ * There's a problem with the way that we do logging for change commands with
+ * implied motions (e.g. A, I, O, cc, etc.).  Since the main vi loop logs the
+ * starting cursor position before the change command "moves" the cursor, the
+ * cursor position to which we return on undo will be where the user entered
+ * the change command, not the start of the change.  Several of the following
+ * routines re-log the cursor to make this work correctly.  Historic vi tried
+ * to do the same thing, and mostly got it right.  (The only spectacular way
+ * it fails is if the user entered 'o' from anywhere but the last character of
+ * the line, the undo returned the cursor to the start of the line.  If the
+ * user was on the last character of the line, the cursor returned to that
+ * position.)  We also check for mapped keys waiting, i.e. if we're in the
+ * middle of a map, don't bother logging the cursor.
+ */
+#define        LOG_CORRECT {                                                   \
+       if (!MAPPED_KEYS_WAITING(sp))                                   \
+               (void)log_cursor(sp);                                   \
+}
+
+static u_int32_t set_txt_std __P((SCR *, VICMD *, u_int32_t));
+
+/*
+ * v_iA -- [count]A
+ *     Append text to the end of the line.
+ *
+ * PUBLIC: int v_iA __P((SCR *, VICMD *));
+ */
+int
+v_iA(SCR *sp, VICMD *vp)
+{
+       size_t len;
+
+       if (!db_get(sp, vp->m_start.lno, 0, NULL, &len))
+               sp->cno = len == 0 ? 0 : len - 1;
+
+       LOG_CORRECT;
+
+       return (v_ia(sp, vp));
+}
+
+/*
+ * v_ia -- [count]a
+ *        [count]A
+ *     Append text to the cursor position.
+ *
+ * PUBLIC: int v_ia __P((SCR *, VICMD *));
+ */
+int
+v_ia(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       u_int32_t flags;
+       int isempty;
+       CHAR_T *p;
+
+       flags = set_txt_std(sp, vp, 0);
+       sp->showmode = SM_APPEND;
+       sp->lno = vp->m_start.lno;
+
+       /* Move the cursor one column to the right and repaint the screen. */
+       if (db_eget(sp, sp->lno, &p, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               len = 0;
+               LF_SET(TXT_APPENDEOL);
+       } else if (len) {
+               if (len == sp->cno + 1) {
+                       sp->cno = len;
+                       LF_SET(TXT_APPENDEOL);
+               } else
+                       ++sp->cno;
+       } else
+               LF_SET(TXT_APPENDEOL);
+
+       return (v_txt(sp, vp, NULL, p, len,
+           0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+/*
+ * v_iI -- [count]I
+ *     Insert text at the first nonblank.
+ *
+ * PUBLIC: int v_iI __P((SCR *, VICMD *));
+ */
+int
+v_iI(SCR *sp, VICMD *vp)
+{
+       sp->cno = 0;
+       if (nonblank(sp, vp->m_start.lno, &sp->cno))
+               return (1);
+
+       LOG_CORRECT;
+
+       return (v_ii(sp, vp));
+}
+
+/*
+ * v_ii -- [count]i
+ *        [count]I
+ *     Insert text at the cursor position.
+ *
+ * PUBLIC: int v_ii __P((SCR *, VICMD *));
+ */
+int
+v_ii(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       u_int32_t flags;
+       int isempty;
+       CHAR_T *p;
+
+       flags = set_txt_std(sp, vp, 0);
+       sp->showmode = SM_INSERT;
+       sp->lno = vp->m_start.lno;
+
+       if (db_eget(sp, sp->lno, &p, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               len = 0;
+       }
+
+       if (len == 0)
+               LF_SET(TXT_APPENDEOL);
+       return (v_txt(sp, vp, NULL, p, len,
+           0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+enum which { o_cmd, O_cmd };
+static int io __P((SCR *, VICMD *, enum which));
+
+/*
+ * v_iO -- [count]O
+ *     Insert text above this line.
+ *
+ * PUBLIC: int v_iO __P((SCR *, VICMD *));
+ */
+int
+v_iO(SCR *sp, VICMD *vp)
+{
+       return (io(sp, vp, O_cmd));
+}
+
+/*
+ * v_io -- [count]o
+ *     Insert text after this line.
+ *
+ * PUBLIC: int v_io __P((SCR *, VICMD *));
+ */
+int
+v_io(SCR *sp, VICMD *vp)
+{
+       return (io(sp, vp, o_cmd));
+}
+
+static int
+io(SCR *sp, VICMD *vp, enum which cmd)
+{
+       db_recno_t ai_line, lno;
+       size_t len;
+       u_int32_t flags;
+       CHAR_T *p;
+
+       flags = set_txt_std(sp, vp, TXT_ADDNEWLINE | TXT_APPENDEOL);
+       sp->showmode = SM_INSERT;
+
+       if (sp->lno == 1) {
+               if (db_last(sp, &lno))
+                       return (1);
+               if (lno != 0)
+                       goto insert;
+               p = NULL;
+               len = 0;
+               ai_line = OOBLNO;
+       } else {
+               static CHAR_T nul = 0;
+insert:                p = &nul;
+               sp->cno = 0;
+               LOG_CORRECT;
+
+               if (cmd == O_cmd) {
+                       if (db_insert(sp, sp->lno, p, 0))
+                               return (1);
+                       if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
+                               return (1);
+                       ai_line = sp->lno + 1;
+               } else {
+                       if (db_append(sp, 1, sp->lno, p, 0))
+                               return (1);
+                       if (db_get(sp, ++sp->lno, DBG_FATAL, &p, &len))
+                               return (1);
+                       ai_line = sp->lno - 1;
+               }
+       }
+       return (v_txt(sp, vp, NULL, p, len,
+           0, ai_line, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+/*
+ * v_change -- [buffer][count]c[count]motion
+ *            [buffer][count]C
+ *            [buffer][count]S
+ *     Change command.
+ *
+ * PUBLIC: int v_change __P((SCR *, VICMD *));
+ */
+int
+v_change(SCR *sp, VICMD *vp)
+{
+       size_t blen, len;
+       u_int32_t flags;
+       int isempty, lmode, rval;
+       CHAR_T *bp;
+       CHAR_T *p;
+
+       /*
+        * 'c' can be combined with motion commands that set the resulting
+        * cursor position, i.e. "cG".  Clear the VM_RCM flags and make the
+        * resulting cursor position stick, inserting text has its own rules
+        * for cursor positioning.
+        */
+       F_CLR(vp, VM_RCM_MASK);
+       F_SET(vp, VM_RCM_SET);
+
+       /*
+        * Find out if the file is empty, it's easier to handle it as a
+        * special case.
+        */
+       if (vp->m_start.lno == vp->m_stop.lno &&
+           db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               return (v_ia(sp, vp));
+       }
+
+       flags = set_txt_std(sp, vp, 0);
+       sp->showmode = SM_CHANGE;
+
+       /*
+        * Move the cursor to the start of the change.  Note, if autoindent
+        * is turned on, the cc command in line mode changes from the first
+        * *non-blank* character of the line, not the first character.  And,
+        * to make it just a bit more exciting, the initial space is handled
+        * as auto-indent characters.
+        */
+       lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
+       if (lmode) {
+               vp->m_start.cno = 0;
+               if (O_ISSET(sp, O_AUTOINDENT)) {
+                       if (nonblank(sp, vp->m_start.lno, &vp->m_start.cno))
+                               return (1);
+                       LF_SET(TXT_AICHARS);
+               }
+       }
+       sp->lno = vp->m_start.lno;
+       sp->cno = vp->m_start.cno;
+
+       LOG_CORRECT;
+
+       /*
+        * If not in line mode and changing within a single line, copy the
+        * text and overwrite it.
+        */
+       if (!lmode && vp->m_start.lno == vp->m_stop.lno) {
+               /*
+                * !!!
+                * Historic practice, c did not cut into the numeric buffers,
+                * only the unnamed one.
+                */
+               if (cut(sp,
+                   F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+                   &vp->m_start, &vp->m_stop, lmode))
+                       return (1);
+               if (len == 0)
+                       LF_SET(TXT_APPENDEOL);
+               LF_SET(TXT_EMARK | TXT_OVERWRITE);
+               return (v_txt(sp, vp, &vp->m_stop, p, len,
+                   0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+       }
+
+       /*
+        * It's trickier if in line mode or changing over multiple lines.  If
+        * we're in line mode delete all of the lines and insert a replacement
+        * line which the user edits.  If there was leading whitespace in the
+        * first line being changed, we copy it and use it as the replacement.
+        * If we're not in line mode, we delete the text and start inserting.
+        *
+        * !!!
+        * Copy the text.  Historic practice, c did not cut into the numeric
+        * buffers, only the unnamed one.
+        */
+       if (cut(sp,
+           F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+           &vp->m_start, &vp->m_stop, lmode))
+               return (1);
+
+       /* If replacing entire lines and there's leading text. */
+       if (lmode && vp->m_start.cno) {
+               /*
+                * Get a copy of the first line changed, and copy out the
+                * leading text.
+                */
+               if (db_get(sp, vp->m_start.lno, DBG_FATAL, &p, &len))
+                       return (1);
+               GET_SPACE_RETW(sp, bp, blen, vp->m_start.cno);
+               MEMMOVEW(bp, p, vp->m_start.cno);
+       } else
+               bp = NULL;
+
+       /* Delete the text. */
+       if (del(sp, &vp->m_start, &vp->m_stop, lmode))
+               return (1);
+
+       /* If replacing entire lines, insert a replacement line. */
+       if (lmode) {
+               if (db_insert(sp, vp->m_start.lno, bp, vp->m_start.cno))
+                       return (1);
+               sp->lno = vp->m_start.lno;
+               len = sp->cno = vp->m_start.cno;
+       }
+
+       /* Get the line we're editing. */
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               len = 0;
+       }
+
+       /* Check to see if we're appending to the line. */
+       if (vp->m_start.cno >= len)
+               LF_SET(TXT_APPENDEOL);
+
+       rval = v_txt(sp, vp, NULL, p, len,
+           0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags);
+
+       if (bp != NULL)
+               FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
+
+/*
+ * v_Replace -- [count]R
+ *     Overwrite multiple characters.
+ *
+ * PUBLIC: int v_Replace __P((SCR *, VICMD *));
+ */
+int
+v_Replace(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       u_int32_t flags;
+       int isempty;
+       CHAR_T *p;
+
+       flags = set_txt_std(sp, vp, 0);
+       sp->showmode = SM_REPLACE;
+
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               len = 0;
+               LF_SET(TXT_APPENDEOL);
+       } else {
+               if (len == 0)
+                       LF_SET(TXT_APPENDEOL);
+               LF_SET(TXT_OVERWRITE | TXT_REPLACE);
+       }
+       vp->m_stop.lno = vp->m_start.lno;
+       vp->m_stop.cno = len ? len - 1 : 0;
+
+       return (v_txt(sp, vp, &vp->m_stop, p, len,
+           0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+/*
+ * v_subst -- [buffer][count]s
+ *     Substitute characters.
+ *
+ * PUBLIC: int v_subst __P((SCR *, VICMD *));
+ */
+int
+v_subst(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       u_int32_t flags;
+       int isempty;
+       CHAR_T *p;
+
+       flags = set_txt_std(sp, vp, 0);
+       sp->showmode = SM_CHANGE;
+
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               len = 0;
+               LF_SET(TXT_APPENDEOL);
+       } else {
+               if (len == 0)
+                       LF_SET(TXT_APPENDEOL);
+               LF_SET(TXT_EMARK | TXT_OVERWRITE);
+       }
+
+       vp->m_stop.lno = vp->m_start.lno;
+       vp->m_stop.cno =
+           vp->m_start.cno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0);
+       if (vp->m_stop.cno > len - 1)
+               vp->m_stop.cno = len - 1;
+
+       if (p != NULL && cut(sp,
+           F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+           &vp->m_start, &vp->m_stop, 0))
+               return (1);
+
+       return (v_txt(sp, vp, &vp->m_stop, p, len, 0, OOBLNO, 1, flags));
+}
+
+/*
+ * set_txt_std --
+ *     Initialize text processing flags.
+ */
+static u_int32_t
+set_txt_std(SCR *sp, VICMD *vp, u_int32_t flags)
+{
+       LF_SET(TXT_CNTRLT |
+           TXT_ESCAPE | TXT_MAPINPUT | TXT_RECORD | TXT_RESOLVE);
+
+       if (F_ISSET(vp, VC_ISDOT))
+               LF_SET(TXT_REPLAY);
+
+       if (O_ISSET(sp, O_ALTWERASE))
+               LF_SET(TXT_ALTWERASE);
+       if (O_ISSET(sp, O_AUTOINDENT))
+               LF_SET(TXT_AUTOINDENT);
+       if (O_ISSET(sp, O_BEAUTIFY))
+               LF_SET(TXT_BEAUTIFY);
+       if (O_ISSET(sp, O_SHOWMATCH))
+               LF_SET(TXT_SHOWMATCH);
+       if (F_ISSET(sp, SC_SCRIPT))
+               LF_SET(TXT_CR);
+       if (O_ISSET(sp, O_TTYWERASE))
+               LF_SET(TXT_TTYWERASE);
+
+       /*
+        * !!!
+        * Mapped keys were sometimes unaffected by the wrapmargin option
+        * in the historic 4BSD vi.  Consider the following commands, where
+        * each is executed on an empty line, in an 80 column screen, with
+        * the wrapmargin value set to 60.
+        *
+        *      aABC DEF <ESC>....
+        *      :map K aABC DEF ^V<ESC><CR>KKKKK
+        *      :map K 5aABC DEF ^V<ESC><CR>K
+        *
+        * The first and second commands are affected by wrapmargin.  The
+        * third is not.  (If the inserted text is itself longer than the
+        * wrapmargin value, i.e. if the "ABC DEF " string is replaced by
+        * something that's longer than 60 columns from the beginning of
+        * the line, the first two commands behave as before, but the third
+        * command gets fairly strange.)  The problem is that people wrote
+        * macros that depended on the third command NOT being affected by
+        * wrapmargin, as in this gem which centers lines:
+        *
+        *      map #c $mq81a ^V^[81^V^V|D`qld0:s/  / /g^V^M$p
+        *
+        * For compatibility reasons, we try and make it all work here.  I
+        * offer no hope that this is right, but it's probably pretty close.
+        *
+        * XXX
+        * Once I work my courage up, this is all gonna go away.  It's too
+        * evil to survive.
+        */
+       if ((O_ISSET(sp, O_WRAPLEN) || O_ISSET(sp, O_WRAPMARGIN)) &&
+           (!MAPPED_KEYS_WAITING(sp) || !F_ISSET(vp, VC_C1SET)))
+               LF_SET(TXT_WRAPMARGIN);
+       return (flags);
+}
diff --git a/dist/nvi/vi/v_left.c b/dist/nvi/vi/v_left.c
new file mode 100644 (file)
index 0000000..8827e95
--- /dev/null
@@ -0,0 +1,285 @@
+/*     $NetBSD: v_left.c,v 1.1.1.2 2008/05/18 14:31:42 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_left.c,v 10.9 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_left -- [count]^H, [count]h
+ *     Move left by columns.
+ *
+ * PUBLIC: int v_left __P((SCR *, VICMD *));
+ */
+int
+v_left(SCR *sp, VICMD *vp)
+{
+       db_recno_t cnt;
+
+       /*
+        * !!!
+        * The ^H and h commands always failed in the first column.
+        */
+       if (vp->m_start.cno == 0) {
+               v_sol(sp);
+               return (1);
+       }
+
+       /* Find the end of the range. */
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       if (vp->m_start.cno > cnt)
+               vp->m_stop.cno = vp->m_start.cno - cnt;
+       else
+               vp->m_stop.cno = 0;
+
+       /*
+        * All commands move to the end of the range.  Motion commands
+        * adjust the starting point to the character before the current
+        * one.
+        */
+       if (ISMOTION(vp))
+               --vp->m_start.cno;
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_cfirst -- [count]_
+ *     Move to the first non-blank character in a line.
+ *
+ * PUBLIC: int v_cfirst __P((SCR *, VICMD *));
+ */
+int
+v_cfirst(SCR *sp, VICMD *vp)
+{
+       db_recno_t cnt, lno;
+
+       /*
+        * !!!
+        * If the _ is a motion component, it makes the command a line motion
+        * e.g. "d_" deletes the line.  It also means that the cursor doesn't
+        * move.
+        *
+        * The _ command never failed in the first column.
+        */
+       if (ISMOTION(vp))
+               F_SET(vp, VM_LMODE);
+       /*
+        * !!!
+        * Historically a specified count makes _ move down count - 1
+        * rows, so, "3_" is the same as "2j_".
+        */
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       if (cnt != 1) {
+               --vp->count;
+               return (v_down(sp, vp));
+       }
+
+       /*
+        * Move to the first non-blank.
+        *
+        * Can't just use RCM_SET_FNB, in case _ is used as the motion
+        * component of another command.
+        */
+       vp->m_stop.cno = 0;
+       if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+               return (1);
+
+       /*
+        * !!!
+        * The _ command has to fail if the file is empty and we're doing
+        * a delete.  If deleting line 1, and 0 is the first nonblank,
+        * make the check.
+        */
+       if (vp->m_stop.lno == 1 &&
+           vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) {
+               if (db_last(sp, &lno))
+                       return (1);
+               if (lno == 0) {
+                       v_sol(sp);
+                       return (1);
+               }
+       }
+
+       /*
+        * Delete and non-motion commands move to the end of the range,
+        * yank stays at the start.  Ignore others.
+        */
+       vp->m_final =
+           ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_first -- ^
+ *     Move to the first non-blank character in this line.
+ *
+ * PUBLIC: int v_first __P((SCR *, VICMD *));
+ */
+int
+v_first(SCR *sp, VICMD *vp)
+{
+       /*
+        * !!!
+        * Yielding to none in our quest for compatibility with every
+        * historical blemish of vi, no matter how strange it might be,
+        * we permit the user to enter a count and then ignore it.
+        */
+
+       /*
+        * Move to the first non-blank.
+        *
+        * Can't just use RCM_SET_FNB, in case ^ is used as the motion
+        * component of another command.
+        */
+       vp->m_stop.cno = 0;
+       if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+               return (1);
+
+       /*
+        * !!!
+        * The ^ command succeeded if used as a command when the cursor was
+        * on the first non-blank in the line, but failed if used as a motion
+        * component in the same situation.
+        */
+       if (ISMOTION(vp) && vp->m_start.cno == vp->m_stop.cno) {
+               v_sol(sp);
+               return (1);
+       }
+
+       /*
+        * If moving right, non-motion commands move to the end of the range.
+        * Delete and yank stay at the start.  Motion commands adjust the
+        * ending point to the character before the current ending charcter.
+        *
+        * If moving left, all commands move to the end of the range.  Motion
+        * commands adjust the starting point to the character before the
+        * current starting character.
+        */
+       if (vp->m_start.cno < vp->m_stop.cno)
+               if (ISMOTION(vp)) {
+                       --vp->m_stop.cno;
+                       vp->m_final = vp->m_start;
+               } else
+                       vp->m_final = vp->m_stop;
+       else {
+               if (ISMOTION(vp))
+                       --vp->m_start.cno;
+               vp->m_final = vp->m_stop;
+       }
+       return (0);
+}
+
+/*
+ * v_ncol -- [count]|
+ *     Move to column count or the first column on this line.  If the
+ *     requested column is past EOL, move to EOL.  The nasty part is
+ *     that we have to know character column widths to make this work.
+ *
+ * PUBLIC: int v_ncol __P((SCR *, VICMD *));
+ */
+int
+v_ncol(SCR *sp, VICMD *vp)
+{
+       if (F_ISSET(vp, VC_C1SET) && vp->count > 1) {
+               --vp->count;
+               vp->m_stop.cno =
+                   vs_colpos(sp, vp->m_start.lno, (size_t)vp->count);
+               /*
+                * !!!
+                * The | command succeeded if used as a command and the cursor
+                * didn't move, but failed if used as a motion component in the
+                * same situation.
+                */
+               if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) {
+                       v_nomove(sp);
+                       return (1);
+               }
+       } else {
+               /*
+                * !!!
+                * The | command succeeded if used as a command in column 0
+                * without a count, but failed if used as a motion component
+                * in the same situation.
+                */
+               if (ISMOTION(vp) && vp->m_start.cno == 0) {
+                       v_sol(sp);
+                       return (1);
+               }
+               vp->m_stop.cno = 0;
+       }
+
+       /*
+        * If moving right, non-motion commands move to the end of the range.
+        * Delete and yank stay at the start.  Motion commands adjust the
+        * ending point to the character before the current ending charcter.
+        *
+        * If moving left, all commands move to the end of the range.  Motion
+        * commands adjust the starting point to the character before the
+        * current starting character.
+        */
+       if (vp->m_start.cno < vp->m_stop.cno)
+               if (ISMOTION(vp)) {
+                       --vp->m_stop.cno;
+                       vp->m_final = vp->m_start;
+               } else
+                       vp->m_final = vp->m_stop;
+       else {
+               if (ISMOTION(vp))
+                       --vp->m_start.cno;
+               vp->m_final = vp->m_stop;
+       }
+       return (0);
+}
+
+/*
+ * v_zero -- 0
+ *     Move to the first column on this line.
+ *
+ * PUBLIC: int v_zero __P((SCR *, VICMD *));
+ */
+int
+v_zero(SCR *sp, VICMD *vp)
+{
+       /*
+        * !!!
+        * The 0 command succeeded if used as a command in the first column
+        * but failed if used as a motion component in the same situation.
+        */
+       if (ISMOTION(vp) && vp->m_start.cno == 0) {
+               v_sol(sp);
+               return (1);
+       }
+
+       /*
+        * All commands move to the end of the range.  Motion commands
+        * adjust the starting point to the character before the current
+        * one.
+        */
+       vp->m_stop.cno = 0;
+       if (ISMOTION(vp))
+               --vp->m_start.cno;
+       vp->m_final = vp->m_stop;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_mark.c b/dist/nvi/vi/v_mark.c
new file mode 100644 (file)
index 0000000..b54d0ee
--- /dev/null
@@ -0,0 +1,248 @@
+/*     $NetBSD: v_mark.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_mark.c,v 10.12 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+enum which {BQMARK, FQMARK};
+static int mark __P((SCR *, VICMD *, int, enum which));
+
+/*
+ * v_mark -- m[a-z]
+ *     Set a mark.
+ *
+ * PUBLIC: int v_mark __P((SCR *, VICMD *));
+ */
+int
+v_mark(SCR *sp, VICMD *vp)
+{
+       return (mark_set(sp, vp->character, &vp->m_start, 1));
+}
+
+/*
+ * v_bmark -- `['`a-z]
+ *     Move to a mark.
+ *
+ * Moves to a mark, setting both row and column.
+ *
+ * !!!
+ * Although not commonly known, the "'`" and "'`" forms are historically
+ * valid.  The behavior is determined by the first character, so "`'" is
+ * the same as "``".  Remember this fact -- you'll be amazed at how many
+ * people don't know it and will be delighted that you are able to tell
+ * them.
+ *
+ * PUBLIC: int v_bmark __P((SCR *, VICMD *));
+ */
+int
+v_bmark(SCR *sp, VICMD *vp)
+{
+       return (mark(sp, vp, 1, BQMARK));
+}
+
+/*
+ * v_fmark -- '['`a-z]
+ *     Move to a mark.
+ *
+ * Move to the first nonblank character of the line containing the mark.
+ *
+ * PUBLIC: int v_fmark __P((SCR *, VICMD *));
+ */
+int
+v_fmark(SCR *sp, VICMD *vp)
+{
+       return (mark(sp, vp, 1, FQMARK));
+}
+
+/*
+ * v_emark -- <mouse click>
+ *     Mouse mark.
+ *
+ * PUBLIC: int v_emark __P((SCR *, VICMD *));
+ */
+int
+v_emark(SCR *sp, VICMD *vp)
+{
+       SMAP *smp;
+
+       smp = HMAP + vp->ev.e_lno;
+       if (smp > TMAP) {
+               msgq(sp, M_BERR, "320|Unknown cursor position.");
+               return (1);
+       }
+       vp->m_stop.lno = smp->lno;
+       vp->m_stop.cno =
+           vs_colpos(sp, smp->lno, vp->ev.e_cno + (smp->soff - 1) * sp->cols);
+       return (mark(sp, vp, 0, BQMARK));
+}
+
+/*
+ * mark --
+ *     Mark commands.
+ */
+static int
+mark(SCR *sp, VICMD *vp, int getmark, enum which cmd)
+{
+       dir_t dir;
+       MARK m;
+       size_t len;
+
+       if (getmark && mark_get(sp, vp->character, &vp->m_stop, M_BERR))
+               return (1);
+
+       /*
+        * !!!
+        * Historically, BQMARKS for character positions that no longer
+        * existed acted as FQMARKS.
+        *
+        * FQMARKS move to the first non-blank.
+        */
+       switch (cmd) {
+       case BQMARK:
+               if (db_get(sp, vp->m_stop.lno, DBG_FATAL, NULL, &len))
+                       return (1);
+               if (vp->m_stop.cno < len ||
+                   (vp->m_stop.cno == len && len == 0))
+                       break;
+
+               if (ISMOTION(vp))
+                       F_SET(vp, VM_LMODE);
+               cmd = FQMARK;
+               /* FALLTHROUGH */
+       case FQMARK:
+               vp->m_stop.cno = 0;
+               if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+                       return (1);
+               break;
+       default:
+               abort();
+       }
+
+       /* Non-motion commands move to the end of the range. */
+       if (!ISMOTION(vp)) {
+               vp->m_final = vp->m_stop;
+               return (0);
+       }
+
+       /*
+        * !!!
+        * If a motion component to a BQMARK, the cursor has to move.
+        */
+       if (cmd == BQMARK &&
+           vp->m_stop.lno == vp->m_start.lno &&
+           vp->m_stop.cno == vp->m_start.cno) {
+               v_nomove(sp);
+               return (1);
+       }
+
+       /*
+        * If the motion is in the reverse direction, switch the start and
+        * stop MARK's so that it's in a forward direction.  (There's no
+        * reason for this other than to make the tests below easier.  The
+        * code in vi.c:vi() would have done the switch.)  Both forward
+        * and backward motions can happen for any kind of search command.
+        */
+       if (vp->m_start.lno > vp->m_stop.lno ||
+           (vp->m_start.lno == vp->m_stop.lno &&
+           vp->m_start.cno > vp->m_stop.cno)) {
+               m = vp->m_start;
+               vp->m_start = vp->m_stop;
+               vp->m_stop = m;
+               dir = BACKWARD;
+       } else
+               dir = FORWARD;
+
+       /*
+        * Yank cursor motion, when associated with marks as motion commands,
+        * historically behaved as follows:
+        *
+        * ` motion                     ' motion
+        *              Line change?            Line change?
+        *              Y       N               Y       N
+        *            --------------          ---------------
+        * FORWARD:  |  NM      NM            | NM      NM
+        *           |                        |
+        * BACKWARD: |  M       M             | M       NM(1)
+        *
+        * where NM means the cursor didn't move, and M means the cursor
+        * moved to the mark.
+        *
+        * As the cursor was usually moved for yank commands associated
+        * with backward motions, this implementation regularizes it by
+        * changing the NM at position (1) to be an M.  This makes mark
+        * motions match search motions, which is probably A Good Thing.
+        *
+        * Delete cursor motion was always to the start of the text region,
+        * regardless.  Ignore other motion commands.
+        */
+#ifdef HISTORICAL_PRACTICE
+       if (ISCMD(vp->rkp, 'y')) {
+               if ((cmd == BQMARK ||
+                   cmd == FQMARK && vp->m_start.lno != vp->m_stop.lno) &&
+                   (vp->m_start.lno > vp->m_stop.lno ||
+                   vp->m_start.lno == vp->m_stop.lno &&
+                   vp->m_start.cno > vp->m_stop.cno))
+                       vp->m_final = vp->m_stop;
+       } else if (ISCMD(vp->rkp, 'd'))
+               if (vp->m_start.lno > vp->m_stop.lno ||
+                   vp->m_start.lno == vp->m_stop.lno &&
+                   vp->m_start.cno > vp->m_stop.cno)
+                       vp->m_final = vp->m_stop;
+#else
+       vp->m_final = vp->m_start;
+#endif
+
+       /*
+        * Forward marks are always line oriented, and it's set in the
+        * vcmd.c table.
+        */
+       if (cmd == FQMARK)
+               return (0);
+
+       /*
+        * BQMARK'S moving backward and starting at column 0, and ones moving
+        * forward and ending at column 0 are corrected to the last column of
+        * the previous line.  Otherwise, adjust the starting/ending point to
+        * the character before the current one (this is safe because we know
+        * the search had to move to succeed).
+        *
+        * Mark motions become line mode opertions if they start at the first
+        * nonblank and end at column 0 of another line.
+        */
+       if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
+               if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+                       return (1);
+               vp->m_stop.cno = len ? len - 1 : 0;
+               len = 0;
+               if (nonblank(sp, vp->m_start.lno, &len))
+                       return (1);
+               if (vp->m_start.cno <= len)
+                       F_SET(vp, VM_LMODE);
+       } else
+               --vp->m_stop.cno;
+
+       return (0);
+}
diff --git a/dist/nvi/vi/v_match.c b/dist/nvi/vi/v_match.c
new file mode 100644 (file)
index 0000000..be80b9a
--- /dev/null
@@ -0,0 +1,170 @@
+/*     $NetBSD: v_match.c,v 1.5 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_match.c,v 10.10 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_match -- %
+ *     Search to matching character.
+ *
+ * PUBLIC: int v_match __P((SCR *, VICMD *));
+ */
+int
+v_match(SCR *sp, VICMD *vp)
+{
+       VCS cs;
+       MARK *mp;
+       size_t cno, len, off;
+       int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *));
+       CHAR_T *p;
+       char *cp;
+       const char *match_chars;
+
+       static MARK match = { 0, 0 };
+       static int match_dir;
+
+       /*
+        * Historically vi would match (), {} and [] however
+        * an update included <>.  This is ok for editing HTML
+        * but a pain in the butt for C source.
+        * Making it an option lets the user decide what is 'right'.
+        * Also fixed to do something sensible with "".
+        */
+       match_chars = O_STR(sp, O_MATCHCHARS);
+
+       /*
+        * !!!
+        * Historic practice; ignore the count.
+        *
+        * !!!
+        * Historical practice was to search for the initial character in the
+        * forward direction only.
+        */
+       if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+               if (isempty)
+                       goto nomatch;
+               return (1);
+       }
+       for (off = vp->m_start.cno;; ++off) {
+               if (off >= len) {
+nomatch:               msgq(sp, M_BERR, "184|No match character on this line");
+                       return (1);
+               }
+               startc = p[off];
+               cp = strchr(match_chars, startc);
+               if (cp != NULL)
+                       break;
+       }
+       cnt = cp - match_chars;
+       matchc = match_chars[cnt ^ 1];
+
+       /* Alternate back-forward search if startc and matchc the same */
+       if (startc == matchc) {
+               /* are we continuing from where last match finished? */
+               if (match.lno == vp->m_start.lno && match.cno ==vp->m_start.cno)
+                       /* yes - continue in sequence */
+                       match_dir++;
+               else
+                       /* no - go forward, back, back, forward */
+                       match_dir = 1;
+               if (match_dir & 2)
+                       cnt++;
+       }
+       gc = cnt & 1 ? cs_prev : cs_next;
+
+       cs.cs_lno = vp->m_start.lno;
+       cs.cs_cno = off;
+       if (cs_init(sp, &cs))
+               return (1);
+       for (cnt = 1;;) {
+               if (gc(sp, &cs))
+                       return (1);
+               if (cs.cs_flags != 0) {
+                       if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
+                               break;
+                       continue;
+               }
+               if (cs.cs_ch == matchc && --cnt == 0)
+                       break;
+               if (cs.cs_ch == startc)
+                       ++cnt;
+       }
+       if (cnt) {
+               msgq(sp, M_BERR, "185|Matching character not found");
+               return (1);
+       }
+
+       vp->m_stop.lno = cs.cs_lno;
+       vp->m_stop.cno = cs.cs_cno;
+
+       /*
+        * If moving right, non-motion commands move to the end of the range.
+        * Delete and yank stay at the start.
+        *
+        * If moving left, all commands move to the end of the range.
+        *
+        * !!!
+        * Don't correct for leftward movement -- historic vi deleted the
+        * starting cursor position when deleting to a match.
+        */
+       if (vp->m_start.lno < vp->m_stop.lno ||
+           (vp->m_start.lno == vp->m_stop.lno &&
+           vp->m_start.cno < vp->m_stop.cno))
+               vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       else
+               vp->m_final = vp->m_stop;
+
+       match.lno = vp->m_final.lno;
+       match.cno = vp->m_final.cno;
+
+       /*
+        * !!!
+        * If the motion is across lines, and the earliest cursor position
+        * is at or before any non-blank characters in the line, i.e. the
+        * movement is cutting all of the line's text, and the later cursor
+        * position has nothing other than whitespace characters between it
+        * and the end of its line, the buffer is in line mode.
+        */
+       if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno)
+               return (0);
+       mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop;
+       if (mp->cno != 0) {
+               cno = 0;
+               if (nonblank(sp, mp->lno, &cno))
+                       return (1);
+               if (cno < mp->cno)
+                       return (0);
+       }
+       mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start;
+       if (db_get(sp, mp->lno, DBG_FATAL, &p, &len))
+               return (1);
+       for (p += mp->cno + 1, len -= mp->cno; --len; ++p)
+               if (!ISBLANK((UCHAR_T)*p))
+                       return (0);
+       F_SET(vp, VM_LMODE);
+       return (0);
+}
diff --git a/dist/nvi/vi/v_paragraph.c b/dist/nvi/vi/v_paragraph.c
new file mode 100644 (file)
index 0000000..8891439
--- /dev/null
@@ -0,0 +1,344 @@
+/*     $NetBSD: v_paragraph.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_paragraph.c,v 10.10 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+#define        INTEXT_CHECK {                                                  \
+       if (len == 0 || v_isempty(p, len)) {                            \
+               if (!--cnt)                                             \
+                       goto found;                                     \
+               pstate = P_INBLANK;                                     \
+       }                                                               \
+       /*                                                              \
+        * !!!                                                          \
+        * Historic documentation (USD:15-11, 4.2) said that formfeed   \
+        * characters (^L) in the first column delimited paragraphs.    \
+        * The historic vi code mentions formfeed characters, but never \
+        * implements them.  It seems reasonable, do it.                \
+        */                                                             \
+       if (p[0] == '\014') {                                           \
+               if (!--cnt)                                             \
+                       goto found;                                     \
+               continue;                                               \
+       }                                                               \
+       if (p[0] != '.' || len < 2)                                     \
+               continue;                                               \
+       for (lp = VIP(sp)->ps; *lp != '\0'; lp += 2)                    \
+               if (lp[0] == p[1] &&                                    \
+                   ((lp[1] == ' ' && len == 2) || lp[1] == p[2]) &&    \
+                   !--cnt)                                             \
+                       goto found;                                     \
+}
+
+/*
+ * v_paragraphf -- [count]}
+ *     Move forward count paragraphs.
+ *
+ * Paragraphs are empty lines after text, formfeed characters, or values
+ * from the paragraph or section options.
+ *
+ * PUBLIC: int v_paragraphf __P((SCR *, VICMD *));
+ */
+int
+v_paragraphf(SCR *sp, VICMD *vp)
+{
+       enum { P_INTEXT, P_INBLANK } pstate;
+       size_t lastlen, len;
+       db_recno_t cnt, lastlno, lno;
+       int isempty;
+       CHAR_T *p;
+       char *lp;
+
+       /*
+        * !!!
+        * If the starting cursor position is at or before any non-blank
+        * characters in the line, i.e. the movement is cutting all of the
+        * line's text, the buffer is in line mode.  It's a lot easier to
+        * check here, because we know that the end is going to be the start
+        * or end of a line.
+        *
+        * This was historical practice in vi, with a single exception.  If
+        * the paragraph movement was from the start of the last line to EOF,
+        * then all the characters were deleted from the last line, but the
+        * line itself remained.  If somebody complains, don't pause, don't
+        * hesitate, just hit them.
+        */
+       if (ISMOTION(vp)) {
+               if (vp->m_start.cno == 0)
+                       F_SET(vp, VM_LMODE);
+               else {
+                       vp->m_stop = vp->m_start;
+                       vp->m_stop.cno = 0;
+                       if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+                               return (1);
+                       if (vp->m_start.cno <= vp->m_stop.cno)
+                               F_SET(vp, VM_LMODE);
+               }
+       }
+
+       /* Figure out what state we're currently in. */
+       lno = vp->m_start.lno;
+       if (db_get(sp, lno, 0, &p, &len))
+               goto eof;
+
+       /*
+        * If we start in text, we want to switch states
+        * (2 * N - 1) times, in non-text, (2 * N) times.
+        */
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       cnt *= 2;
+       if (len == 0 || v_isempty(p, len))
+               pstate = P_INBLANK;
+       else {
+               --cnt;
+               pstate = P_INTEXT;
+       }
+
+       for (;;) {
+               lastlno = lno;
+               lastlen = len;
+               if (db_get(sp, ++lno, 0, &p, &len))
+                       goto eof;
+               switch (pstate) {
+               case P_INTEXT:
+                       INTEXT_CHECK;
+                       break;
+               case P_INBLANK:
+                       if (len == 0 || v_isempty(p, len))
+                               break;
+                       if (--cnt) {
+                               pstate = P_INTEXT;
+                               break;
+                       }
+                       /*
+                        * !!!
+                        * Non-motion commands move to the end of the range,
+                        * delete and yank stay at the start.  Ignore others.
+                        * Adjust the end of the range for motion commands;
+                        * historically, a motion component was to the end of
+                        * the previous line, whereas the movement command was
+                        * to the start of the new "paragraph".
+                        */
+found:                 if (ISMOTION(vp)) {
+                               vp->m_stop.lno = lastlno;
+                               vp->m_stop.cno = lastlen ? lastlen - 1 : 0;
+                               vp->m_final = vp->m_start;
+                       } else {
+                               vp->m_stop.lno = lno;
+                               vp->m_stop.cno = 0;
+                               vp->m_final = vp->m_stop;
+                       }
+                       return (0);
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * !!!
+        * Adjust end of the range for motion commands; EOF is a movement
+        * sink.  The } command historically moved to the end of the last
+        * line, not the beginning, from any position before the end of the
+        * last line.  It also historically worked on empty files, so we
+        * have to make it okay.
+        */
+eof:   if (vp->m_start.lno == lno || vp->m_start.lno == lno - 1) {
+               if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+                       if (!isempty)
+                               return (1);
+                       vp->m_start.cno = 0;
+                       return (0);
+               }
+               if (vp->m_start.cno == (len ? len - 1 : 0)) {
+                       v_eof(sp, NULL);
+                       return (1);
+               }
+       }
+       /*
+        * !!!
+        * Non-motion commands move to the end of the range, delete
+        * and yank stay at the start.  Ignore others.
+        *
+        * If deleting the line (which happens if deleting to EOF), then
+        * cursor movement is to the first nonblank.
+        */
+       if (ISMOTION(vp) && ISCMD(vp->rkp, 'd')) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SETFNB);
+       }
+       vp->m_stop.lno = lno - 1;
+       vp->m_stop.cno = len ? len - 1 : 0;
+       vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_paragraphb -- [count]{
+ *     Move backward count paragraphs.
+ *
+ * PUBLIC: int v_paragraphb __P((SCR *, VICMD *));
+ */
+int
+v_paragraphb(SCR *sp, VICMD *vp)
+{
+       enum { P_INTEXT, P_INBLANK } pstate;
+       size_t len;
+       db_recno_t cnt, lno;
+       CHAR_T *p;
+       char *lp;
+
+       /*
+        * !!!
+        * Check for SOF.  The historic vi didn't complain if users hit SOF
+        * repeatedly, unless it was part of a motion command.  There is no
+        * question but that Emerson's editor of choice was vi.
+        *
+        * The { command historically moved to the beginning of the first
+        * line if invoked on the first line.
+        *
+        * !!!
+        * If the starting cursor position is in the first column (backward
+        * paragraph movements did NOT historically pay attention to non-blank
+        * characters) i.e. the movement is cutting the entire line, the buffer
+        * is in line mode.  Cuts from the beginning of the line also did not
+        * cut the current line, but started at the previous EOL.
+        *
+        * Correct for a left motion component while we're thinking about it.
+        */
+       lno = vp->m_start.lno;
+
+       if (ISMOTION(vp)) {
+               if (vp->m_start.cno == 0) {
+                       if (vp->m_start.lno == 1) {
+                               v_sof(sp, &vp->m_start);
+                               return (1);
+                       } else
+                               --vp->m_start.lno;
+                       F_SET(vp, VM_LMODE);
+               } else
+                       --vp->m_start.cno;
+       }
+
+       if (vp->m_start.lno <= 1)
+               goto sof;
+
+       /* Figure out what state we're currently in. */
+       if (db_get(sp, lno, 0, &p, &len))
+               goto sof;
+
+       /*
+        * If we start in text, we want to switch states
+        * (2 * N - 1) times, in non-text, (2 * N) times.
+        */
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       cnt *= 2;
+       if (len == 0 || v_isempty(p, len))
+               pstate = P_INBLANK;
+       else {
+               --cnt;
+               pstate = P_INTEXT;
+
+               /*
+                * !!!
+                * If the starting cursor is past the first column,
+                * the current line is checked for a paragraph.
+                */
+               if (vp->m_start.cno > 0)
+                       ++lno;
+       }
+
+       for (;;) {
+               if (db_get(sp, --lno, 0, &p, &len))
+                       goto sof;
+               switch (pstate) {
+               case P_INTEXT:
+                       INTEXT_CHECK;
+                       break;
+               case P_INBLANK:
+                       if (len != 0 && !v_isempty(p, len)) {
+                               if (!--cnt)
+                                       goto found;
+                               pstate = P_INTEXT;
+                       }
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /* SOF is a movement sink. */
+sof:   lno = 1;
+
+found: vp->m_stop.lno = lno;
+       vp->m_stop.cno = 0;
+
+       /*
+        * All commands move to the end of the range.  (We already
+        * adjusted the start of the range for motion commands).
+        */
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_buildps --
+ *     Build the paragraph command search pattern.
+ *
+ * PUBLIC: int v_buildps __P((SCR *, const char *, const char *));
+ */
+int
+v_buildps(SCR *sp, const char *p_p, const char *s_p)
+{
+       VI_PRIVATE *vip;
+       size_t p_len, s_len;
+       char *p;
+
+       /*
+        * The vi paragraph command searches for either a paragraph or
+        * section option macro.
+        */
+       p_len = p_p == NULL ? 0 : strlen(p_p);
+       s_len = s_p == NULL ? 0 : strlen(s_p);
+
+       if (p_len == 0 && s_len == 0)
+               return (0);
+
+       MALLOC_RET(sp, p, char *, p_len + s_len + 1);
+
+       vip = VIP(sp);
+       if (vip->ps != NULL)
+               free(vip->ps);
+
+       if (p_p != NULL)
+               memmove(p, p_p, p_len + 1);
+       if (s_p != NULL)
+               memmove(p + p_len, s_p, s_len + 1);
+       vip->ps = p;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_put.c b/dist/nvi/vi/v_put.c
new file mode 100644 (file)
index 0000000..3cb08d7
--- /dev/null
@@ -0,0 +1,142 @@
+/*     $NetBSD: v_put.c,v 1.1.1.2 2008/05/18 14:31:43 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_put.c,v 10.6 2001/06/25 15:19:34 skimo Exp (Berkeley) Date: 2001/06/25 15:19:34";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static void    inc_buf __P((SCR *, VICMD *));
+
+/*
+ * v_Put -- [buffer]P
+ *     Insert the contents of the buffer before the cursor.
+ *
+ * PUBLIC: int v_Put __P((SCR *, VICMD *));
+ */
+int
+v_Put(SCR *sp, VICMD *vp)
+{
+       u_long cnt;
+
+       if (F_ISSET(vp, VC_ISDOT))
+               inc_buf(sp, vp);
+
+       /*
+        * !!!
+        * Historic vi did not support a count with the 'p' and 'P'
+        * commands.  It's useful, so we do.
+        */
+       for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
+               if (put(sp, NULL,
+                   F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+                   &vp->m_start, &vp->m_final, 0))
+                       return (1);
+               vp->m_start = vp->m_final;
+               if (INTERRUPTED(sp))
+                       return (1);
+       }
+       return (0);
+}
+
+/*
+ * v_put -- [buffer]p
+ *     Insert the contents of the buffer after the cursor.
+ *
+ * PUBLIC: int v_put __P((SCR *, VICMD *));
+ */
+int
+v_put(SCR *sp, VICMD *vp)
+{
+       u_long cnt;
+
+       if (F_ISSET(vp, VC_ISDOT))
+               inc_buf(sp, vp);
+
+       /*
+        * !!!
+        * Historic vi did not support a count with the 'p' and 'P'
+        * commands.  It's useful, so we do.
+        */
+       for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
+               if (put(sp, NULL,
+                   F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+                   &vp->m_start, &vp->m_final, 1))
+                       return (1);
+               vp->m_start = vp->m_final;
+               if (INTERRUPTED(sp))
+                       return (1);
+       }
+       return (0);
+}
+
+/*
+ * !!!
+ * Historical whackadoo.  The dot command `puts' the numbered buffer
+ * after the last one put.  For example, `"4p.' would put buffer #4
+ * and buffer #5.  If the user continued to enter '.', the #9 buffer
+ * would be repeatedly output.  This was not documented, and is a bit
+ * tricky to reconstruct.  Historical versions of vi also dropped the
+ * contents of the default buffer after each put, so after `"4p' the
+ * default buffer would be empty.  This makes no sense to me, so we
+ * don't bother.  Don't assume sequential order of numeric characters.
+ *
+ * And, if that weren't exciting enough, failed commands don't normally
+ * set the dot command.  Well, boys and girls, an exception is that
+ * the buffer increment gets done regardless of the success of the put.
+ */
+static void
+inc_buf(SCR *sp, VICMD *vp)
+{
+       CHAR_T v;
+
+       switch (vp->buffer) {
+       case '1':
+               v = '2';
+               break;
+       case '2':
+               v = '3';
+               break;
+       case '3':
+               v = '4';
+               break;
+       case '4':
+               v = '5';
+               break;
+       case '5':
+               v = '6';
+               break;
+       case '6':
+               v = '7';
+               break;
+       case '7':
+               v = '8';
+               break;
+       case '8':
+               v = '9';
+               break;
+       default:
+               return;
+       }
+       VIP(sp)->sdot.buffer = vp->buffer = v;
+}
diff --git a/dist/nvi/vi/v_redraw.c b/dist/nvi/vi/v_redraw.c
new file mode 100644 (file)
index 0000000..9789d13
--- /dev/null
@@ -0,0 +1,39 @@
+/*     $NetBSD: v_redraw.c,v 1.1.1.2 2008/05/18 14:31:43 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_redraw.c,v 10.7 2001/06/25 15:19:34 skimo Exp (Berkeley) Date: 2001/06/25 15:19:34";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_redraw -- ^L, ^R
+ *     Redraw the screen.
+ *
+ * PUBLIC: int v_redraw __P((SCR *, VICMD *));
+ */
+int
+v_redraw(SCR *sp, VICMD *vp)
+{
+       return (sp->gp->scr_refresh(sp, 1));
+}
diff --git a/dist/nvi/vi/v_replace.c b/dist/nvi/vi/v_replace.c
new file mode 100644 (file)
index 0000000..faf2d16
--- /dev/null
@@ -0,0 +1,204 @@
+/*     $NetBSD: v_replace.c,v 1.3 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_replace.c,v 10.24 2001/06/25 15:19:34 skimo Exp (Berkeley) Date: 2001/06/25 15:19:34";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_replace -- [count]r<char>
+ *
+ * !!!
+ * The r command in historic vi was almost beautiful in its badness.  For
+ * example, "r<erase>" and "r<word erase>" beeped the terminal and deleted
+ * a single character.  "Nr<carriage return>", where N was greater than 1,
+ * inserted a single carriage return.  "r<escape>" did cancel the command,
+ * but "r<literal><escape>" erased a single character.  To enter a literal
+ * <literal> character, it required three <literal> characters after the
+ * command.  This may not be right, but at least it's not insane.
+ *
+ * PUBLIC: int v_replace __P((SCR *, VICMD *));
+ */
+int
+v_replace(SCR *sp, VICMD *vp)
+{
+       EVENT ev;
+       VI_PRIVATE *vip;
+       TEXT *tp;
+       size_t blen, len;
+       u_long cnt;
+       int quote, rval;
+       CHAR_T *bp;
+       CHAR_T *p;
+
+       vip = VIP(sp);
+
+       /*
+        * If the line doesn't exist, or it's empty, replacement isn't
+        * allowed.  It's not hard to implement, but:
+        *
+        *      1: It's historic practice (vi beeped before the replacement
+        *         character was even entered).
+        *      2: For consistency, this change would require that the more
+        *         general case, "Nr", when the user is < N characters from
+        *         the end of the line, also work, which would be a bit odd.
+        *      3: Replacing with a <newline> has somewhat odd semantics.
+        */
+       if (db_get(sp, vp->m_start.lno, DBG_FATAL, &p, &len))
+               return (1);
+       if (len == 0) {
+               msgq(sp, M_BERR, "186|No characters to replace");
+               return (1);
+       }
+
+       /*
+        * Figure out how many characters to be replace.  For no particular
+        * reason (other than that the semantics of replacing the newline
+        * are confusing) only permit the replacement of the characters in
+        * the current line.  I suppose we could append replacement characters
+        * to the line, but I see no compelling reason to do so.  Check this
+        * before we get the character to match historic practice, where Nr
+        * failed immediately if there were less than N characters from the
+        * cursor to the end of the line.
+        */
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       vp->m_stop.lno = vp->m_start.lno;
+       vp->m_stop.cno = vp->m_start.cno + cnt - 1;
+       if (vp->m_stop.cno > len - 1) {
+               v_eol(sp, &vp->m_start);
+               return (1);
+       }
+
+       /*
+        * If it's not a repeat, reset the current mode and get a replacement
+        * character.
+        */
+       quote = 0;
+       if (!F_ISSET(vp, VC_ISDOT)) {
+               sp->showmode = SM_REPLACE;
+               if (vs_refresh(sp, 0))
+                       return (1);
+next:          if (v_event_get(sp, &ev, 0, 0))
+                       return (1);
+
+               switch (ev.e_event) {
+               case E_CHARACTER:
+                       /*
+                        * <literal_next> means escape the next character.
+                        * <escape> means they changed their minds.
+                        */
+                       if (!quote) {
+                               if (ev.e_value == K_VLNEXT) {
+                                       quote = 1;
+                                       goto next;
+                               }
+                               if (ev.e_value == K_ESCAPE)
+                                       return (0);
+                       }
+                       vip->rlast = ev.e_c;
+                       vip->rvalue = ev.e_value;
+                       break;
+               case E_ERR:
+               case E_EOF:
+                       F_SET(sp, SC_EXIT_FORCE);
+                       return (1);
+               case E_INTERRUPT:
+                       /* <interrupt> means they changed their minds. */
+                       return (0);
+               case E_WRESIZE:
+                       /* <resize> interrupts the input mode. */
+                       v_emsg(sp, NULL, VIM_WRESIZE);
+                       return (0);
+               case E_REPAINT:
+                       if (v_erepaint(sp, &ev))
+                               return (1);
+                       goto next;
+               default:
+                       v_event_err(sp, &ev);
+                       return (0);
+               }
+       }
+
+       /* Copy the line. */
+       GET_SPACE_RETW(sp, bp, blen, len);
+       MEMMOVE(bp, p, len);
+       p = bp;
+
+       /*
+        * Versions of nvi before 1.57 created N new lines when they replaced
+        * N characters with <carriage-return> or <newline> characters.  This
+        * is different from the historic vi, which replaced N characters with
+        * a single new line.  Users complained, so we match historic practice.
+        */
+       if ((!quote && vip->rvalue == K_CR) || vip->rvalue == K_NL) {
+               /* Set return line. */
+               vp->m_stop.lno = vp->m_start.lno + 1;
+               vp->m_stop.cno = 0;
+
+               /* The first part of the current line. */
+               if (db_set(sp, vp->m_start.lno, p, vp->m_start.cno))
+                       goto err_ret;
+
+               /*
+                * The rest of the current line.  And, of course, now it gets
+                * tricky.  If there are characters left in the line and if
+                * the autoindent edit option is set, white space after the
+                * replaced character is discarded, autoindent is applied, and
+                * the cursor moves to the last indent character.
+                */
+               p += vp->m_start.cno + cnt;
+               len -= vp->m_start.cno + cnt;
+               if (len != 0 && O_ISSET(sp, O_AUTOINDENT))
+                       for (; len && ISBLANK((UCHAR_T)*p); --len, ++p);
+
+               if ((tp = text_init(sp, p, len, len)) == NULL)
+                       goto err_ret;
+
+               if (len != 0 && O_ISSET(sp, O_AUTOINDENT)) {
+                       if (v_txt_auto(sp, vp->m_start.lno, NULL, 0, tp))
+                               goto err_ret;
+                       vp->m_stop.cno = tp->ai ? tp->ai - 1 : 0;
+               } else
+                       vp->m_stop.cno = 0;
+
+               vp->m_stop.cno = tp->ai ? tp->ai - 1 : 0;
+               if (db_append(sp, 1, vp->m_start.lno, tp->lb, tp->len))
+err_ret:               rval = 1;
+               else {
+                       text_free(tp);
+                       rval = 0;
+               }
+       } else {
+               STRSET(bp + vp->m_start.cno, vip->rlast, cnt);
+               rval = db_set(sp, vp->m_start.lno, bp, len);
+       }
+       FREE_SPACEW(sp, bp, blen);
+
+       vp->m_final = vp->m_stop;
+       return (rval);
+}
diff --git a/dist/nvi/vi/v_right.c b/dist/nvi/vi/v_right.c
new file mode 100644 (file)
index 0000000..9f38dfc
--- /dev/null
@@ -0,0 +1,143 @@
+/*     $NetBSD: v_right.c,v 1.1.1.2 2008/05/18 14:31:43 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_right.c,v 10.8 2001/06/25 15:19:34 skimo Exp (Berkeley) Date: 2001/06/25 15:19:34";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_right -- [count]' ', [count]l
+ *     Move right by columns.
+ *
+ * PUBLIC: int v_right __P((SCR *, VICMD *));
+ */
+int
+v_right(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       int isempty;
+
+       if (db_eget(sp, vp->m_start.lno, NULL, &len, &isempty)) {
+               if (isempty)
+                       goto eol;
+               return (1);
+       }
+
+       /* It's always illegal to move right on empty lines. */
+       if (len == 0) {
+eol:           v_eol(sp, NULL);
+               return (1);
+       }
+
+       /*
+        * Non-motion commands move to the end of the range.  Delete and
+        * yank stay at the start.  Ignore others.  Adjust the end of the
+        * range for motion commands.
+        *
+        * !!!
+        * Historically, "[cdsy]l" worked at the end of a line.  Also,
+        * EOL is a count sink.
+        */
+       vp->m_stop.cno = vp->m_start.cno +
+           (F_ISSET(vp, VC_C1SET) ? vp->count : 1);
+       if (vp->m_start.cno == len - 1 && !ISMOTION(vp)) {
+               v_eol(sp, NULL);
+               return (1);
+       }
+       if (vp->m_stop.cno >= len) {
+               vp->m_stop.cno = len - 1;
+               vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       } else if (ISMOTION(vp)) {
+               --vp->m_stop.cno;
+               vp->m_final = vp->m_start;
+       } else
+               vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_dollar -- [count]$
+ *     Move to the last column.
+ *
+ * PUBLIC: int v_dollar __P((SCR *, VICMD *));
+ */
+int
+v_dollar(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       int isempty;
+
+       /*
+        * !!!
+        * A count moves down count - 1 rows, so, "3$" is the same as "2j$".
+        */
+       if ((F_ISSET(vp, VC_C1SET) ? vp->count : 1) != 1) {
+               /*
+                * !!!
+                * Historically, if the $ is a motion, and deleting from
+                * at or before the first non-blank of the line, it's a
+                * line motion, and the line motion flag is set.
+                */
+               vp->m_stop.cno = 0;
+               if (nonblank(sp, vp->m_start.lno, &vp->m_stop.cno))
+                       return (1);
+               if (ISMOTION(vp) && vp->m_start.cno <= vp->m_stop.cno)
+                       F_SET(vp, VM_LMODE);
+
+               --vp->count;
+               if (v_down(sp, vp))
+                       return (1);
+       }
+
+       /*
+        * !!!
+        * Historically, it was illegal to use $ as a motion command on
+        * an empty line.  Unfortunately, even though C was historically
+        * aliased to c$, it (and not c$) was special cased to work on
+        * empty lines.  Since we alias C to c$ too, we have a problem.
+        * To fix it, we let c$ go through, on the assumption that it's
+        * not a problem for it to work.
+        */
+       if (db_eget(sp, vp->m_stop.lno, NULL, &len, &isempty)) {
+               if (!isempty)
+                       return (1);
+               len = 0;
+       }
+
+       if (len == 0) {
+               if (ISMOTION(vp) && !ISCMD(vp->rkp, 'c')) {
+                       v_eol(sp, NULL);
+                       return (1);
+               }
+               return (0);
+       }
+
+       /*
+        * Non-motion commands move to the end of the range.  Delete
+        * and yank stay at the start.  Ignore others.
+        */
+       vp->m_stop.cno = len ? len - 1 : 0;
+       vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_screen.c b/dist/nvi/vi/v_screen.c
new file mode 100644 (file)
index 0000000..efe4b84
--- /dev/null
@@ -0,0 +1,65 @@
+/*     $NetBSD: v_screen.c,v 1.1.1.2 2008/05/18 14:31:43 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_screen.c,v 10.12 2001/06/25 15:19:34 skimo Exp (Berkeley) Date: 2001/06/25 15:19:34";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_screen -- ^W
+ *     Switch screens.
+ *
+ * PUBLIC: int v_screen __P((SCR *, VICMD *));
+ */
+int
+v_screen(SCR *sp, VICMD *vp)
+{
+       /*
+        * You can't leave a colon command-line edit window -- it's not that
+        * it won't work, but it gets real weird, real fast when you execute
+        * a colon command out of a window that was forked from a window that's
+        * now backgrounded...  You get the idea.
+        */
+       if (F_ISSET(sp, SC_COMEDIT)) {
+               msgq(sp, M_ERR,
+                   "308|Enter <CR> to execute a command, :q to exit");
+               return (1);
+       }
+               
+       /*
+        * Try for the next lower screen, or, go back to the first
+        * screen on the stack.
+        */
+       if (sp->q.cqe_next != (void *)&sp->wp->scrq)
+               sp->nextdisp = sp->q.cqe_next;
+       else if (sp->wp->scrq.cqh_first == sp) {
+               msgq(sp, M_ERR, "187|No other screen to switch to");
+               return (1);
+       } else
+               sp->nextdisp = sp->wp->scrq.cqh_first;
+
+       F_SET(sp->nextdisp, SC_STATUS);
+       F_SET(sp, SC_SSWITCH | SC_STATUS);
+       return (0);
+}
diff --git a/dist/nvi/vi/v_scroll.c b/dist/nvi/vi/v_scroll.c
new file mode 100644 (file)
index 0000000..e163a9a
--- /dev/null
@@ -0,0 +1,449 @@
+/*     $NetBSD: v_scroll.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_scroll.c,v 10.12 2001/06/25 15:19:34 skimo Exp (Berkeley) Date: 2001/06/25 15:19:34";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static void goto_adjust __P((VICMD *));
+
+/*
+ * The historic vi had a problem in that all movements were by physical
+ * lines, not by logical, or screen lines.  Arguments can be made that this
+ * is the right thing to do.  For example, single line movements, such as
+ * 'j' or 'k', should probably work on physical lines.  Commands like "dj",
+ * or "j.", where '.' is a change command, make more sense for physical lines
+ * than they do for logical lines.
+ *
+ * These arguments, however, don't apply to scrolling commands like ^D and
+ * ^F -- if the window is fairly small, using physical lines can result in
+ * a half-page scroll repainting the entire screen, which is not what the
+ * user wanted.  Second, if the line is larger than the screen, using physical
+ * lines can make it impossible to display parts of the line -- there aren't
+ * any commands that don't display the beginning of the line in historic vi,
+ * and if both the beginning and end of the line can't be on the screen at
+ * the same time, you lose.  This is even worse in the case of the H, L, and
+ * M commands -- for large lines, they may all refer to the same line and
+ * will result in no movement at all.
+ *
+ * Another issue is that page and half-page scrolling commands historically
+ * moved to the first non-blank character in the new line.  If the line is
+ * approximately the same size as the screen, this loses because the cursor
+ * before and after a ^D, may refer to the same location on the screen.  In
+ * this implementation, scrolling commands set the cursor to the first non-
+ * blank character if the line changes because of the scroll.  Otherwise,
+ * the cursor is left alone.
+ *
+ * This implementation does the scrolling (^B, ^D, ^F, ^U, ^Y, ^E), and the
+ * cursor positioning commands (H, L, M) commands using logical lines, not
+ * physical.
+ */
+
+/*
+ * v_lgoto -- [count]G
+ *     Go to first non-blank character of the line count, the last line
+ *     of the file by default.
+ *
+ * PUBLIC: int v_lgoto __P((SCR *, VICMD *));
+ */
+int
+v_lgoto(SCR *sp, VICMD *vp)
+{
+       db_recno_t nlines;
+
+       if (F_ISSET(vp, VC_C1SET)) {
+               if (!db_exist(sp, vp->count)) {
+                       /*
+                        * !!!
+                        * Historically, 1G was legal in an empty file.
+                        */
+                       if (vp->count == 1) {
+                               if (db_last(sp, &nlines))
+                                       return (1);
+                               if (nlines == 0)
+                                       return (0);
+                       }
+                       v_eof(sp, &vp->m_start);
+                       return (1);
+               }
+               vp->m_stop.lno = vp->count;
+       } else {
+               if (db_last(sp, &nlines))
+                       return (1);
+               vp->m_stop.lno = nlines ? nlines : 1;
+       }
+       goto_adjust(vp);
+       return (0);
+}
+
+/*
+ * v_home -- [count]H
+ *     Move to the first non-blank character of the logical line
+ *     count - 1 from the top of the screen, 0 by default.
+ *
+ * PUBLIC: int v_home __P((SCR *, VICMD *));
+ */
+int
+v_home(SCR *sp, VICMD *vp)
+{
+       if (vs_sm_position(sp, &vp->m_stop,
+           F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0, P_TOP))
+               return (1);
+       goto_adjust(vp);
+       return (0);
+}
+
+/*
+ * v_middle -- M
+ *     Move to the first non-blank character of the logical line
+ *     in the middle of the screen.
+ *
+ * PUBLIC: int v_middle __P((SCR *, VICMD *));
+ */
+int
+v_middle(SCR *sp, VICMD *vp)
+{
+       /*
+        * Yielding to none in our quest for compatibility with every
+        * historical blemish of vi, no matter how strange it might be,
+        * we permit the user to enter a count and then ignore it.
+        */
+       if (vs_sm_position(sp, &vp->m_stop, 0, P_MIDDLE))
+               return (1);
+       goto_adjust(vp);
+       return (0);
+}
+
+/*
+ * v_bottom -- [count]L
+ *     Move to the first non-blank character of the logical line
+ *     count - 1 from the bottom of the screen, 0 by default.
+ *
+ * PUBLIC: int v_bottom __P((SCR *, VICMD *));
+ */
+int
+v_bottom(SCR *sp, VICMD *vp)
+{
+       if (vs_sm_position(sp, &vp->m_stop,
+           F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0, P_BOTTOM))
+               return (1);
+       goto_adjust(vp);
+       return (0);
+}
+
+static void
+goto_adjust(VICMD *vp)
+{
+       /* Guess that it's the end of the range. */
+       vp->m_final = vp->m_stop;
+
+       /*
+        * Non-motion commands move the cursor to the end of the range, and
+        * then to the NEXT nonblank of the line.  Historic vi always moved
+        * to the first nonblank in the line; since the H, M, and L commands
+        * are logical motions in this implementation, we do the next nonblank
+        * so that it looks approximately the same to the user.  To make this
+        * happen, the VM_RCM_SETNNB flag is set in the vcmd.c command table.
+        *
+        * If it's a motion, it's more complicated.  The best possible solution
+        * is probably to display the first nonblank of the line the cursor
+        * will eventually rest on.  This is tricky, particularly given that if
+        * the associated command is a delete, we don't yet know what line that
+        * will be.  So, we clear the VM_RCM_SETNNB flag, and set the first
+        * nonblank flag (VM_RCM_SETFNB).  Note, if the lines are sufficiently
+        * long, this can cause the cursor to warp out of the screen.  It's too
+        * hard to fix.
+        *
+        * XXX
+        * The G command is always first nonblank, so it's okay to reset it.
+        */
+       if (ISMOTION(vp)) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SETFNB);
+       } else
+               return;
+
+       /*
+        * If moving backward in the file, delete and yank move to the end
+        * of the range, unless the line didn't change, in which case yank
+        * doesn't move.  If moving forward in the file, delete and yank
+        * stay at the start of the range.  Ignore others.
+        */
+       if (vp->m_stop.lno < vp->m_start.lno ||
+           (vp->m_stop.lno == vp->m_start.lno &&
+           vp->m_stop.cno < vp->m_start.cno)) {
+               if (ISCMD(vp->rkp, 'y') && vp->m_stop.lno == vp->m_start.lno)
+                       vp->m_final = vp->m_start;
+       } else
+               vp->m_final = vp->m_start;
+}
+
+/*
+ * v_up -- [count]^P, [count]k, [count]-
+ *     Move up by lines.
+ *
+ * PUBLIC: int v_up __P((SCR *, VICMD *));
+ */
+int
+v_up(SCR *sp, VICMD *vp)
+{
+       db_recno_t lno;
+
+       lno = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       if (vp->m_start.lno <= lno) {
+               v_sof(sp, &vp->m_start);
+               return (1);
+       }
+       vp->m_stop.lno = vp->m_start.lno - lno;
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_cr -- [count]^M
+ *     In a script window, send the line to the shell.
+ *     In a regular window, move down by lines.
+ *
+ * PUBLIC: int v_cr __P((SCR *, VICMD *));
+ */
+int
+v_cr(SCR *sp, VICMD *vp)
+{
+       /* If it's a colon command-line edit window, it's an ex command. */
+       if (F_ISSET(sp, SC_COMEDIT))
+               return (v_ecl_exec(sp));
+
+       /* If it's a script window, exec the line. */
+       if (F_ISSET(sp, SC_SCRIPT))
+               return (sscr_exec(sp, vp->m_start.lno));
+
+       /* Otherwise, it's the same as v_down(). */
+       return (v_down(sp, vp));
+}
+
+/*
+ * v_down -- [count]^J, [count]^N, [count]j, [count]^M, [count]+
+ *     Move down by lines.
+ *
+ * PUBLIC: int v_down __P((SCR *, VICMD *));
+ */
+int
+v_down(SCR *sp, VICMD *vp)
+{
+       db_recno_t lno;
+
+       lno = vp->m_start.lno + (F_ISSET(vp, VC_C1SET) ? vp->count : 1);
+       if (!db_exist(sp, lno)) {
+               v_eof(sp, &vp->m_start);
+               return (1);
+       }
+       vp->m_stop.lno = lno;
+       vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_hpageup -- [count]^U
+ *     Page up half screens.
+ *
+ * PUBLIC: int v_hpageup __P((SCR *, VICMD *));
+ */
+int
+v_hpageup(SCR *sp, VICMD *vp)
+{
+       /*
+        * Half screens always succeed unless already at SOF.
+        *
+        * !!!
+        * Half screens set the scroll value, even if the command
+        * ultimately failed, in historic vi.  Probably a don't care.
+        */
+       if (F_ISSET(vp, VC_C1SET))
+               sp->defscroll = vp->count;
+       if (vs_sm_scroll(sp, &vp->m_stop, sp->defscroll, CNTRL_U))
+               return (1);
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_hpagedown -- [count]^D
+ *     Page down half screens.
+ *
+ * PUBLIC: int v_hpagedown __P((SCR *, VICMD *));
+ */
+int
+v_hpagedown(SCR *sp, VICMD *vp)
+{
+       /*
+        * Half screens always succeed unless already at EOF.
+        *
+        * !!!
+        * Half screens set the scroll value, even if the command
+        * ultimately failed, in historic vi.  Probably a don't care.
+        */
+       if (F_ISSET(vp, VC_C1SET))
+               sp->defscroll = vp->count;
+       if (vs_sm_scroll(sp, &vp->m_stop, sp->defscroll, CNTRL_D))
+               return (1);
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_pagedown -- [count]^F
+ *     Page down full screens.
+ * !!!
+ * Historic vi did not move to the EOF if the screen couldn't move, i.e.
+ * if EOF was already displayed on the screen.  This implementation does
+ * move to EOF in that case, making ^F more like the the historic ^D.
+ *
+ * PUBLIC: int v_pagedown __P((SCR *, VICMD *));
+ */
+int
+v_pagedown(SCR *sp, VICMD *vp)
+{
+       db_recno_t offset;
+
+       /*
+        * !!!
+        * The calculation in IEEE Std 1003.2-1992 (POSIX) is:
+        *
+        *      top_line = top_line + count * (window - 2);
+        *
+        * which was historically wrong.  The correct one is:
+        *
+        *      top_line = top_line + count * window - 2;
+        *
+        * i.e. the two line "overlap" was only subtracted once.  Which
+        * makes no sense, but then again, an overlap makes no sense for
+        * any screen but the "next" one anyway.  We do it the historical
+        * way as there's no good reason to change it.
+        *
+        * If the screen has been split horizontally, use the smaller of
+        * the current window size and the window option value.
+        *
+        * It possible for this calculation to be less than 1; move at
+        * least one line.
+        */
+       offset = (F_ISSET(vp, VC_C1SET) ? vp->count : 1) * (IS_HSPLIT(sp) ?
+           MIN(sp->t_maxrows, O_VAL(sp, O_WINDOW)) : O_VAL(sp, O_WINDOW));
+       offset = offset <= 2 ? 1 : offset - 2;
+       if (vs_sm_scroll(sp, &vp->m_stop, offset, CNTRL_F))
+               return (1);
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_pageup -- [count]^B
+ *     Page up full screens.
+ *
+ * !!!
+ * Historic vi did not move to the SOF if the screen couldn't move, i.e.
+ * if SOF was already displayed on the screen.  This implementation does
+ * move to SOF in that case, making ^B more like the the historic ^U.
+ *
+ * PUBLIC: int v_pageup __P((SCR *, VICMD *));
+ */
+int
+v_pageup(SCR *sp, VICMD *vp)
+{
+       db_recno_t offset;
+
+       /*
+        * !!!
+        * The calculation in IEEE Std 1003.2-1992 (POSIX) is:
+        *
+        *      top_line = top_line - count * (window - 2);
+        *
+        * which was historically wrong.  The correct one is:
+        *
+        *      top_line = (top_line - count * window) + 2;
+        *
+        * A simpler expression is that, as with ^F, we scroll exactly:
+        *
+        *      count * window - 2
+        *
+        * lines.
+        *
+        * Bizarre.  As with ^F, an overlap makes no sense for anything
+        * but the first screen.  We do it the historical way as there's
+        * no good reason to change it.
+        *
+        * If the screen has been split horizontally, use the smaller of
+        * the current window size and the window option value.
+        *
+        * It possible for this calculation to be less than 1; move at
+        * least one line.
+        */
+       offset = (F_ISSET(vp, VC_C1SET) ? vp->count : 1) * (IS_HSPLIT(sp) ?
+           MIN(sp->t_maxrows, O_VAL(sp, O_WINDOW)) : O_VAL(sp, O_WINDOW));
+       offset = offset <= 2 ? 1 : offset - 2;
+       if (vs_sm_scroll(sp, &vp->m_stop, offset, CNTRL_B))
+               return (1);
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_lineup -- [count]^Y
+ *     Page up by lines.
+ *
+ * PUBLIC: int v_lineup __P((SCR *, VICMD *));
+ */
+int
+v_lineup(SCR *sp, VICMD *vp)
+{
+       /*
+        * The cursor moves down, staying with its original line, unless it
+        * reaches the bottom of the screen.
+        */
+       if (vs_sm_scroll(sp,
+           &vp->m_stop, F_ISSET(vp, VC_C1SET) ? vp->count : 1, CNTRL_Y))
+               return (1);
+       vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_linedown -- [count]^E
+ *     Page down by lines.
+ *
+ * PUBLIC: int v_linedown __P((SCR *, VICMD *));
+ */
+int
+v_linedown(SCR *sp, VICMD *vp)
+{
+       /*
+        * The cursor moves up, staying with its original line, unless it
+        * reaches the top of the screen.
+        */
+       if (vs_sm_scroll(sp,
+           &vp->m_stop, F_ISSET(vp, VC_C1SET) ? vp->count : 1, CNTRL_E))
+               return (1);
+       vp->m_final = vp->m_stop;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_search.c b/dist/nvi/vi/v_search.c
new file mode 100644 (file)
index 0000000..4ded14a
--- /dev/null
@@ -0,0 +1,537 @@
+/*     $NetBSD: v_search.c,v 1.4 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_search.c,v 10.30 2001/09/11 20:52:46 skimo Exp (Berkeley) Date: 2001/09/11 20:52:46";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+#include "../ipc/ip.h"
+
+static int v_exaddr __P((SCR *, VICMD *, dir_t));
+static int v_search __P((SCR *, VICMD *, CHAR_T *, size_t, u_int, dir_t));
+
+/*
+ * v_srch -- [count]?RE[? offset]
+ *     Ex address search backward.
+ *
+ * PUBLIC: int v_searchb __P((SCR *, VICMD *));
+ */
+int
+v_searchb(SCR *sp, VICMD *vp)
+{
+       return (v_exaddr(sp, vp, BACKWARD));
+}
+
+/*
+ * v_searchf -- [count]/RE[/ offset]
+ *     Ex address search forward.
+ *
+ * PUBLIC: int v_searchf __P((SCR *, VICMD *));
+ */
+int
+v_searchf(SCR *sp, VICMD *vp)
+{
+       return (v_exaddr(sp, vp, FORWARD));
+}
+
+/*
+ * v_exaddr --
+ *     Do a vi search (which is really an ex address).
+ */
+static int
+v_exaddr(SCR *sp, VICMD *vp, dir_t dir)
+{
+       static EXCMDLIST fake = { .name = L("search") };
+       EXCMD *cmdp;
+       WIN *wp;
+       TEXT *tp;
+       db_recno_t s_lno;
+       size_t len, s_cno, tlen;
+       int err, nb, type;
+       char buf[20];
+       CHAR_T *cmd, *t;
+       const CHAR_T *w;
+       size_t wlen;
+
+       /*
+        * !!!
+        * If using the search command as a motion, any addressing components
+        * are lost, i.e. y/ptrn/+2, when repeated, is the same as y/ptrn/.
+        */
+       if (F_ISSET(vp, VC_ISDOT))
+               return (v_search(sp, vp,
+                   NULL, 0, SEARCH_PARSE | SEARCH_MSG | SEARCH_SET, dir));
+
+       /* Get the search pattern. */
+       if (v_tcmd(sp, vp, dir == BACKWARD ? CH_BSEARCH : CH_FSEARCH,
+           TXT_BS | TXT_CR | TXT_ESCAPE | TXT_PROMPT |
+           (O_ISSET(sp, O_SEARCHINCR) ? TXT_SEARCHINCR : 0)))
+               return (1);
+
+       tp = sp->tiq.cqh_first;
+
+       /* If the user backspaced over the prompt, do nothing. */
+       if (tp->term == TERM_BS)
+               return (1);
+
+       /*
+        * If the user was doing an incremental search, then we've already
+        * updated the cursor and moved to the right location.  Return the
+        * correct values, we're done.
+        */
+       if (tp->term == TERM_SEARCH) {
+               vp->m_stop.lno = sp->lno;
+               vp->m_stop.cno = sp->cno;
+               if (ISMOTION(vp))
+                       return (v_correct(sp, vp, 0));
+               vp->m_final = vp->m_stop;
+               return (0);
+       }
+
+       /*
+        * If the user entered <escape> or <carriage-return>, the length is
+        * 1 and the right thing will happen, i.e. the prompt will be used
+        * as a command character.
+        *
+        * Build a fake ex command structure.
+        */
+       wp = sp->wp;
+       wp->excmd.cp = tp->lb;
+       wp->excmd.clen = tp->len;
+       F_INIT(&wp->excmd, E_VISEARCH);
+
+       /*
+        * XXX
+        * Warn if the search wraps.  This is a pretty special case, but it's
+        * nice feature that wasn't in the original implementations of ex/vi.
+        * (It was added at some point to System V's version.)  This message
+        * is only displayed if there are no keys in the queue. The problem is
+        * the command is going to succeed, and the message is informational,
+        * not an error.  If a macro displays it repeatedly, e.g., the pattern
+        * only occurs once in the file and wrapscan is set, you lose big.  For
+        * example, if the macro does something like:
+        *
+        *      :map K /pattern/^MjK
+        *
+        * Each search will display the message, but the following "/pattern/"
+        * will immediately overwrite it, with strange results.  The System V
+        * vi displays the "wrapped" message multiple times, but because it's
+        * overwritten each time, it's not as noticeable.  As we don't discard
+        * messages, it's a real problem for us.
+        */
+       if (!KEYS_WAITING(sp))
+               F_SET(&wp->excmd, E_SEARCH_WMSG);
+               
+       /* Save the current line/column. */
+       s_lno = sp->lno;
+       s_cno = sp->cno;
+
+       /*
+        * !!!
+        * Historically, vi / and ? commands were full-blown ex addresses,
+        * including ';' delimiters, trailing <blank>'s, multiple search
+        * strings (separated by semi-colons) and, finally, full-blown z
+        * commands after the / and ? search strings.  (If the search was
+        * being used as a motion, the trailing z command was ignored.
+        * Also, we do some argument checking on the z command, to be sure
+        * that it's not some other random command.) For multiple search
+        * strings, leading <blank>'s at the second and subsequent strings
+        * were eaten as well.  This has some (unintended?) side-effects:
+        * the command /ptrn/;3 is legal and results in moving to line 3.
+        * I suppose you could use it to optionally move to line 3...
+        *
+        * !!!
+        * Historically, if any part of the search command failed, the cursor
+        * remained unmodified (even if ; was used).  We have to play games
+        * because the underlying ex parser thinks we're modifying the cursor
+        * as we go, but I think we're compatible with historic practice.
+        *
+        * !!!
+        * Historically, the command "/STRING/;   " failed, apparently it
+        * confused the parser.  We're not that compatible.
+        */
+       cmdp = &wp->excmd;
+       if (ex_range(sp, cmdp, &err))
+               return (1);
+       
+       /*
+        * Remember where any remaining command information is, and clean
+        * up the fake ex command.
+        */
+       cmd = cmdp->cp;
+       len = cmdp->clen;
+       wp->excmd.clen = 0;
+
+       if (err)
+               goto err2;
+
+       /* Copy out the new cursor position and make sure it's okay. */
+       switch (cmdp->addrcnt) {
+       case 1:
+               vp->m_stop = cmdp->addr1;
+               break;
+       case 2:
+               vp->m_stop = cmdp->addr2;
+               break;
+       }
+       if (!db_exist(sp, vp->m_stop.lno)) {
+               ex_badaddr(sp, &fake,
+                   vp->m_stop.lno == 0 ? A_ZERO : A_EOF, NUM_OK);
+               goto err2;
+       }
+
+       /*
+        * !!!
+        * Historic practice is that a trailing 'z' was ignored if it was a
+        * motion command.  Should probably be an error, but not worth the
+        * effort.
+        */
+       if (ISMOTION(vp))
+               return (v_correct(sp, vp, F_ISSET(cmdp, E_DELTA)));
+               
+       /*
+        * !!!
+        * Historically, if it wasn't a motion command, a delta in the search
+        * pattern turns it into a first nonblank movement.
+        */
+       nb = F_ISSET(cmdp, E_DELTA);
+
+       /* Check for the 'z' command. */
+       if (len != 0) {
+               if (*cmd != 'z')
+                       goto err1;
+
+               /* No blanks, just like the z command. */
+               for (t = cmd + 1, tlen = len - 1; tlen > 0; ++t, --tlen)
+                       if (!ISDIGIT((UCHAR_T)*t))
+                               break;
+               if (tlen &&
+                   (*t == '-' || *t == '.' || *t == '+' || *t == '^')) {
+                       ++t;
+                       --tlen;
+                       type = 1;
+               } else
+                       type = 0;
+               if (tlen)
+                       goto err1;
+
+               /* The z command will do the nonblank for us. */
+               nb = 0;
+
+               /* Default to z+. */
+               if (!type &&
+                   v_event_push(sp, NULL, L("+"), 1, CH_NOMAP | CH_QUOTED))
+                       return (1);
+
+               /* Push the user's command. */
+               if (v_event_push(sp, NULL, cmd, len, CH_NOMAP | CH_QUOTED))
+                       return (1);
+
+               /* Push line number so get correct z display. */
+               tlen = snprintf(buf,
+                   sizeof(buf), "%lu", (u_long)vp->m_stop.lno);
+               CHAR2INT(sp, buf, tlen, w, wlen);
+               if (v_event_push(sp, NULL, w, wlen, CH_NOMAP | CH_QUOTED))
+                       return (1);
+                
+               /* Don't refresh until after 'z' happens. */
+               F_SET(VIP(sp), VIP_S_REFRESH);
+       }
+
+       /* Non-motion commands move to the end of the range. */
+       vp->m_final = vp->m_stop;
+       if (nb) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SETFNB);
+       }
+       return (0);
+
+err1:  msgq(sp, M_ERR,
+           "188|Characters after search string, line offset and/or z command");
+err2:  vp->m_final.lno = s_lno;
+       vp->m_final.cno = s_cno;
+       return (1);
+}
+
+/*
+ * v_searchN -- N
+ *     Reverse last search.
+ *
+ * PUBLIC: int v_searchN __P((SCR *, VICMD *));
+ */
+int
+v_searchN(SCR *sp, VICMD *vp)
+{
+       dir_t dir;
+
+       switch (sp->searchdir) {
+       case BACKWARD:
+               dir = FORWARD;
+               break;
+       case FORWARD:
+               dir = BACKWARD;
+               break;
+       default:
+               dir = sp->searchdir;
+               break;
+       }
+       return (v_search(sp, vp, NULL, 0, SEARCH_PARSE, dir));
+}
+
+/*
+ * v_searchn -- n
+ *     Repeat last search.
+ *
+ * PUBLIC: int v_searchn __P((SCR *, VICMD *));
+ */
+int
+v_searchn(SCR *sp, VICMD *vp)
+{
+       return (v_search(sp, vp, NULL, 0, SEARCH_PARSE, sp->searchdir));
+}
+
+/*
+ * v_searchw -- [count]^A
+ *     Search for the word under the cursor.
+ *
+ * PUBLIC: int v_searchw __P((SCR *, VICMD *));
+ */
+int
+v_searchw(SCR *sp, VICMD *vp)
+{
+       size_t blen, len;
+       size_t olen = STRLEN(VIP(sp)->keyw);
+       int rval;
+       CHAR_T *bp, *p;
+
+       len = olen + RE_WSTART_LEN + RE_WSTOP_LEN;
+       GET_SPACE_RETW(sp, bp, blen, len);
+       MEMCPY(bp, RE_WSTART, RE_WSTART_LEN); 
+       p = bp + RE_WSTART_LEN;
+       MEMCPY(p, VIP(sp)->keyw, olen);
+       p += olen;
+       MEMCPY(p, RE_WSTOP, RE_WSTOP_LEN); 
+
+       rval = v_search(sp, vp, bp, len, SEARCH_SET, FORWARD);
+
+       FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
+
+/*
+ * v_esearch -- <dialog box>
+ *     Search command from the screen.
+ *
+ * PUBLIC: int v_esearch __P((SCR *, VICMD *));
+ */
+int
+v_esearch(SCR *sp, VICMD *vp)
+{
+       MARK m;
+       int flags;
+
+       m.lno = sp->lno;
+       m.cno = sp->cno;
+
+       LF_INIT(SEARCH_NOOPT);
+       if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_EXT))
+               LF_SET(SEARCH_EXTEND);
+       if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_IC))
+               LF_SET(SEARCH_IC);
+       if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_ICL))
+               LF_SET(SEARCH_ICL);
+       if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_INCR))
+               LF_SET(SEARCH_INCR);
+       if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_LIT))
+               LF_SET(SEARCH_LITERAL);
+       if (FL_ISSET(vp->ev.e_flags, VI_SEARCH_WR))
+               LF_SET(SEARCH_WRAP);
+       return (v_search(sp, vp, vp->ev.e_csp, vp->ev.e_len, flags,
+           FL_ISSET(vp->ev.e_flags, VI_SEARCH_REV) ? BACKWARD : FORWARD));
+}
+
+/*
+ * v_search --
+ *     The search commands.
+ */
+static int
+v_search(SCR *sp, VICMD *vp, CHAR_T *ptrn, size_t plen, u_int flags, dir_t dir)
+{
+       /* Display messages. */
+       LF_SET(SEARCH_MSG);
+
+       /* If it's a motion search, offset past end-of-line is okay. */
+       if (ISMOTION(vp))
+               LF_SET(SEARCH_EOL);
+
+       /*
+        * XXX
+        * Warn if the search wraps.  See the comment above, in v_exaddr().
+        */
+       if (!KEYS_WAITING(sp))
+               LF_SET(SEARCH_WMSG);
+               
+       switch (dir) {
+       case BACKWARD:
+               if (b_search(sp,
+                   &vp->m_start, &vp->m_stop, ptrn, plen, NULL, flags))
+                       return (1);
+               break;
+       case FORWARD:
+               if (f_search(sp,
+                   &vp->m_start, &vp->m_stop, ptrn, plen, NULL, flags))
+                       return (1);
+               break;
+       case NOTSET:
+               msgq(sp, M_ERR, "189|No previous search pattern");
+               return (1);
+       default:
+               abort();
+       }
+
+       /* Correct motion commands, otherwise, simply move to the location. */
+       if (ISMOTION(vp)) {
+               if (v_correct(sp, vp, 0))
+                       return(1);
+       } else
+               vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_correct --
+ *     Handle command with a search as the motion.
+ *
+ * !!!
+ * Historically, commands didn't affect the line searched to/from if the
+ * motion command was a search and the final position was the start/end
+ * of the line.  There were some special cases and vi was not consistent;
+ * it was fairly easy to confuse it.  For example, given the two lines:
+ *
+ *     abcdefghi
+ *     ABCDEFGHI
+ *
+ * placing the cursor on the 'A' and doing y?$ would so confuse it that 'h'
+ * 'k' and put would no longer work correctly.  In any case, we try to do
+ * the right thing, but it's not going to exactly match historic practice.
+ *
+ * PUBLIC: int v_correct __P((SCR *, VICMD *, int));
+ */
+int
+v_correct(SCR *sp, VICMD *vp, int isdelta)
+{
+       dir_t dir;
+       MARK m;
+       size_t len;
+
+       /*
+        * !!!
+        * We may have wrapped if wrapscan was set, and we may have returned
+        * to the position where the cursor started.  Historic vi didn't cope
+        * with this well.  Yank wouldn't beep, but the first put after the
+        * yank would move the cursor right one column (without adding any
+        * text) and the second would put a copy of the current line.  The
+        * change and delete commands would beep, but would leave the cursor
+        * on the colon command line.  I believe that there are macros that
+        * depend on delete, at least, failing.  For now, commands that use
+        * search as a motion component fail when the search returns to the
+        * original cursor position.
+        */
+       if (vp->m_start.lno == vp->m_stop.lno &&
+           vp->m_start.cno == vp->m_stop.cno) {
+               msgq(sp, M_BERR, "190|Search wrapped to original position");
+               return (1);
+       }
+
+       /*
+        * !!!
+        * Searches become line mode operations if there was a delta specified
+        * to the search pattern.
+        */
+       if (isdelta)
+               F_SET(vp, VM_LMODE);
+
+       /*
+        * If the motion is in the reverse direction, switch the start and
+        * stop MARK's so that it's in a forward direction.  (There's no
+        * reason for this other than to make the tests below easier.  The
+        * code in vi.c:vi() would have done the switch.)  Both forward
+        * and backward motions can happen for any kind of search command
+        * because of the wrapscan option.
+        */
+       if (vp->m_start.lno > vp->m_stop.lno ||
+           (vp->m_start.lno == vp->m_stop.lno &&
+           vp->m_start.cno > vp->m_stop.cno)) {
+               m = vp->m_start;
+               vp->m_start = vp->m_stop;
+               vp->m_stop = m;
+               dir = BACKWARD;
+       } else
+               dir = FORWARD;
+
+       /*
+        * BACKWARD:
+        *      Delete and yank commands move to the end of the range.
+        *      Ignore others.
+        *
+        * FORWARD:
+        *      Delete and yank commands don't move.  Ignore others.
+        */
+       vp->m_final = vp->m_start;
+
+       /*
+        * !!!
+        * Delta'd searches don't correct based on column positions.
+        */
+       if (isdelta)
+               return (0);
+
+       /*
+        * !!!
+        * Backward searches starting at column 0, and forward searches ending
+        * at column 0 are corrected to the last column of the previous line.
+        * Otherwise, adjust the starting/ending point to the character before
+        * the current one (this is safe because we know the search had to move
+        * to succeed).
+        *
+        * Searches become line mode operations if they start at the first
+        * nonblank and end at column 0 of another line.
+        */
+       if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
+               if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+                       return (1);
+               vp->m_stop.cno = len ? len - 1 : 0;
+               len = 0;
+               if (nonblank(sp, vp->m_start.lno, &len))
+                       return (1);
+               if (vp->m_start.cno <= len)
+                       F_SET(vp, VM_LMODE);
+       } else
+               --vp->m_stop.cno;
+
+       return (0);
+}
diff --git a/dist/nvi/vi/v_section.c b/dist/nvi/vi/v_section.c
new file mode 100644 (file)
index 0000000..03cc382
--- /dev/null
@@ -0,0 +1,253 @@
+/*     $NetBSD: v_section.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_section.c,v 10.10 2001/06/25 15:19:35 skimo Exp (Berkeley) Date: 2001/06/25 15:19:35";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * !!!
+ * In historic vi, the section commands ignored empty lines, unlike the
+ * paragraph commands, which was probably okay.  However, they also moved
+ * to the start of the last line when there where no more sections instead
+ * of the end of the last line like the paragraph commands.  I've changed
+ * the latter behavior to match the paragraph commands.
+ *
+ * In historic vi, a section was defined as the first character(s) of the
+ * line matching, which could be followed by anything.  This implementation
+ * follows that historic practice.
+ *
+ * !!!
+ * The historic vi documentation (USD:15-10) claimed:
+ *     The section commands interpret a preceding count as a different
+ *     window size in which to redraw the screen at the new location,
+ *     and this window size is the base size for newly drawn windows
+ *     until another size is specified.  This is very useful if you are
+ *     on a slow terminal ...
+ *
+ * I can't get the 4BSD vi to do this, it just beeps at me.  For now, a
+ * count to the section commands simply repeats the command.
+ */
+
+/*
+ * v_sectionf -- [count]]]
+ *     Move forward count sections/functions.
+ *
+ * !!!
+ * Using ]] as a motion command was a bit special, historically.  It could
+ * match } as well as the usual { and section values.  If it matched a { or
+ * a section, it did NOT include the matched line.  If it matched a }, it
+ * did include the line.  No clue why.
+ *
+ * PUBLIC: int v_sectionf __P((SCR *, VICMD *));
+ */
+int
+v_sectionf(SCR *sp, VICMD *vp)
+{
+       db_recno_t cnt, lno;
+       size_t len;
+       CHAR_T *p;
+       const char *list, *lp;
+
+       /* Get the macro list. */
+       if ((list = O_STR(sp, O_SECTIONS)) == NULL)
+               return (1);
+
+       /*
+        * !!!
+        * If the starting cursor position is at or before any non-blank
+        * characters in the line, i.e. the movement is cutting all of the
+        * line's text, the buffer is in line mode.  It's a lot easier to
+        * check here, because we know that the end is going to be the start
+        * or end of a line.
+        */
+       if (ISMOTION(vp)) {
+               if (vp->m_start.cno == 0)
+                       F_SET(vp, VM_LMODE);
+               else {
+                       vp->m_stop = vp->m_start;
+                       vp->m_stop.cno = 0;
+                       if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+                               return (1);
+                       if (vp->m_start.cno <= vp->m_stop.cno)
+                               F_SET(vp, VM_LMODE);
+               }
+       }
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       for (lno = vp->m_start.lno; !db_get(sp, ++lno, 0, &p, &len);) {
+               if (len == 0)
+                       continue;
+               if (p[0] == '{' || (ISMOTION(vp) && p[0] == '}')) {
+                       if (!--cnt) {
+                               if (p[0] == '{')
+                                       goto adjust1;
+                               goto adjust2;
+                       }
+                       continue;
+               }
+               /*
+                * !!!
+                * Historic documentation (USD:15-11, 4.2) said that formfeed
+                * characters (^L) in the first column delimited sections.
+                * The historic code mentions formfeed characters, but never
+                * implements them.  Seems reasonable, do it.
+                */
+               if (p[0] == '\014') {
+                       if (!--cnt)
+                               goto adjust1;
+                       continue;
+               }
+               if (p[0] != '.' || len < 2)
+                       continue;
+               for (lp = list; *lp != '\0'; lp += 2 * sizeof(*lp))
+                       if (lp[0] == p[1] &&
+                           ((lp[1] == ' ' && len == 2) || lp[1] == p[2]) &&
+                           !--cnt) {
+                               /*
+                                * !!!
+                                * If not cutting this line, adjust to the end
+                                * of the previous one.  Otherwise, position to
+                                * column 0.
+                                */
+adjust1:                       if (ISMOTION(vp))
+                                       goto ret1;
+
+adjust2:                       vp->m_stop.lno = lno;
+                               vp->m_stop.cno = 0;
+                               goto ret2;
+                       }
+       }
+
+       /* If moving forward, reached EOF, check to see if we started there. */
+       if (vp->m_start.lno == lno - 1) {
+               v_eof(sp, NULL);
+               return (1);
+       }
+
+ret1:  if (db_get(sp, --lno, DBG_FATAL, NULL, &len))
+               return (1);
+       vp->m_stop.lno = lno;
+       vp->m_stop.cno = len ? len - 1 : 0;
+
+       /*
+        * Non-motion commands go to the end of the range.  Delete and
+        * yank stay at the start of the range.  Ignore others.
+        */
+ret2:  if (ISMOTION(vp)) {
+               vp->m_final = vp->m_start;
+               if (F_ISSET(vp, VM_LMODE))
+                       vp->m_final.cno = 0;
+       } else
+               vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_sectionb -- [count][[
+ *     Move backward count sections/functions.
+ *
+ * PUBLIC: int v_sectionb __P((SCR *, VICMD *));
+ */
+int
+v_sectionb(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       db_recno_t cnt, lno;
+       CHAR_T *p;
+       const char *list, *lp;
+
+       /* An empty file or starting from line 1 is always illegal. */
+       if (vp->m_start.lno <= 1) {
+               v_sof(sp, NULL);
+               return (1);
+       }
+
+       /* Get the macro list. */
+       if ((list = O_STR(sp, O_SECTIONS)) == NULL)
+               return (1);
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       for (lno = vp->m_start.lno; !db_get(sp, --lno, 0, &p, &len);) {
+               if (len == 0)
+                       continue;
+               if (p[0] == '{') {
+                       if (!--cnt)
+                               goto adjust1;
+                       continue;
+               }
+               /*
+                * !!!
+                * Historic documentation (USD:15-11, 4.2) said that formfeed
+                * characters (^L) in the first column delimited sections.
+                * The historic code mentions formfeed characters, but never
+                * implements them.  Seems reasonable, do it.
+                */
+               if (p[0] == '\014') {
+                       if (!--cnt)
+                               goto adjust1;
+                       continue;
+               }
+               if (p[0] != '.' || len < 2)
+                       continue;
+               for (lp = list; *lp != '\0'; lp += 2 * sizeof(*lp))
+                       if (lp[0] == p[1] &&
+                           ((lp[1] == ' ' && len == 2) || lp[1] == p[2]) &&
+                           !--cnt) {
+adjust1:                       vp->m_stop.lno = lno;
+                               vp->m_stop.cno = 0;
+                               goto ret1;
+                       }
+       }
+
+       /*
+        * If moving backward, reached SOF, which is a movement sink.
+        * We already checked for starting there.
+        */
+       vp->m_stop.lno = 1;
+       vp->m_stop.cno = 0;
+
+       /*
+        * All commands move to the end of the range.
+        *
+        * !!!
+        * Historic practice is the section cut was in line mode if it started
+        * from column 0 and was in the backward direction.  Otherwise, left
+        * motion commands adjust the starting point to the character before
+        * the current one.  What makes this worse is that if it cut to line
+        * mode it also went to the first non-<blank>.
+        */
+ret1:  if (vp->m_start.cno == 0) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SETFNB);
+
+               --vp->m_start.lno;
+               F_SET(vp, VM_LMODE);
+       } else
+               --vp->m_start.cno;
+
+       vp->m_final = vp->m_stop;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_sentence.c b/dist/nvi/vi/v_sentence.c
new file mode 100644 (file)
index 0000000..9ee151d
--- /dev/null
@@ -0,0 +1,358 @@
+/*     $NetBSD: v_sentence.c,v 1.3 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_sentence.c,v 10.9 2001/06/25 15:19:35 skimo Exp (Berkeley) Date: 2001/06/25 15:19:35";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * !!!
+ * In historic vi, a sentence was delimited by a '.', '?' or '!' character
+ * followed by TWO spaces or a newline.  One or more empty lines was also
+ * treated as a separate sentence.  The Berkeley documentation for historical
+ * vi states that any number of ')', ']', '"' and '\'' characters can be
+ * between the delimiter character and the spaces or end of line, however,
+ * the historical implementation did not handle additional '"' characters.
+ * We follow the documentation here, not the implementation.
+ *
+ * Once again, historical vi didn't do sentence movements associated with
+ * counts consistently, mostly in the presence of lines containing only
+ * white-space characters.
+ *
+ * This implementation also permits a single tab to delimit sentences, and
+ * treats lines containing only white-space characters as empty lines.
+ * Finally, tabs are eaten (along with spaces) when skipping to the start
+ * of the text following a "sentence".
+ */
+
+/*
+ * v_sentencef -- [count])
+ *     Move forward count sentences.
+ *
+ * PUBLIC: int v_sentencef __P((SCR *, VICMD *));
+ */
+int
+v_sentencef(SCR *sp, VICMD *vp)
+{
+       enum { BLANK, NONE, PERIOD } state;
+       VCS cs;
+       size_t len;
+       u_long cnt;
+
+       cs.cs_lno = vp->m_start.lno;
+       cs.cs_cno = vp->m_start.cno;
+       if (cs_init(sp, &cs))
+               return (1);
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+
+       /*
+        * !!!
+        * If in white-space, the next start of sentence counts as one.
+        * This may not handle "  .  " correctly, but it's real unclear
+        * what correctly means in that case.
+        */
+       if (cs.cs_flags == CS_EMP || (cs.cs_flags == 0 && ISBLANK2(cs.cs_ch))) {
+               if (cs_fblank(sp, &cs))
+                       return (1);
+               if (--cnt == 0) {
+                       if (vp->m_start.lno != cs.cs_lno ||
+                           vp->m_start.cno != cs.cs_cno)
+                               goto okret;
+                       return (1);
+               }
+       }
+
+       for (state = NONE;;) {
+               if (cs_next(sp, &cs))
+                       return (1);
+               if (cs.cs_flags == CS_EOF)
+                       break;
+               if (cs.cs_flags == CS_EOL) {
+                       if ((state == PERIOD || state == BLANK) && --cnt == 0) {
+                               if (cs_next(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == 0 &&
+                                   ISBLANK2(cs.cs_ch) && cs_fblank(sp, &cs))
+                                       return (1);
+                               goto okret;
+                       }
+                       state = NONE;
+                       continue;
+               }
+               if (cs.cs_flags == CS_EMP) {    /* An EMP is two sentences. */
+                       if (--cnt == 0)
+                               goto okret;
+                       if (cs_fblank(sp, &cs))
+                               return (1);
+                       if (--cnt == 0)
+                               goto okret;
+                       state = NONE;
+                       continue;
+               }
+               switch (cs.cs_ch) {
+               case '.':
+               case '?':
+               case '!':
+                       state = PERIOD;
+                       break;
+               case ')':
+               case ']':
+               case '"':
+               case '\'':
+                       if (state != PERIOD)
+                               state = NONE;
+                       break;
+               case '\t':
+                       if (state == PERIOD)
+                               state = BLANK;
+                       /* FALLTHROUGH */
+               case ' ':
+                       if (state == PERIOD) {
+                               state = BLANK;
+                               break;
+                       }
+                       if (state == BLANK && --cnt == 0) {
+                               if (cs_fblank(sp, &cs))
+                                       return (1);
+                               goto okret;
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       state = NONE;
+                       break;
+               }
+       }
+
+       /* EOF is a movement sink, but it's an error not to have moved. */
+       if (vp->m_start.lno == cs.cs_lno && vp->m_start.cno == cs.cs_cno) {
+               v_eof(sp, NULL);
+               return (1);
+       }
+
+okret: vp->m_stop.lno = cs.cs_lno;
+       vp->m_stop.cno = cs.cs_cno;
+
+       /*
+        * !!!
+        * Historic, uh, features, yeah, that's right, call 'em features.
+        * If the starting and ending cursor positions are at the first
+        * column in their lines, i.e. the movement is cutting entire lines,
+        * the buffer is in line mode, and the ending position is the last
+        * character of the previous line.  Note check to make sure that
+        * it's not within a single line.
+        *
+        * Non-motion commands move to the end of the range.  Delete and
+        * yank stay at the start.  Ignore others.  Adjust the end of the
+        * range for motion commands.
+        */
+       if (ISMOTION(vp)) {
+               if (vp->m_start.cno == 0 &&
+                   (cs.cs_flags != 0 || vp->m_stop.cno == 0)) {
+                       if (vp->m_start.lno < vp->m_stop.lno) {
+                               if (db_get(sp,
+                                   --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+                                       return (1);
+                               vp->m_stop.cno = len ? len - 1 : 0;
+                       }
+                       F_SET(vp, VM_LMODE);
+               } else
+                       --vp->m_stop.cno;
+               vp->m_final = vp->m_start;
+       } else
+               vp->m_final = vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_sentenceb -- [count](
+ *     Move backward count sentences.
+ *
+ * PUBLIC: int v_sentenceb __P((SCR *, VICMD *));
+ */
+int
+v_sentenceb(SCR *sp, VICMD *vp)
+{
+       VCS cs;
+       db_recno_t slno;
+       size_t len, scno;
+       u_long cnt;
+       int last;
+
+       /*
+        * !!!
+        * Historic vi permitted the user to hit SOF repeatedly.
+        */
+       if (vp->m_start.lno == 1 && vp->m_start.cno == 0)
+               return (0);
+
+       cs.cs_lno = vp->m_start.lno;
+       cs.cs_cno = vp->m_start.cno;
+       if (cs_init(sp, &cs))
+               return (1);
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+
+       /*
+        * !!!
+        * In empty lines, skip to the previous non-white-space character.
+        * If in text, skip to the prevous white-space character.  Believe
+        * it or not, in the paragraph:
+        *      ab cd.
+        *      AB CD.
+        * if the cursor is on the 'A' or 'B', ( moves to the 'a'.  If it
+        * is on the ' ', 'C' or 'D', it moves to the 'A'.  Yes, Virginia,
+        * Berkeley was once a major center of drug activity.
+        */
+       if (cs.cs_flags == CS_EMP) {
+               if (cs_bblank(sp, &cs))
+                       return (1);
+               for (;;) {
+                       if (cs_prev(sp, &cs))
+                               return (1);
+                       if (cs.cs_flags != CS_EOL)
+                               break;
+               }
+       } else if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch))
+               for (;;) {
+                       if (cs_prev(sp, &cs))
+                               return (1);
+                       if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                               break;
+               }
+
+       for (last = 0;;) {
+               if (cs_prev(sp, &cs))
+                       return (1);
+               if (cs.cs_flags == CS_SOF)      /* SOF is a movement sink. */
+                       break;
+               if (cs.cs_flags == CS_EOL) {
+                       last = 1;
+                       continue;
+               }
+               if (cs.cs_flags == CS_EMP) {
+                       if (--cnt == 0)
+                               goto ret;
+                       if (cs_bblank(sp, &cs))
+                               return (1);
+                       last = 0;
+                       continue;
+               }
+               switch (cs.cs_ch) {
+               case '.':
+               case '?':
+               case '!':
+                       if (!last || --cnt != 0) {
+                               last = 0;
+                               continue;
+                       }
+
+ret:                   slno = cs.cs_lno;
+                       scno = cs.cs_cno;
+
+                       /*
+                        * Move to the start of the sentence, skipping blanks
+                        * and special characters.
+                        */
+                       do {
+                               if (cs_next(sp, &cs))
+                                       return (1);
+                       } while (!cs.cs_flags &&
+                           (cs.cs_ch == ')' || cs.cs_ch == ']' ||
+                           cs.cs_ch == '"' || cs.cs_ch == '\''));
+                       if ((cs.cs_flags || ISBLANK2(cs.cs_ch)) &&
+                           cs_fblank(sp, &cs))
+                               return (1);
+
+                       /*
+                        * If it was ".  xyz", with the cursor on the 'x', or
+                        * "end.  ", with the cursor in the spaces, or the
+                        * beginning of a sentence preceded by an empty line,
+                        * we can end up where we started.  Fix it.
+                        */
+                       if (vp->m_start.lno != cs.cs_lno ||
+                           vp->m_start.cno != cs.cs_cno)
+                               goto okret;
+
+                       /*
+                        * Well, if an empty line preceded possible blanks
+                        * and the sentence, it could be a real sentence.
+                        */
+                       for (;;) {
+                               if (cs_prev(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_EOL)
+                                       continue;
+                               if (cs.cs_flags == 0 && ISBLANK2(cs.cs_ch))
+                                       continue;
+                               break;
+                       }
+                       if (cs.cs_flags == CS_EMP)
+                               goto okret;
+
+                       /* But it wasn't; try again. */
+                       ++cnt;
+                       cs.cs_lno = slno;
+                       cs.cs_cno = scno;
+                       last = 0;
+                       break;
+               case '\t':
+                       last = 1;
+                       break;
+               default:
+                       last =
+                           cs.cs_flags == CS_EOL || ISBLANK2(cs.cs_ch) ||
+                           cs.cs_ch == ')' || cs.cs_ch == ']' ||
+                           cs.cs_ch == '"' || cs.cs_ch == '\'' ? 1 : 0;
+               }
+       }
+
+okret: vp->m_stop.lno = cs.cs_lno;
+       vp->m_stop.cno = cs.cs_cno;
+
+       /*
+        * !!!
+        * If the starting and stopping cursor positions are at the first
+        * columns in the line, i.e. the movement is cutting an entire line,
+        * the buffer is in line mode, and the starting position is the last
+        * character of the previous line.
+        *
+        * All commands move to the end of the range.  Adjust the start of
+        * the range for motion commands.
+        */
+       if (ISMOTION(vp)) {
+               if (vp->m_start.cno == 0 &&
+                   (cs.cs_flags != 0 || vp->m_stop.cno == 0)) {
+                       if (db_get(sp,
+                           --vp->m_start.lno, DBG_FATAL, NULL, &len))
+                               return (1);
+                       vp->m_start.cno = len ? len - 1 : 0;
+                       F_SET(vp, VM_LMODE);
+               } else
+                       --vp->m_start.cno;
+       }
+       vp->m_final = vp->m_stop;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_status.c b/dist/nvi/vi/v_status.c
new file mode 100644 (file)
index 0000000..7a7850f
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: v_status.c,v 1.1.1.2 2008/05/18 14:31:47 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_status.c,v 10.10 2001/06/25 15:19:35 skimo Exp (Berkeley) Date: 2001/06/25 15:19:35";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_status -- ^G
+ *     Show the file status.
+ *
+ * PUBLIC: int v_status __P((SCR *, VICMD *));
+ */
+int
+v_status(SCR *sp, VICMD *vp)
+{
+       (void)msgq_status(sp, vp->m_start.lno, MSTAT_SHOWLAST);
+       return (0);
+}
diff --git a/dist/nvi/vi/v_txt.c b/dist/nvi/vi/v_txt.c
new file mode 100644 (file)
index 0000000..3a25e8c
--- /dev/null
@@ -0,0 +1,2916 @@
+/*     $NetBSD: v_txt.c,v 1.8 2011/11/23 19:25:28 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_txt.c,v 10.108 2003/07/18 21:27:42 skimo Exp (Berkeley) Date: 2003/07/18 21:27:42";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int      txt_abbrev __P((SCR *, TEXT *, ARG_CHAR_T *, int, int *, int *));
+static void     txt_ai_resolve __P((SCR *, TEXT *, int *));
+static TEXT    *txt_backup __P((SCR *, TEXTH *, TEXT *, u_int32_t *));
+static int      txt_dent __P((SCR *, TEXT *, int));
+static int      txt_emark __P((SCR *, TEXT *, size_t));
+static void     txt_err __P((SCR *, TEXTH *));
+static int      txt_fc __P((SCR *, TEXT *, int *));
+static int      txt_fc_col __P((SCR *, int, ARGS **));
+static int      txt_hex __P((SCR *, TEXT *));
+static int      txt_insch __P((SCR *, TEXT *, ARG_CHAR_T *, u_int));
+static int      txt_isrch __P((SCR *, VICMD *, TEXT *, u_int8_t *));
+static int      txt_map_end __P((SCR *));
+static int      txt_map_init __P((SCR *));
+static int      txt_margin __P((SCR *, TEXT *, TEXT *, int *, u_int32_t));
+static void     txt_nomorech __P((SCR *));
+static void     txt_Rresolve __P((SCR *, TEXTH *, TEXT *, const size_t));
+static int      txt_resolve __P((SCR *, TEXTH *, u_int32_t));
+static int      txt_showmatch __P((SCR *, TEXT *));
+static void     txt_unmap __P((SCR *, TEXT *, u_int32_t *));
+
+/* Cursor character (space is hard to track on the screen). */
+#if defined(DEBUG) && 0
+#undef CH_CURSOR
+#define        CH_CURSOR       '+'
+#endif
+
+/*
+ * v_tcmd --
+ *     Fill a buffer from the terminal for vi.
+ *
+ * PUBLIC: int v_tcmd __P((SCR *, VICMD *, ARG_CHAR_T, u_int));
+ */
+int
+v_tcmd(SCR *sp, VICMD *vp, ARG_CHAR_T prompt, u_int flags)
+{
+       /* Normally, we end up where we started. */
+       vp->m_final.lno = sp->lno;
+       vp->m_final.cno = sp->cno;
+
+       /* Initialize the map. */
+       if (txt_map_init(sp))
+               return (1);
+
+       /* Move to the last line. */
+       sp->lno = TMAP[0].lno;
+       sp->cno = 0;
+
+       /* Don't update the modeline for now. */
+       F_SET(sp, SC_TINPUT_INFO);
+
+       /* Set the input flags. */
+       LF_SET(TXT_APPENDEOL |
+           TXT_CR | TXT_ESCAPE | TXT_INFOLINE | TXT_MAPINPUT);
+       if (O_ISSET(sp, O_ALTWERASE))
+               LF_SET(TXT_ALTWERASE);
+       if (O_ISSET(sp, O_TTYWERASE))
+               LF_SET(TXT_TTYWERASE);
+
+       /* Do the input thing. */
+       if (v_txt(sp, vp, NULL, NULL, 0, prompt, 0, 1, flags))
+               return (1);
+
+       /* Reenable the modeline updates. */
+       F_CLR(sp, SC_TINPUT_INFO);
+
+       /* Clean up the map. */
+       if (txt_map_end(sp))
+               return (1);
+
+       if (IS_ONELINE(sp))
+               F_SET(sp, SC_SCR_REDRAW);       /* XXX */
+
+       /* Set the cursor to the resulting position. */
+       sp->lno = vp->m_final.lno;
+       sp->cno = vp->m_final.cno;
+
+       return (0);
+}
+
+/*
+ * txt_map_init
+ *     Initialize the screen map for colon command-line input.
+ */
+static int
+txt_map_init(SCR *sp)
+{
+       SMAP *esmp;
+       VI_PRIVATE *vip;
+
+       vip = VIP(sp);
+       if (!IS_ONELINE(sp)) {
+               /*
+                * Fake like the user is doing input on the last line of the
+                * screen.  This makes all of the scrolling work correctly,
+                * and allows us the use of the vi text editing routines, not
+                * to mention practically infinite length ex commands.
+                *
+                * Save the current location.
+                */
+               vip->sv_tm_lno = TMAP->lno;
+               vip->sv_tm_soff = TMAP->soff;
+               vip->sv_tm_coff = TMAP->coff;
+               vip->sv_t_maxrows = sp->t_maxrows;
+               vip->sv_t_minrows = sp->t_minrows;
+               vip->sv_t_rows = sp->t_rows;
+
+               /*
+                * If it's a small screen, TMAP may be small for the screen.
+                * Fix it, filling in fake lines as we go.
+                */
+               if (IS_SMALL(sp))
+                       for (esmp =
+                           HMAP + (sp->t_maxrows - 1); TMAP < esmp; ++TMAP) {
+                               TMAP[1].lno = TMAP[0].lno + 1;
+                               TMAP[1].coff = HMAP->coff;
+                               TMAP[1].soff = 1;
+                       }
+
+               /* Build the fake entry. */
+               TMAP[1].lno = TMAP[0].lno + 1;
+               TMAP[1].soff = 1;
+               TMAP[1].coff = 0;
+               SMAP_FLUSH(&TMAP[1]);
+               ++TMAP;
+
+               /* Reset the screen information. */
+               sp->t_rows = sp->t_minrows = ++sp->t_maxrows;
+       }
+       return (0);
+}
+
+/*
+ * txt_map_end
+ *     Reset the screen map for colon command-line input.
+ */
+static int
+txt_map_end(SCR *sp)
+{
+       VI_PRIVATE *vip;
+       size_t cnt;
+
+       vip = VIP(sp);
+       if (!IS_ONELINE(sp)) {
+               /* Restore the screen information. */
+               sp->t_rows = vip->sv_t_rows;
+               sp->t_minrows = vip->sv_t_minrows;
+               sp->t_maxrows = vip->sv_t_maxrows;
+
+               /*
+                * If it's a small screen, TMAP may be wrong.  Clear any
+                * lines that might have been overwritten.
+                */
+               if (IS_SMALL(sp)) {
+                       for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
+                               (void)sp->gp->scr_move(sp, cnt, 0);
+                               (void)sp->gp->scr_clrtoeol(sp);
+                       }
+                       TMAP = HMAP + (sp->t_rows - 1);
+               } else
+                       --TMAP;
+
+               /*
+                * The map may be wrong if the user entered more than one
+                * (logical) line.  Fix it.  If the user entered a whole
+                * screen, this will be slow, but we probably don't care.
+                */
+               if (!O_ISSET(sp, O_LEFTRIGHT))
+                       while (vip->sv_tm_lno != TMAP->lno ||
+                           vip->sv_tm_soff != TMAP->soff)
+                               if (vs_sm_1down(sp))
+                                       return (1);
+       }
+
+       /*
+        * Invalidate the cursor and the line size cache, the line never
+        * really existed.  This fixes bugs where the user searches for
+        * the last line on the screen + 1 and the refresh routine thinks
+        * that's where we just were.
+        */
+       VI_SCR_CFLUSH(vip);
+       F_SET(vip, VIP_CUR_INVALID);
+
+       return (0);
+}
+
+/*
+ * If doing input mapping on the colon command line, may need to unmap
+ * based on the command.
+ */
+#define        UNMAP_TST                                                       \
+       FL_ISSET(ec_flags, EC_MAPINPUT) && LF_ISSET(TXT_INFOLINE)
+
+/* 
+ * Internally, we maintain tp->lno and tp->cno, externally, everyone uses
+ * sp->lno and sp->cno.  Make them consistent as necessary.
+ */
+#define        UPDATE_POSITION(sp, tp) {                                       \
+       (sp)->lno = (tp)->lno;                                          \
+       (sp)->cno = (tp)->cno;                                          \
+}
+
+/*
+ * v_txt --
+ *     Vi text input.
+ *
+ * PUBLIC: int v_txt __P((SCR *, VICMD *, MARK *,
+ * PUBLIC:    const CHAR_T *, size_t, ARG_CHAR_T, db_recno_t, u_long, u_int32_t));
+ */
+int
+v_txt(SCR *sp, VICMD *vp, MARK *tm, const CHAR_T *lp, size_t len, ARG_CHAR_T prompt, db_recno_t ai_line, u_long rcount, u_int32_t flags)
+               
+                 
+                               /* To MARK. */
+                               /* Input line. */
+                               /* Input line length. */
+                               /* Prompt to display. */
+                               /* Line number to use for autoindent count. */
+                               /* Replay count. */
+                               /* TXT_* flags. */
+{
+       EVENT ev, *evp = NULL;  /* Current event. */
+       EVENT fc;               /* File name completion event. */
+       GS *gp;
+       TEXT *ntp, *tp;         /* Input text structures. */
+       TEXT ait;               /* Autoindent text structure. */
+       TEXT wmt;               /* Wrapmargin text structure. */
+       TEXTH *tiqh;
+       VI_PRIVATE *vip;
+       abb_t abb;              /* State of abbreviation checks. */
+       carat_t carat;          /* State of the "[^0]^D" sequences. */
+       quote_t quote;          /* State of quotation. */
+       size_t owrite, insert;  /* Temporary copies of TEXT fields. */
+       size_t margin;          /* Wrapmargin value. */
+       size_t rcol;            /* 0-N: insert offset in the replay buffer. */
+       size_t tcol;            /* Temporary column. */
+       u_int32_t ec_flags;     /* Input mapping flags. */
+#define        IS_RESTART      0x01    /* Reset the incremental search. */
+#define        IS_RUNNING      0x02    /* Incremental search turned on. */
+       u_int8_t is_flags;
+       int abcnt, ab_turnoff;  /* Abbreviation character count, switch. */
+       int filec_redraw;       /* Redraw after the file completion routine. */
+       int hexcnt;             /* Hex character count. */
+       int showmatch;          /* Showmatch set on this character. */
+       int wm_set, wm_skip;    /* Wrapmargin happened, blank skip flags. */
+       size_t max;
+       int tmp;
+       CHAR_T *p;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+       memset(&wmt, 0, sizeof(wmt));
+
+       /*
+        * Set the input flag, so tabs get displayed correctly
+        * and everyone knows that the text buffer is in use.
+        */
+       F_SET(sp, SC_TINPUT);
+
+       /*
+        * Get one TEXT structure with some initial buffer space, reusing
+        * the last one if it's big enough.  (All TEXT bookkeeping fields
+        * default to 0 -- text_init() handles this.)  If changing a line,
+        * copy it into the TEXT buffer.
+        */
+       tiqh = &sp->tiq;
+       if (tiqh->cqh_first != (void *)tiqh) {
+               tp = tiqh->cqh_first;
+               if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < len + 32) {
+                       text_lfree(tiqh);
+                       goto newtp;
+               }
+               tp->ai = tp->insert = tp->offset = tp->owrite = 0;
+               if (lp != NULL) {
+                       tp->len = len;
+                       BINC_RETW(sp, tp->lb, tp->lb_len, len);
+                       MEMMOVEW(tp->lb, lp, len);
+               } else
+                       tp->len = 0;
+       } else {
+newtp:         if ((tp = text_init(sp, lp, len, len + 32)) == NULL)
+                       return (1);
+               CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
+       }
+
+       /* Set default termination condition. */
+       tp->term = TERM_OK;
+
+       /* Set the starting line, column. */
+       tp->lno = sp->lno;
+       tp->cno = sp->cno;
+
+       /*
+        * Set the insert and overwrite counts.  If overwriting characters,
+        * do insertion afterward.  If not overwriting characters, assume
+        * doing insertion.  If change is to a mark, emphasize it with an
+        * CH_ENDMARK character.
+        */
+       if (len) {
+               if (LF_ISSET(TXT_OVERWRITE)) {
+                       tp->owrite = (tm->cno - tp->cno) + 1;
+                       tp->insert = (len - tm->cno) - 1;
+               } else
+                       tp->insert = len - tp->cno;
+
+               if (LF_ISSET(TXT_EMARK) && txt_emark(sp, tp, tm->cno))
+                       return (1);
+       }
+
+       /*
+        * Many of the special cases in text input are to handle autoindent
+        * support.  Somebody decided that it would be a good idea if "^^D"
+        * and "0^D" deleted all of the autoindented characters.  In an editor
+        * that takes single character input from the user, this beggars the
+        * imagination.  Note also, "^^D" resets the next lines' autoindent,
+        * but "0^D" doesn't.
+        *
+        * We assume that autoindent only happens on empty lines, so insert
+        * and overwrite will be zero.  If doing autoindent, figure out how
+        * much indentation we need and fill it in.  Update input column and
+        * screen cursor as necessary.
+        */
+       if (LF_ISSET(TXT_AUTOINDENT) && ai_line != OOBLNO) {
+               if (v_txt_auto(sp, ai_line, NULL, 0, tp))
+                       return (1);
+               tp->cno = tp->ai;
+       } else {
+               /*
+                * The cc and S commands have a special feature -- leading
+                * <blank> characters are handled as autoindent characters.
+                * Beauty!
+                */
+               if (LF_ISSET(TXT_AICHARS)) {
+                       tp->offset = 0;
+                       tp->ai = tp->cno;
+               } else
+                       tp->offset = tp->cno;
+       }
+
+       /* If getting a command buffer from the user, there may be a prompt. */
+       if (LF_ISSET(TXT_PROMPT)) {
+               tp->lb[tp->cno++] = prompt;
+               ++tp->len;
+               ++tp->offset;
+       }
+
+       /*
+        * If appending after the end-of-line, add a space into the buffer
+        * and move the cursor right.  This space is inserted, i.e. pushed
+        * along, and then deleted when the line is resolved.  Assumes that
+        * the cursor is already positioned at the end of the line.  This
+        * avoids the nastiness of having the cursor reside on a magical
+        * column, i.e. a column that doesn't really exist.  The only down
+        * side is that we may wrap lines or scroll the screen before it's
+        * strictly necessary.  Not a big deal.
+        */
+       if (LF_ISSET(TXT_APPENDEOL)) {
+               tp->lb[tp->cno] = CH_CURSOR;
+               ++tp->len;
+               ++tp->insert;
+               (void)vs_change(sp, tp->lno, LINE_RESET);
+       }
+
+       /*
+        * Historic practice is that the wrapmargin value was a distance
+        * from the RIGHT-HAND margin, not the left.  It's more useful to
+        * us as a distance from the left-hand margin, i.e. the same as
+        * the wraplen value.  The wrapmargin option is historic practice.
+        * Nvi added the wraplen option so that it would be possible to
+        * edit files with consistent margins without knowing the number of
+        * columns in the window.
+        *
+        * XXX
+        * Setting margin causes a significant performance hit.  Normally
+        * we don't update the screen if there are keys waiting, but we
+        * have to if margin is set, otherwise the screen routines don't
+        * know where the cursor is.
+        *
+        * !!!
+        * Abbreviated keys were affected by the wrapmargin option in the
+        * historic 4BSD vi.  Mapped keys were usually, but sometimes not.
+        * See the comment in vi/v_text():set_txt_std for more information.
+        *
+        * !!!
+        * One more special case.  If an inserted <blank> character causes
+        * wrapmargin to split the line, the next user entered character is
+        * discarded if it's a <space> character.
+        */
+       wm_set = wm_skip = 0;
+       if (LF_ISSET(TXT_WRAPMARGIN))
+               if ((margin = O_VAL(sp, O_WRAPMARGIN)) != 0)
+                       margin = sp->cols - margin;
+               else
+                       margin = O_VAL(sp, O_WRAPLEN);
+       else
+               margin = 0;
+
+       /* Initialize abbreviation checks. */
+       abcnt = ab_turnoff = 0;
+       abb = F_ISSET(gp, G_ABBREV) &&
+           LF_ISSET(TXT_MAPINPUT) ? AB_INWORD : AB_NOTSET;
+
+       /*
+        * Set up the dot command.  Dot commands are done by saving the actual
+        * characters and then reevaluating them so that things like wrapmargin
+        * can change between the insert and the replay.
+        *
+        * !!!
+        * Historically, vi did not remap or reabbreviate replayed input.  (It
+        * did beep at you if you changed an abbreviation and then replayed the
+        * input.  We're not that compatible.)  We don't have to do anything to
+        * avoid remapping, as we're not getting characters from the terminal
+        * routines.  Turn the abbreviation check off.
+        *
+        * XXX
+        * It would be nice if we could swallow backspaces and such, but it's
+        * not all that easy to do.  What we can do is turn off the common
+        * error messages during the replay.  Otherwise, when the user enters
+        * an illegal command, e.g., "Ia<erase><erase><erase><erase>b<escape>",
+        * and then does a '.', they get a list of error messages after command
+        * completion.
+        */
+       rcol = 0;
+       if (LF_ISSET(TXT_REPLAY)) {
+               abb = AB_NOTSET;
+               LF_CLR(TXT_RECORD);
+       }
+
+       /* Other text input mode setup. */
+       quote = Q_NOTSET;
+       carat = C_NOTSET;
+       FL_INIT(is_flags,
+           LF_ISSET(TXT_SEARCHINCR) ? IS_RESTART | IS_RUNNING : 0);
+       filec_redraw = hexcnt = showmatch = 0;
+
+       /* Initialize input flags. */
+       ec_flags = LF_ISSET(TXT_MAPINPUT) ? EC_MAPINPUT : 0;
+
+       /* Refresh the screen. */
+       UPDATE_POSITION(sp, tp);
+       if (vs_refresh(sp, 1))
+               return (1);
+
+       /* If it's dot, just do it now. */
+       if (F_ISSET(vp, VC_ISDOT))
+               goto replay;
+
+       /* Get an event. */
+       evp = &ev;
+next:  if (v_event_get(sp, evp, 0, ec_flags))
+               return (1);
+
+       /*
+        * If file completion overwrote part of the screen and nothing else has
+        * been displayed, clean up.  We don't do this as part of the normal
+        * message resolution because we know the user is on the colon command
+        * line and there's no reason to enter explicit characters to continue.
+        */
+       if (filec_redraw && !F_ISSET(sp, SC_SCR_EXWROTE)) {
+               filec_redraw = 0;
+
+               fc.e_event = E_REPAINT;
+               fc.e_flno = vip->totalcount >=
+                   sp->rows ? 1 : sp->rows - vip->totalcount;
+               fc.e_tlno = sp->rows;
+               vip->linecount = vip->lcontinue = vip->totalcount = 0;
+               (void)v_erepaint(sp, &fc);
+               (void)vs_refresh(sp, 1);
+       }
+
+       /* Deal with all non-character events. */
+       switch (evp->e_event) {
+       case E_CHARACTER:
+               break;
+       case E_ERR:
+       case E_EOF:
+               F_SET(sp, SC_EXIT_FORCE);
+               return (1);
+       case E_INTERRUPT:
+               /*
+                * !!!
+                * Historically, <interrupt> exited the user from text input
+                * mode or cancelled a colon command, and returned to command
+                * mode.  It also beeped the terminal, but that seems a bit
+                * excessive.
+                */
+               goto k_escape;
+       case E_REPAINT:
+               if (v_erepaint(sp, &ev))
+                       return (1);
+               goto next;
+       case E_WRESIZE:
+               /* <resize> interrupts the input mode. */
+               v_emsg(sp, NULL, VIM_WRESIZE);
+               goto k_escape;
+       default:
+               v_event_err(sp, evp);
+               goto k_escape;
+       }
+
+       /*
+        * !!!
+        * If the first character of the input is a nul, replay the previous
+        * input.  (Historically, it's okay to replay non-existent input.)
+        * This was not documented as far as I know, and is a great test of vi
+        * clones.
+        */
+       if (rcol == 0 && !LF_ISSET(TXT_REPLAY) && evp->e_c == '\0') {
+               if (vip->rep == NULL)
+                       goto done;
+
+               abb = AB_NOTSET;
+               LF_CLR(TXT_RECORD);
+               LF_SET(TXT_REPLAY);
+               goto replay;
+       }
+
+       /*
+        * File name completion and colon command-line editing.   We don't
+        * have enough meta characters, so we expect people to overload
+        * them.  If the two characters are the same, then we do file name
+        * completion if the cursor is past the first column, and do colon
+        * command-line editing if it's not.
+        */
+       if (quote == Q_NOTSET) {
+               int L__cedit, L__filec;
+
+               L__cedit = L__filec = 0;
+               if (LF_ISSET(TXT_CEDIT) && O_STR(sp, O_CEDIT) != NULL &&
+                   O_STR(sp, O_CEDIT)[0] == evp->e_c)
+                       L__cedit = 1;
+               if (LF_ISSET(TXT_FILEC) && O_STR(sp, O_FILEC) != NULL &&
+                   O_STR(sp, O_FILEC)[0] == evp->e_c)
+                       L__filec = 1;
+               if (L__cedit == 1 && (L__filec == 0 || tp->cno == tp->offset)) {
+                       tp->term = TERM_CEDIT;
+                       goto k_escape;
+               }
+               if (L__filec == 1) {
+                       if (txt_fc(sp, tp, &filec_redraw))
+                               goto err;
+                       goto resolve;
+               }
+       }
+
+       /* Abbreviation overflow check.  See comment in txt_abbrev(). */
+#define        MAX_ABBREVIATION_EXPANSION      256
+       if (FL_ISSET(evp->e_flags, CH_ABBREVIATED)) {
+               if (++abcnt > MAX_ABBREVIATION_EXPANSION) {
+                       if (v_event_flush(sp, CH_ABBREVIATED))
+                               msgq(sp, M_ERR,
+"191|Abbreviation exceeded expansion limit: characters discarded");
+                       abcnt = 0;
+                       if (LF_ISSET(TXT_REPLAY))
+                               goto done;
+                       goto resolve;
+               }
+       } else
+               abcnt = 0;
+
+       /* Check to see if the character fits into the replay buffers. */
+       if (LF_ISSET(TXT_RECORD)) {
+               BINC_GOTO(sp, EVENT, vip->rep,
+                   vip->rep_len, (rcol + 1) * sizeof(EVENT));
+               vip->rep[rcol++] = *evp;
+       }
+
+replay:        if (LF_ISSET(TXT_REPLAY)) {
+               if (rcol == vip->rep_cnt)
+                       goto k_escape;
+               evp = vip->rep + rcol++;
+       }
+
+       /* Wrapmargin check for leading space. */
+       if (wm_skip) {
+               wm_skip = 0;
+               if (evp->e_c == ' ')
+                       goto resolve;
+       }
+
+       /* If quoted by someone else, simply insert the character. */
+       if (FL_ISSET(evp->e_flags, CH_QUOTED))
+               goto insq_ch;
+
+       /*
+        * !!!
+        * If this character was quoted by a K_VLNEXT or a backslash, replace
+        * the placeholder (a carat or a backslash) with the new character.
+        * If it was quoted by a K_VLNEXT, we've already adjusted the cursor
+        * because it has to appear on top of the placeholder character.  If
+        * it was quoted by a backslash, adjust the cursor now, the cursor
+        * doesn't appear on top of it.  Historic practice in both cases.
+        *
+        * Skip tests for abbreviations; ":ab xa XA" followed by "ixa^V<space>"
+        * doesn't perform an abbreviation.  Special case, ^V^J (not ^V^M) is
+        * the same as ^J, historically.
+        */
+       if (quote == Q_BTHIS || quote == Q_VTHIS) {
+               FL_CLR(ec_flags, EC_QUOTED);
+               if (LF_ISSET(TXT_MAPINPUT))
+                       FL_SET(ec_flags, EC_MAPINPUT);
+
+               if (quote == Q_BTHIS &&
+                   (evp->e_value == K_VERASE || evp->e_value == K_VKILL)) {
+                       quote = Q_NOTSET;
+                       --tp->cno;
+                       ++tp->owrite;
+                       goto insl_ch;
+               }
+               if (quote == Q_VTHIS && evp->e_value != K_NL) {
+                       quote = Q_NOTSET;
+                       goto insl_ch;
+               }
+               quote = Q_NOTSET;
+       }
+
+       /*
+        * !!!
+        * Translate "<CH_HEX>[isxdigit()]*" to a character with a hex value:
+        * this test delimits the value by any non-hex character.  Offset by
+        * one, we use 0 to mean that we've found <CH_HEX>.
+        */
+       if (hexcnt > 1 && !ISXDIGIT(evp->e_c)) {
+               hexcnt = 0;
+               if (txt_hex(sp, tp))
+                       goto err;
+       }
+
+       switch (evp->e_value) {
+       case K_CR:                              /* Carriage return. */
+       case K_NL:                              /* New line. */
+               /* Return in script windows and the command line. */
+k_cr:          if (LF_ISSET(TXT_CR)) {
+                       static CHAR_T cr[] = { '\r', 0 };
+                       /*
+                        * If this was a map, we may have not displayed
+                        * the line.  Display it, just in case.
+                        *
+                        * If a script window and not the colon line,
+                        * push a <cr> so it gets executed.
+                        */
+                       if (LF_ISSET(TXT_INFOLINE)) {
+                               if (vs_change(sp, tp->lno, LINE_RESET))
+                                       goto err;
+                       } else if (F_ISSET(sp, SC_SCRIPT))
+                               (void)v_event_push(sp, NULL, cr, 1, CH_NOMAP);
+
+                       /* Set term condition: if empty. */
+                       if (tp->cno <= tp->offset)
+                               tp->term = TERM_CR;
+                       /*
+                        * Set term condition: if searching incrementally and
+                        * the user entered a pattern, return a completed
+                        * search, regardless if the entire pattern was found.
+                        */
+                       if (FL_ISSET(is_flags, IS_RUNNING) &&
+                           tp->cno >= tp->offset + 1)
+                               tp->term = TERM_SEARCH;
+
+                       goto k_escape;
+               }
+
+#define        LINE_RESOLVE {                                                  \
+               /*                                                      \
+                * Handle abbreviations.  If there was one, discard the \
+                * replay characters.                                   \
+                */                                                     \
+               if (abb == AB_INWORD &&                                 \
+                   !LF_ISSET(TXT_REPLAY) && F_ISSET(gp, G_ABBREV)) {   \
+                       if (txt_abbrev(sp, tp, &evp->e_c,               \
+                           LF_ISSET(TXT_INFOLINE), &tmp,               \
+                           &ab_turnoff))                               \
+                               goto err;                               \
+                       if (tmp) {                                      \
+                               if (LF_ISSET(TXT_RECORD))               \
+                                       rcol -= tmp + 1;                \
+                               goto resolve;                           \
+                       }                                               \
+               }                                                       \
+               if (abb != AB_NOTSET)                                   \
+                       abb = AB_NOTWORD;                               \
+               if (UNMAP_TST)                                          \
+                       txt_unmap(sp, tp, &ec_flags);                   \
+               /*                                                      \
+                * Delete any appended cursor.  It's possible to get in \
+                * situations where TXT_APPENDEOL is set but tp->insert \
+                * is 0 when using the R command and all the characters \
+                * are tp->owrite characters.                           \
+                */                                                     \
+               if (LF_ISSET(TXT_APPENDEOL) && tp->insert > 0) {        \
+                       --tp->len;                                      \
+                       --tp->insert;                                   \
+               }                                                       \
+}
+               LINE_RESOLVE;
+
+               /*
+                * Save the current line information for restoration in
+                * txt_backup(), and set the line final length.
+                */
+               tp->sv_len = tp->len;
+               tp->sv_cno = tp->cno;
+               tp->len = tp->cno;
+
+               /* Update the old line. */
+               if (vs_change(sp, tp->lno, LINE_RESET))
+                       goto err;
+
+               /*
+                * Historic practice, when the autoindent edit option was set,
+                * was to delete <blank> characters following the inserted
+                * newline.  This affected the 'R', 'c', and 's' commands; 'c'
+                * and 's' retained the insert characters only, 'R' moved the
+                * overwrite and insert characters into the next TEXT structure.
+                * We keep track of the number of characters erased for the 'R'
+                * command so that the final resolution of the line is correct.
+                */
+               tp->R_erase = 0;
+               owrite = tp->owrite;
+               insert = tp->insert;
+               if (LF_ISSET(TXT_REPLACE) && owrite != 0) {
+                       for (p = tp->lb + tp->cno; owrite > 0 && ISBLANK((UCHAR_T)*p);
+                           ++p, --owrite, ++tp->R_erase);
+                       if (owrite == 0)
+                               for (; insert > 0 && ISBLANK((UCHAR_T)*p);
+                                   ++p, ++tp->R_erase, --insert);
+               } else {
+                       p = tp->lb + tp->cno + owrite;
+                       if (O_ISSET(sp, O_AUTOINDENT))
+                               for (; insert > 0 &&
+                                   ISBLANK((UCHAR_T)*p); ++p, --insert);
+                       owrite = 0;
+               }
+
+               /*
+                * !!!
+                * Create a new line and insert the new TEXT into the queue.
+                * DON'T insert until the old line has been updated, or the
+                * inserted line count in line.c:db_get() will be wrong.
+                */
+               if ((ntp = text_init(sp, p,
+                   insert + owrite, insert + owrite + 32)) == NULL)
+                       goto err;
+               CIRCLEQ_INSERT_TAIL(&sp->tiq, ntp, q);
+
+               /* Set up bookkeeping for the new line. */
+               ntp->insert = insert;
+               ntp->owrite = owrite;
+               ntp->lno = tp->lno + 1;
+
+               /*
+                * Reset the autoindent line value.  0^D keeps the autoindent
+                * line from changing, ^D changes the level, even if there were
+                * no characters in the old line.  Note, if using the current
+                * tp structure, use the cursor as the length, the autoindent
+                * characters may have been erased.
+                */
+               if (LF_ISSET(TXT_AUTOINDENT)) {
+                       if (carat == C_NOCHANGE) {
+                               if (v_txt_auto(sp, OOBLNO, &ait, ait.ai, ntp))
+                                       goto err;
+                               FREE_SPACEW(sp, ait.lb, ait.lb_len);
+                       } else
+                               if (v_txt_auto(sp, OOBLNO, tp, tp->cno, ntp))
+                                       goto err;
+                       carat = C_NOTSET;
+               }
+
+               /* Reset the cursor. */
+               ntp->cno = ntp->ai;
+
+               /*
+                * If we're here because wrapmargin was set and we've broken a
+                * line, there may be additional information (i.e. the start of
+                * a line) in the wmt structure.
+                */
+               if (wm_set) {
+                       if (wmt.offset != 0 ||
+                           wmt.owrite != 0 || wmt.insert != 0) {
+#define        WMTSPACE        wmt.offset + wmt.owrite + wmt.insert
+                               BINC_GOTOW(sp, ntp->lb,
+                                   ntp->lb_len, ntp->len + WMTSPACE + 32);
+                               MEMMOVEW(ntp->lb + ntp->cno, wmt.lb, WMTSPACE);
+                               ntp->len += WMTSPACE;
+                               ntp->cno += wmt.offset;
+                               ntp->owrite = wmt.owrite;
+                               ntp->insert = wmt.insert;
+                       }
+                       wm_set = 0;
+               }
+
+               /* New lines are TXT_APPENDEOL. */
+               if (ntp->owrite == 0 && ntp->insert == 0) {
+                       BINC_GOTOW(sp, ntp->lb, ntp->lb_len, ntp->len + 1);
+                       LF_SET(TXT_APPENDEOL);
+                       ntp->lb[ntp->cno] = CH_CURSOR;
+                       ++ntp->insert;
+                       ++ntp->len;
+               }
+
+               /* Swap old and new TEXT's, and update the new line. */
+               tp = ntp;
+               if (vs_change(sp, tp->lno, LINE_INSERT))
+                       goto err;
+
+               goto resolve;
+       case K_ESCAPE:                          /* Escape. */
+               if (!LF_ISSET(TXT_ESCAPE))
+                       goto ins_ch;
+
+               /* If we have a count, start replaying the input. */
+               if (rcount > 1) {
+                       --rcount;
+
+                       vip->rep_cnt = rcol;
+                       rcol = 0;
+                       abb = AB_NOTSET;
+                       LF_CLR(TXT_RECORD);
+                       LF_SET(TXT_REPLAY);
+
+                       /*
+                        * Some commands (e.g. 'o') need a <newline> for each
+                        * repetition.
+                        */
+                       if (LF_ISSET(TXT_ADDNEWLINE))
+                               goto k_cr;
+
+                       /*
+                        * The R command turns into the 'a' command after the
+                        * first repetition.
+                        */
+                       if (LF_ISSET(TXT_REPLACE)) {
+                               tp->insert = tp->owrite;
+                               tp->owrite = 0;
+                               LF_CLR(TXT_REPLACE);
+                       }
+                       goto replay;
+               }
+
+               /* Set term condition: if empty. */
+               if (tp->cno <= tp->offset)
+                       tp->term = TERM_ESC;
+               /*
+                * Set term condition: if searching incrementally and the user
+                * entered a pattern, return a completed search, regardless if
+                * the entire pattern was found.
+                */
+               if (FL_ISSET(is_flags, IS_RUNNING) && tp->cno >= tp->offset + 1)
+                       tp->term = TERM_SEARCH;
+
+k_escape:      LINE_RESOLVE;
+
+               /*
+                * Clean up for the 'R' command, restoring overwrite
+                * characters, and making them into insert characters.
+                */
+               if (LF_ISSET(TXT_REPLACE))
+                       txt_Rresolve(sp, &sp->tiq, tp, len);
+
+               /*
+                * If there are any overwrite characters, copy down
+                * any insert characters, and decrement the length.
+                */
+               if (tp->owrite) {
+                       if (tp->insert)
+                               MEMMOVEW(tp->lb + tp->cno,
+                                   tp->lb + tp->cno + tp->owrite, tp->insert);
+                       tp->len -= tp->owrite;
+               }
+
+               /*
+                * Optionally resolve the lines into the file.  If not
+                * resolving the lines into the file, end the line with
+                * a nul.  If the line is empty, then set the length to
+                * 0, the termination condition has already been set.
+                *
+                * XXX
+                * This is wrong, should pass back a length.
+                */
+               if (LF_ISSET(TXT_RESOLVE)) {
+                       if (txt_resolve(sp, &sp->tiq, flags))
+                               goto err;
+               } else {
+                       BINC_GOTOW(sp, tp->lb, tp->lb_len, tp->len + 1);
+                       tp->lb[tp->len] = '\0';
+               }
+
+               /*
+                * Set the return cursor position to rest on the last
+                * inserted character.
+                */
+               if (tp->cno != 0)
+                       --tp->cno;
+
+               /* Update the last line. */
+               if (vs_change(sp, tp->lno, LINE_RESET))
+                       return (1);
+               goto done;
+       case K_CARAT:                   /* Delete autoindent chars. */
+               if (tp->cno <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+                       carat = C_CARATSET;
+               goto ins_ch;
+       case K_ZERO:                    /* Delete autoindent chars. */
+               if (tp->cno <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+                       carat = C_ZEROSET;
+               goto ins_ch;
+       case K_CNTRLD:                  /* Delete autoindent char. */
+               /*
+                * If in the first column or no characters to erase, ignore
+                * the ^D (this matches historic practice).  If not doing
+                * autoindent or already inserted non-ai characters, it's a
+                * literal.  The latter test is done in the switch, as the
+                * CARAT forms are N + 1, not N.
+                */
+               if (!LF_ISSET(TXT_AUTOINDENT))
+                       goto ins_ch;
+               if (tp->cno == 0)
+                       goto resolve;
+
+               switch (carat) {
+               case C_CARATSET:        /* ^^D */
+                       if (tp->ai == 0 || tp->cno != tp->ai + tp->offset + 1)
+                               goto ins_ch;
+
+                       /* Save the ai string for later. */
+                       ait.lb = NULL;
+                       ait.lb_len = 0;
+                       BINC_GOTOW(sp, ait.lb, ait.lb_len, tp->ai);
+                       MEMMOVEW(ait.lb, tp->lb, tp->ai);
+                       ait.ai = ait.len = tp->ai;
+
+                       carat = C_NOCHANGE;
+                       goto leftmargin;
+               case C_ZEROSET:         /* 0^D */
+                       if (tp->ai == 0 || tp->cno != tp->ai + tp->offset + 1)
+                               goto ins_ch;
+
+                       carat = C_NOTSET;
+leftmargin:            tp->lb[tp->cno - 1] = ' ';
+                       tp->owrite += tp->cno - tp->offset;
+                       tp->cno = tp->offset;
+                       break;
+               case C_NOCHANGE:        /* ^D after reset with ^^D */
+                       /* FALLTHROUGH */
+               case C_NOTSET:          /* ^D */
+                       if (tp->ai == 0 || tp->cno != tp->ai + tp->offset)
+                               goto ins_ch;
+
+                       (void)txt_dent(sp, tp, 0);
+                       break;
+               default:
+                       abort();
+               }
+               break;
+       case K_VERASE:                  /* Erase the last character. */
+               /* If can erase over the prompt, return. */
+               if (tp->cno <= tp->offset && LF_ISSET(TXT_BS)) {
+                       tp->term = TERM_BS;
+                       goto done;
+               }
+
+               /*
+                * If at the beginning of the line, try and drop back to a
+                * previously inserted line.
+                */
+               if (tp->cno == 0) {
+                       if ((ntp =
+                           txt_backup(sp, &sp->tiq, tp, &flags)) == NULL)
+                               goto err;
+                       tp = ntp;
+                       break;
+               }
+
+               /* If nothing to erase, bell the user. */
+               if (tp->cno <= tp->offset) {
+                       if (!LF_ISSET(TXT_REPLAY))
+                               txt_nomorech(sp);
+                       break;
+               }
+
+               /* Drop back one character. */
+               --tp->cno;
+
+               /*
+                * Historically, vi didn't replace the erased characters with
+                * <blank>s, presumably because it's easier to fix a minor
+                * typing mistake and continue on if the previous letters are
+                * already there.  This is a problem for incremental searching,
+                * because the user can no longer tell where they are in the
+                * colon command line because the cursor is at the last search
+                * point in the screen.  So, if incrementally searching, erase
+                * the erased characters from the screen.
+                */
+               if (FL_ISSET(is_flags, IS_RUNNING))
+                       tp->lb[tp->cno] = ' ';
+
+               /*
+                * Increment overwrite, decrement ai if deleted.
+                *
+                * !!!
+                * Historic vi did not permit users to use erase characters
+                * to delete autoindent characters.  We do.  Eat hot death,
+                * POSIX.
+                */
+               ++tp->owrite;
+               if (tp->cno < tp->ai)
+                       --tp->ai;
+
+               /* Reset if we deleted an incremental search character. */
+               if (FL_ISSET(is_flags, IS_RUNNING))
+                       FL_SET(is_flags, IS_RESTART);
+               break;
+       case K_VWERASE:                 /* Skip back one word. */
+               /*
+                * If at the beginning of the line, try and drop back to a
+                * previously inserted line.
+                */
+               if (tp->cno == 0) {
+                       if ((ntp =
+                           txt_backup(sp, &sp->tiq, tp, &flags)) == NULL)
+                               goto err;
+                       tp = ntp;
+               }
+
+               /*
+                * If at offset, nothing to erase so bell the user.
+                */
+               if (tp->cno <= tp->offset) {
+                       if (!LF_ISSET(TXT_REPLAY))
+                               txt_nomorech(sp);
+                       break;
+               }
+
+               /*
+                * The first werase goes back to any autoindent column and the
+                * second werase goes back to the offset.
+                *
+                * !!!
+                * Historic vi did not permit users to use erase characters to
+                * delete autoindent characters.
+                */
+               if (tp->ai && tp->cno > tp->ai)
+                       max = tp->ai;
+               else {
+                       tp->ai = 0;
+                       max = tp->offset;
+               }
+
+               /* Skip over trailing space characters. */
+               while (tp->cno > max && ISBLANK((UCHAR_T)tp->lb[tp->cno - 1])) {
+                       --tp->cno;
+                       ++tp->owrite;
+               }
+               if (tp->cno == max)
+                       break;
+               /*
+                * There are three types of word erase found on UNIX systems.
+                * They can be identified by how the string /a/b/c is treated
+                * -- as 1, 3, or 6 words.  Historic vi had two classes of
+                * characters, and strings were delimited by them and
+                * <blank>'s, so, 6 words.  The historic tty interface used
+                * <blank>'s to delimit strings, so, 1 word.  The algorithm
+                * offered in the 4.4BSD tty interface (as stty altwerase)
+                * treats it as 3 words -- there are two classes of
+                * characters, and strings are delimited by them and
+                * <blank>'s.  The difference is that the type of the first
+                * erased character erased is ignored, which is exactly right
+                * when erasing pathname components.  The edit options
+                * TXT_ALTWERASE and TXT_TTYWERASE specify the 4.4BSD tty
+                * interface and the historic tty driver behavior,
+                * respectively, and the default is the same as the historic
+                * vi behavior.
+                *
+                * Overwrite erased characters if doing incremental search;
+                * see comment above.
+                */
+               if (LF_ISSET(TXT_TTYWERASE))
+                       while (tp->cno > max) {
+                               --tp->cno;
+                               ++tp->owrite;
+                               if (FL_ISSET(is_flags, IS_RUNNING))
+                                       tp->lb[tp->cno] = ' ';
+                               if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
+                                       break;
+                       }
+               else {
+                       if (LF_ISSET(TXT_ALTWERASE)) {
+                               --tp->cno;
+                               ++tp->owrite;
+                               if (FL_ISSET(is_flags, IS_RUNNING))
+                                       tp->lb[tp->cno] = ' ';
+                               if (ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
+                                       break;
+                       }
+                       if (tp->cno > max)
+                               tmp = inword((UCHAR_T)tp->lb[tp->cno - 1]);
+                       while (tp->cno > max) {
+                               --tp->cno;
+                               ++tp->owrite;
+                               if (FL_ISSET(is_flags, IS_RUNNING))
+                                       tp->lb[tp->cno] = ' ';
+                               if (tmp != inword((UCHAR_T)tp->lb[tp->cno - 1])
+                                   || ISBLANK((UCHAR_T)tp->lb[tp->cno - 1]))
+                                       break;
+                       }
+               }
+
+               /* Reset if we deleted an incremental search character. */
+               if (FL_ISSET(is_flags, IS_RUNNING))
+                       FL_SET(is_flags, IS_RESTART);
+               break;
+       case K_VKILL:                   /* Restart this line. */
+               /*
+                * !!!
+                * If at the beginning of the line, try and drop back to a
+                * previously inserted line.  Historic vi did not permit
+                * users to go back to previous lines.
+                */
+               if (tp->cno == 0) {
+                       if ((ntp =
+                           txt_backup(sp, &sp->tiq, tp, &flags)) == NULL)
+                               goto err;
+                       tp = ntp;
+               }
+
+               /* If at offset, nothing to erase so bell the user. */
+               if (tp->cno <= tp->offset) {
+                       if (!LF_ISSET(TXT_REPLAY))
+                               txt_nomorech(sp);
+                       break;
+               }
+
+               /*
+                * First kill goes back to any autoindent and second kill goes
+                * back to the offset.
+                *
+                * !!!
+                * Historic vi did not permit users to use erase characters to
+                * delete autoindent characters.
+                */
+               if (tp->ai && tp->cno > tp->ai)
+                       max = tp->ai;
+               else {
+                       tp->ai = 0;
+                       max = tp->offset;
+               }
+               tp->owrite += tp->cno - max;
+
+               /*
+                * Overwrite erased characters if doing incremental search;
+                * see comment above.
+                */
+               if (FL_ISSET(is_flags, IS_RUNNING))
+                       do {
+                               tp->lb[--tp->cno] = ' ';
+                       } while (tp->cno > max);
+               else
+                       tp->cno = max;
+
+               /* Reset if we deleted an incremental search character. */
+               if (FL_ISSET(is_flags, IS_RUNNING))
+                       FL_SET(is_flags, IS_RESTART);
+               break;
+       case K_CNTRLT:                  /* Add autoindent characters. */
+               if (!LF_ISSET(TXT_CNTRLT))
+                       goto ins_ch;
+               if (txt_dent(sp, tp, 1))
+                       goto err;
+               goto ebuf_chk;
+       case K_RIGHTBRACE:
+       case K_RIGHTPAREN:
+               if (LF_ISSET(TXT_SHOWMATCH))
+                       showmatch = 1;
+               goto ins_ch;
+       case K_BACKSLASH:               /* Quote next erase/kill. */
+               /*
+                * !!!
+                * Historic vi tried to make abbreviations after a backslash
+                * escape work.  If you did ":ab x y", and inserted "x\^H",
+                * (assuming the erase character was ^H) you got "x^H", and
+                * no abbreviation was done.  If you inserted "x\z", however,
+                * it tried to back up and do the abbreviation, i.e. replace
+                * 'x' with 'y'.  The problem was it got it wrong, and you
+                * ended up with "zy\".
+                *
+                * This is really hard to do (you have to remember the
+                * word/non-word state, for example), and doesn't make any
+                * sense to me.  Both backslash and the characters it
+                * (usually) escapes will individually trigger the
+                * abbreviation, so I don't see why the combination of them
+                * wouldn't.  I don't expect to get caught on this one,
+                * particularly since it never worked right, but I've been
+                * wrong before.
+                *
+                * Do the tests for abbreviations, so ":ab xa XA",
+                * "ixa\<K_VERASE>" performs the abbreviation.
+                */
+               quote = Q_BNEXT;
+               goto insq_ch;
+       case K_VLNEXT:                  /* Quote next character. */
+               evp->e_c = '^';
+               quote = Q_VNEXT;
+               /*
+                * Turn on the quote flag so that the underlying routines
+                * quote the next character where it's possible. Turn off
+                * the input mapbiting flag so that we don't remap the next
+                * character.
+                */
+               FL_SET(ec_flags, EC_QUOTED);
+               FL_CLR(ec_flags, EC_MAPINPUT);
+
+               /*
+                * !!!
+                * Skip the tests for abbreviations, so ":ab xa XA",
+                * "ixa^V<space>" doesn't perform the abbreviation.
+                */
+               goto insl_ch;
+       case K_HEXCHAR:
+               hexcnt = 1;
+               goto insq_ch;
+       default:                        /* Insert the character. */
+ins_ch:                /*
+                * Historically, vi eliminated nul's out of hand.  If the
+                * beautify option was set, it also deleted any unknown
+                * ASCII value less than space (040) and the del character
+                * (0177), except for tabs.  Unknown is a key word here.
+                * Most vi documentation claims that it deleted everything
+                * but <tab>, <nl> and <ff>, as that's what the original
+                * 4BSD documentation said.  This is obviously wrong,
+                * however, as <esc> would be included in that list.  What
+                * we do is eliminate any unquoted, iscntrl() character that
+                * wasn't a replay and wasn't handled specially, except
+                * <tab> or <ff>.
+                */
+               if (LF_ISSET(TXT_BEAUTIFY) && ISCNTRL(evp->e_c) &&
+                   evp->e_value != K_FORMFEED && evp->e_value != K_TAB) {
+                       msgq(sp, M_BERR,
+                           "192|Illegal character; quote to enter");
+                       if (LF_ISSET(TXT_REPLAY))
+                               goto done;
+                       break;
+               }
+
+insq_ch:       /*
+                * If entering a non-word character after a word, check for
+                * abbreviations.  If there was one, discard replay characters.
+                * If entering a blank character, check for unmap commands,
+                * as well.
+                */
+               if (!inword(evp->e_c)) {
+                       if (abb == AB_INWORD &&
+                           !LF_ISSET(TXT_REPLAY) && F_ISSET(gp, G_ABBREV)) {
+                               if (txt_abbrev(sp, tp, &evp->e_c,
+                                   LF_ISSET(TXT_INFOLINE), &tmp, &ab_turnoff))
+                                       goto err;
+                               if (tmp) {
+                                       if (LF_ISSET(TXT_RECORD))
+                                               rcol -= tmp + 1;
+                                       goto resolve;
+                               }
+                       }
+                       if (ISBLANK(evp->e_c) && UNMAP_TST)
+                               txt_unmap(sp, tp, &ec_flags);
+               }
+               if (abb != AB_NOTSET)
+                       abb = inword(evp->e_c) ? AB_INWORD : AB_NOTWORD;
+
+insl_ch:       if (txt_insch(sp, tp, &evp->e_c, flags))
+                       goto err;
+
+               /*
+                * If we're using K_VLNEXT to quote the next character, then
+                * we want the cursor to position itself on the ^ placeholder
+                * we're displaying, to match historic practice.
+                */
+               if (quote == Q_VNEXT) {
+                       --tp->cno;
+                       ++tp->owrite;
+               }
+
+               /*
+                * !!!
+                * Translate "<CH_HEX>[isxdigit()]*" to a character with
+                * a hex value: this test delimits the value by the max
+                * number of hex bytes.  Offset by one, we use 0 to mean
+                * that we've found <CH_HEX>.
+                */
+               if (hexcnt != 0 && hexcnt++ == sizeof(CHAR_T) * 2 + 1) {
+                       hexcnt = 0;
+                       if (txt_hex(sp, tp))
+                               goto err;
+               }
+
+               /*
+                * Check to see if we've crossed the margin.
+                *
+                * !!!
+                * In the historic vi, the wrapmargin value was figured out
+                * using the display widths of the characters, i.e. <tab>
+                * characters were counted as two characters if the list edit
+                * option is set, but as the tabstop edit option number of
+                * characters otherwise.  That's what the vs_column() function
+                * gives us, so we use it.
+                */
+               if (margin != 0) {
+                       if (vs_column(sp, &tcol))
+                               goto err;
+                       if (tcol >= margin) {
+                               if (txt_margin(sp, tp, &wmt, &tmp, flags))
+                                       goto err;
+                               if (tmp) {
+                                       if (ISBLANK(evp->e_c))
+                                               wm_skip = 1;
+                                       wm_set = 1;
+                                       goto k_cr;
+                               }
+                       }
+               }
+
+               /*
+                * If we've reached the end of the buffer, then we need to
+                * switch into insert mode.  This happens when there's a
+                * change to a mark and the user puts in more characters than
+                * the length of the motion.
+                */
+ebuf_chk:      if (tp->cno >= tp->len) {
+                       BINC_GOTOW(sp, tp->lb, tp->lb_len, tp->len + 1);
+                       LF_SET(TXT_APPENDEOL);
+
+                       tp->lb[tp->cno] = CH_CURSOR;
+                       ++tp->insert;
+                       ++tp->len;
+               }
+
+               /* Step the quote state forward. */
+               if (quote != Q_NOTSET) {
+                       if (quote == Q_BNEXT)
+                               quote = Q_BTHIS;
+                       if (quote == Q_VNEXT)
+                               quote = Q_VTHIS;
+               }
+               break;
+       }
+
+#ifdef DEBUG
+       if (tp->cno + tp->insert + tp->owrite != tp->len) {
+               msgq(sp, M_ERR,
+                   "len %u != cno: %u ai: %u insert %u overwrite %u",
+                   tp->len, tp->cno, tp->ai, tp->insert, tp->owrite);
+               if (LF_ISSET(TXT_REPLAY))
+                       goto done;
+               tp->len = tp->cno + tp->insert + tp->owrite;
+       }
+#endif
+
+resolve:/*
+        * 1: If we don't need to know where the cursor really is and we're
+        *    replaying text, keep going.
+        */
+       if (margin == 0 && LF_ISSET(TXT_REPLAY))
+               goto replay;
+
+       /*
+        * 2: Reset the line.  Don't bother unless we're about to wait on
+        *    a character or we need to know where the cursor really is.
+        *    We have to do this before showing matching characters so the
+        *    user can see what they're matching.
+        */
+       if ((margin != 0 || !KEYS_WAITING(sp)) &&
+           vs_change(sp, tp->lno, LINE_RESET))
+               return (1);
+
+       /*
+        * 3: If there aren't keys waiting, display the matching character.
+        *    We have to do this before resolving any messages, otherwise
+        *    the error message from a missing match won't appear correctly.
+        */
+       if (showmatch) {
+               if (!KEYS_WAITING(sp) && txt_showmatch(sp, tp))
+                       return (1);
+               showmatch = 0;
+       }
+
+       /*
+        * 4: If there have been messages and we're not editing on the colon
+        *    command line or doing file name completion, resolve them.
+        */
+       if ((vip->totalcount != 0 || F_ISSET(gp, G_BELLSCHED)) &&
+           !F_ISSET(sp, SC_TINPUT_INFO) && !filec_redraw &&
+           vs_resolve(sp, NULL, 0))
+               return (1);
+
+       /*
+        * 5: Refresh the screen if we're about to wait on a character or we
+        *    need to know where the cursor really is.
+        */
+       if (margin != 0 || !KEYS_WAITING(sp)) {
+               UPDATE_POSITION(sp, tp);
+               if (vs_refresh(sp, margin != 0))
+                       return (1);
+       }
+
+       /* 6: Proceed with the incremental search. */
+       if (FL_ISSET(is_flags, IS_RUNNING) && txt_isrch(sp, vp, tp, &is_flags))
+               return (1);
+
+       /* 7: Next character... */
+       if (LF_ISSET(TXT_REPLAY))
+               goto replay;
+       goto next;
+
+done:  /* Leave input mode. */
+       F_CLR(sp, SC_TINPUT);
+
+       /* If recording for playback, save it. */
+       if (LF_ISSET(TXT_RECORD))
+               vip->rep_cnt = rcol;
+
+       /*
+        * If not working on the colon command line, set the final cursor
+        * position.
+        */
+       if (!F_ISSET(sp, SC_TINPUT_INFO)) {
+               vp->m_final.lno = tp->lno;
+               vp->m_final.cno = tp->cno;
+       }
+       return (0);
+
+err:
+alloc_err:
+       F_CLR(sp, SC_TINPUT);
+       txt_err(sp, &sp->tiq);
+       return (1);
+}
+
+/*
+ * txt_abbrev --
+ *     Handle abbreviations.
+ */
+static int
+txt_abbrev(SCR *sp, TEXT *tp, ARG_CHAR_T *pushcp, int isinfoline, int *didsubp, int *turnoffp)
+{
+       VI_PRIVATE *vip;
+       CHAR_T ch, *p;
+       SEQ *qp;
+       size_t len, off;
+
+       /* Check to make sure we're not at the start of an append. */
+       *didsubp = 0;
+       if (tp->cno == tp->offset)
+               return (0);
+
+       vip = VIP(sp);
+
+       /*
+        * Find the start of the "word".
+        *
+        * !!!
+        * We match historic practice, which, as far as I can tell, had an
+        * off-by-one error.  The way this worked was that when the inserted
+        * text switched from a "word" character to a non-word character,
+        * vi would check for possible abbreviations.  It would then take the
+        * type (i.e. word/non-word) of the character entered TWO characters
+        * ago, and move backward in the text until reaching a character that
+        * was not that type, or the beginning of the insert, the line, or
+        * the file.  For example, in the string "abc<space>", when the <space>
+        * character triggered the abbreviation check, the type of the 'b'
+        * character was used for moving through the string.  Maybe there's a
+        * reason for not using the first (i.e. 'c') character, but I can't
+        * think of one.
+        *
+        * Terminate at the beginning of the insert or the character after the
+        * offset character -- both can be tested for using tp->offset.
+        */
+       off = tp->cno - 1;                      /* Previous character. */
+       p = tp->lb + off;
+       len = 1;                                /* One character test. */
+       if (off == tp->offset || ISBLANK((UCHAR_T)p[-1]))
+               goto search;
+       if (inword((UCHAR_T)p[-1]))                     /* Move backward to change. */
+               for (;;) {
+                       --off; --p; ++len;
+                       if (off == tp->offset || !inword((UCHAR_T)p[-1]))
+                               break;
+               }
+       else
+               for (;;) {
+                       --off; --p; ++len;
+                       if (off == tp->offset ||
+                           inword((UCHAR_T)p[-1]) || ISBLANK((UCHAR_T)p[-1]))
+                               break;
+               }
+
+       /*
+        * !!!
+        * Historic vi exploded abbreviations on the command line.  This has
+        * obvious problems in that unabbreviating the string can be extremely
+        * tricky, particularly if the string has, say, an embedded escape
+        * character.  Personally, I think it's a stunningly bad idea.  Other
+        * examples of problems this caused in historic vi are:
+        *      :ab foo bar
+        *      :ab foo baz
+        * results in "bar" being abbreviated to "baz", which wasn't what the
+        * user had in mind at all.  Also, the commands:
+        *      :ab foo bar
+        *      :unab foo<space>
+        * resulted in an error message that "bar" wasn't mapped.  Finally,
+        * since the string was already exploded by the time the unabbreviate
+        * command got it, all it knew was that an abbreviation had occurred.
+        * Cleverly, it checked the replacement string for its unabbreviation
+        * match, which meant that the commands:
+        *      :ab foo1 bar
+        *      :ab foo2 bar
+        *      :unab foo2
+        * unabbreviate "foo1", and the commands:
+        *      :ab foo bar
+        *      :ab bar baz
+        * unabbreviate "foo"!
+        *
+        * Anyway, people neglected to first ask my opinion before they wrote
+        * macros that depend on this stuff, so, we make this work as follows.
+        * When checking for an abbreviation on the command line, if we get a
+        * string which is <blank> terminated and which starts at the beginning
+        * of the line, we check to see it is the abbreviate or unabbreviate
+        * commands.  If it is, turn abbreviations off and return as if no
+        * abbreviation was found.  Note also, minor trickiness, so that if
+        * the user erases the line and starts another command, we turn the
+        * abbreviations back on.
+        *
+        * This makes the layering look like a Nachos Supreme.
+        */
+search:        if (isinfoline) {
+               if (off == tp->ai || off == tp->offset)
+                       if (ex_is_abbrev(sp, p, len)) {
+                               *turnoffp = 1;
+                               return (0);
+                       } else
+                               *turnoffp = 0;
+               else
+                       if (*turnoffp)
+                               return (0);
+       }
+
+       /* Check for any abbreviations. */
+       if ((qp = seq_find(sp, NULL, NULL, p, len, SEQ_ABBREV, NULL)) == NULL)
+               return (0);
+
+       /*
+        * Push the abbreviation onto the tty stack.  Historically, characters
+        * resulting from an abbreviation expansion were themselves subject to
+        * map expansions, O_SHOWMATCH matching etc.  This means the expanded
+        * characters will be re-tested for abbreviations.  It's difficult to
+        * know what historic practice in this case was, since abbreviations
+        * were applied to :colon command lines, so entering abbreviations that
+        * looped was tricky, although possible.  In addition, obvious loops
+        * didn't work as expected.  (The command ':ab a b|ab b c|ab c a' will
+        * silently only implement and/or display the last abbreviation.)
+        *
+        * This implementation doesn't recover well from such abbreviations.
+        * The main input loop counts abbreviated characters, and, when it
+        * reaches a limit, discards any abbreviated characters on the queue.
+        * It's difficult to back up to the original position, as the replay
+        * queue would have to be adjusted, and the line state when an initial
+        * abbreviated character was received would have to be saved.
+        */
+       ch = (UCHAR_T)*pushcp;
+       if (v_event_push(sp, NULL, &ch, 1, CH_ABBREVIATED))
+               return (1);
+       if (v_event_push(sp, NULL, qp->output, qp->olen, CH_ABBREVIATED))
+               return (1);
+
+       /*
+        * If the size of the abbreviation is larger than or equal to the size
+        * of the original text, move to the start of the replaced characters,
+        * and add their length to the overwrite count.
+        *
+        * If the abbreviation is smaller than the original text, we have to
+        * delete the additional overwrite characters and copy down any insert
+        * characters.
+        */
+       tp->cno -= len;
+       if (qp->olen >= len)
+               tp->owrite += len;
+       else {
+               if (tp->insert)
+                       MEMMOVEW(tp->lb + tp->cno + qp->olen,
+                           tp->lb + tp->cno + tp->owrite + len, tp->insert);
+               tp->owrite += qp->olen;
+               tp->len -= len - qp->olen;
+       }
+
+       /*
+        * We return the length of the abbreviated characters.  This is so
+        * the calling routine can replace the replay characters with the
+        * abbreviation.  This means that subsequent '.' commands will produce
+        * the same text, regardless of intervening :[un]abbreviate commands.
+        * This is historic practice.
+        */
+       *didsubp = len;
+       return (0);
+}
+
+/*
+ * txt_unmap --
+ *     Handle the unmap command.
+ */
+static void
+txt_unmap(SCR *sp, TEXT *tp, u_int32_t *ec_flagsp)
+{
+       size_t len, off;
+       CHAR_T *p;
+
+       /* Find the beginning of this "word". */
+       for (off = tp->cno - 1, p = tp->lb + off, len = 0;; --p, --off) {
+               if (ISBLANK((UCHAR_T)*p)) {
+                       ++p;
+                       break;
+               }
+               ++len;
+               if (off == tp->ai || off == tp->offset)
+                       break;
+       }
+
+       /*
+        * !!!
+        * Historic vi exploded input mappings on the command line.  See the
+        * txt_abbrev() routine for an explanation of the problems inherent
+        * in this.
+        *
+        * We make this work as follows.  If we get a string which is <blank>
+        * terminated and which starts at the beginning of the line, we check
+        * to see it is the unmap command.  If it is, we return that the input
+        * mapping should be turned off.  Note also, minor trickiness, so that
+        * if the user erases the line and starts another command, we go ahead
+        * an turn mapping back on.
+        */
+       if ((off == tp->ai || off == tp->offset) && ex_is_unmap(sp, p, len))
+               FL_CLR(*ec_flagsp, EC_MAPINPUT);
+       else
+               FL_SET(*ec_flagsp, EC_MAPINPUT);
+}
+
+/*
+ * txt_ai_resolve --
+ *     When a line is resolved by <esc>, review autoindent characters.
+ */
+static void
+txt_ai_resolve(SCR *sp, TEXT *tp, int *changedp)
+{
+       u_long ts;
+       int delc;
+       size_t cno, len, new, old, scno, spaces, tab_after_sp, tabs;
+       CHAR_T *p;
+
+       *changedp = 0;
+
+       /*
+        * If the line is empty, has an offset, or no autoindent
+        * characters, we're done.
+        */
+       if (!tp->len || tp->offset || !tp->ai)
+               return;
+
+       /*
+        * If the length is less than or equal to the autoindent
+        * characters, delete them.
+        */
+       if (tp->len <= tp->ai) {
+               tp->ai = tp->cno = tp->len = 0;
+               return;
+       }
+
+       /*
+        * The autoindent characters plus any leading <blank> characters
+        * in the line are resolved into the minimum number of characters.
+        * Historic practice.
+        */
+       ts = O_VAL(sp, O_TABSTOP);
+
+       /* Figure out the last <blank> screen column. */
+       for (p = tp->lb, scno = 0, len = tp->len,
+           spaces = tab_after_sp = 0; len-- && ISBLANK((UCHAR_T)*p); ++p)
+               if (*p == '\t') {
+                       if (spaces)
+                               tab_after_sp = 1;
+                       scno += COL_OFF(scno, ts);
+               } else {
+                       ++spaces;
+                       ++scno;
+               }
+
+       /*
+        * If there are no spaces, or no tabs after spaces and less than
+        * ts spaces, it's already minimal.
+        * Keep analysing if expandtab is set.
+        */
+       if ((!spaces || (!tab_after_sp && spaces < ts)) &&
+           !O_ISSET(sp, O_EXPANDTAB))
+               return;
+
+       /* Count up spaces/tabs needed to get to the target. */
+       cno = 0;
+       tabs = 0;
+       if (!O_ISSET(sp, O_EXPANDTAB)) {
+               for (; cno + COL_OFF(cno, ts) <= scno; ++tabs)
+                       cno += COL_OFF(cno, ts);
+       }
+       spaces = scno - cno;
+
+       /*
+        * Figure out how many characters we're dropping -- if we're not
+        * dropping any, it's already minimal, we're done.
+        */
+       old = p - tp->lb;
+       new = spaces + tabs;
+       if (old == new)
+               return;
+
+       /* Shift the rest of the characters down, adjust the counts. */
+       delc = old - new;
+       MEMMOVEW(p - delc, p, tp->len - old);
+       tp->len -= delc;
+       tp->cno -= delc;
+
+       /* Fill in space/tab characters. */
+       for (p = tp->lb; tabs--;)
+               *p++ = '\t';
+       while (spaces--)
+               *p++ = ' ';
+       *changedp = 1;
+}
+
+/*
+ * v_txt_auto --
+ *     Handle autoindent.  If aitp isn't NULL, use it, otherwise,
+ *     retrieve the line.
+ *
+ * PUBLIC: int v_txt_auto __P((SCR *, db_recno_t, TEXT *, size_t, TEXT *));
+ */
+int
+v_txt_auto(SCR *sp, db_recno_t lno, TEXT *aitp, size_t len, TEXT *tp)
+{
+       size_t nlen;
+       CHAR_T *p, *t;
+
+       if (aitp == NULL) {
+               /*
+                * If the ex append command is executed with an address of 0,
+                * it's possible to get here with a line number of 0.  Return
+                * an indent of 0.
+                */
+               if (lno == 0) {
+                       tp->ai = 0;
+                       return (0);
+               }
+               if (db_get(sp, lno, DBG_FATAL, &t, &len))
+                       return (1);
+       } else
+               t = aitp->lb;
+
+       /* Count whitespace characters. */
+       for (p = t; len > 0; ++p, --len)
+               if (!ISBLANK((UCHAR_T)*p))
+                       break;
+
+       /* Set count, check for no indentation. */
+       if ((nlen = (p - t)) == 0)
+               return (0);
+
+       /* Make sure the buffer's big enough. */
+       BINC_RETW(sp, tp->lb, tp->lb_len, tp->len + nlen);
+
+       /* Copy the buffer's current contents up. */
+       if (tp->len != 0)
+               MEMMOVEW(tp->lb + nlen, tp->lb, tp->len);
+       tp->len += nlen;
+
+       /* Copy the indentation into the new buffer. */
+       MEMMOVEW(tp->lb, t, nlen);
+
+       /* Set the autoindent count. */
+       tp->ai = nlen;
+       return (0);
+}
+
+/*
+ * txt_backup --
+ *     Back up to the previously edited line.
+ */
+static TEXT *
+txt_backup(SCR *sp, TEXTH *tiqh, TEXT *tp, u_int32_t *flagsp)
+{
+       VI_PRIVATE *vip;
+       TEXT *ntp;
+
+       /* Get a handle on the previous TEXT structure. */
+       if ((ntp = tp->q.cqe_prev) == (void *)tiqh) {
+               if (!FL_ISSET(*flagsp, TXT_REPLAY))
+                       msgq(sp, M_BERR,
+                           "193|Already at the beginning of the insert");
+               return (tp);
+       }
+
+       /* Bookkeeping. */
+       ntp->len = ntp->sv_len;
+
+       /* Handle appending to the line. */
+       vip = VIP(sp);
+       if (ntp->owrite == 0 && ntp->insert == 0) {
+               ntp->lb[ntp->len] = CH_CURSOR;
+               ++ntp->insert;
+               ++ntp->len;
+               FL_SET(*flagsp, TXT_APPENDEOL);
+       } else
+               FL_CLR(*flagsp, TXT_APPENDEOL);
+
+       /* Release the current TEXT. */
+       CIRCLEQ_REMOVE(tiqh, tp, q);
+       text_free(tp);
+
+       /* Update the old line on the screen. */
+       if (vs_change(sp, ntp->lno + 1, LINE_DELETE))
+               return (NULL);
+
+       /* Return the new/current TEXT. */
+       return (ntp);
+}
+
+/*
+ * Text indentation is truly strange.  ^T and ^D do movements to the next or
+ * previous shiftwidth value, i.e. for a 1-based numbering, with shiftwidth=3,
+ * ^T moves a cursor on the 7th, 8th or 9th column to the 10th column, and ^D
+ * moves it back.
+ *
+ * !!!
+ * The ^T and ^D characters in historical vi had special meaning only when they
+ * were the first characters entered after entering text input mode.  As normal
+ * erase characters couldn't erase autoindent characters (^T in this case), it
+ * meant that inserting text into previously existing text was strange -- ^T
+ * only worked if it was the first keystroke(s), and then could only be erased
+ * using ^D.  This implementation treats ^T specially anywhere it occurs in the
+ * input, and permits the standard erase characters to erase the characters it
+ * inserts.
+ *
+ * !!!
+ * A fun test is to try:
+ *     :se sw=4 ai list
+ *     i<CR>^Tx<CR>^Tx<CR>^Tx<CR>^Dx<CR>^Dx<CR>^Dx<esc>
+ * Historic vi loses some of the '$' marks on the line ends, but otherwise gets
+ * it right.
+ *
+ * XXX
+ * Technically, txt_dent should be part of the screen interface, as it requires
+ * knowledge of character sizes, including <space>s, on the screen.  It's here
+ * because it's a complicated little beast, and I didn't want to shove it down
+ * into the screen.  It's probable that KEY_LEN will call into the screen once
+ * there are screens with different character representations.
+ *
+ * txt_dent --
+ *     Handle ^T indents, ^D outdents.
+ *
+ * If anything changes here, check the ex version to see if it needs similar
+ * changes.
+ */
+static int
+txt_dent(SCR *sp, TEXT *tp, int isindent)
+{
+       ARG_CHAR_T ch;
+       u_long sw, ts;
+       size_t cno, current, spaces, target, tabs;
+
+       ts = O_VAL(sp, O_TABSTOP);
+       sw = O_VAL(sp, O_SHIFTWIDTH);
+
+       /*
+        * Since we don't know what precedes the character(s) being inserted
+        * (or deleted), the preceding whitespace characters must be resolved.
+        * An example is a <tab>, which doesn't need a full shiftwidth number
+        * of columns because it's preceded by <space>s.  This is easy to get
+        * if the user sets shiftwidth to a value less than tabstop (or worse,
+        * something for which tabstop isn't a multiple) and then uses ^T to
+        * indent, and ^D to outdent.
+        *
+        * Figure out the current and target screen columns.  In the historic
+        * vi, the autoindent column was NOT determined using display widths
+        * of characters as was the wrapmargin column.  For that reason, we
+        * can't use the vs_column() function, but have to calculate it here.
+        * This is slow, but it's normally only on the first few characters of
+        * a line.
+        */
+       for (current = cno = 0; cno < tp->cno; ++cno)
+               current += tp->lb[cno] == '\t' ?
+                   COL_OFF(current, ts) : KEY_COL(sp, tp->lb[cno]);
+
+       target = current;
+       if (isindent)
+               target += COL_OFF(target, sw);
+       else {
+               --target;
+               target -= target % sw;
+       }
+
+       /*
+        * Back up over any previous <blank> characters, changing them into
+        * overwrite characters (including any ai characters).  Then figure
+        * out the current screen column.
+        */
+       for (; tp->cno > tp->offset &&
+           (tp->lb[tp->cno - 1] == ' ' || tp->lb[tp->cno - 1] == '\t');
+           --tp->cno, ++tp->owrite);
+       for (current = cno = 0; cno < tp->cno; ++cno)
+               current += tp->lb[cno] == '\t' ?
+                   COL_OFF(current, ts) : KEY_COL(sp, tp->lb[cno]);
+
+       /*
+        * If we didn't move up to or past the target, it's because there
+        * weren't enough characters to delete, e.g. the first character
+        * of the line was a tp->offset character, and the user entered
+        * ^D to move to the beginning of a line.  An example of this is:
+        *
+        *      :set ai sw=4<cr>i<space>a<esc>i^T^D
+        *
+        * Otherwise, count up the total spaces/tabs needed to get from the
+        * beginning of the line (or the last non-<blank> character) to the
+        * target.
+        */
+       if (current >= target)
+               spaces = tabs = 0;
+       else {
+               cno = current;
+               tabs = 0;
+               if (!O_ISSET(sp, O_EXPANDTAB)) {
+                       for (; cno + COL_OFF(cno, ts) <= target; ++tabs)
+                               cno += COL_OFF(cno, ts);
+               }
+               spaces = target - cno;
+       }
+
+       tp->ai = tabs + spaces;
+
+       /*
+        * Call txt_insch() to insert each character, so that we get the
+        * correct effect when we add a <tab> to replace N <spaces>.
+        */
+       for (ch = '\t'; tabs > 0; --tabs)
+               (void)txt_insch(sp, tp, &ch, 0);
+       for (ch = ' '; spaces > 0; --spaces)
+               (void)txt_insch(sp, tp, &ch, 0);
+       return (0);
+}
+
+/*
+ * txt_fc --
+ *     File name completion.
+ */
+static int
+txt_fc(SCR *sp, TEXT *tp, int *redrawp)
+{
+       struct stat sb;
+       ARGS **argv;
+       CHAR_T s_ch;
+       EXCMD cmd;
+       size_t indx, len, nlen, off;
+       int argc, trydir;
+       CHAR_T *p, *t;
+       const char *np;
+       size_t nplen;
+
+       trydir = 0;
+       *redrawp = 0;
+
+       /*
+        * Find the beginning of this "word" -- if we're at the beginning
+        * of the line, it's a special case.
+        */
+       if (tp->cno == 1) {
+               len = 0;
+               p = tp->lb;
+       } else
+retry:         for (len = 0,
+                   off = tp->cno - 1, p = tp->lb + off;; --off, --p) {
+                       if (ISBLANK((UCHAR_T)*p)) {
+                               ++p;
+                               break;
+                       }
+                       ++len;
+                       if (off == tp->ai || off == tp->offset)
+                               break;
+               }
+
+       /*
+        * Get enough space for a wildcard character.
+        *
+        * XXX
+        * This won't work for "foo\", since the \ will escape the expansion
+        * character.  I'm not sure if that's a bug or not...
+        */
+       off = p - tp->lb;
+       BINC_RETW(sp, tp->lb, tp->lb_len, tp->len + 1);
+       p = tp->lb + off;
+
+       s_ch = p[len];
+       p[len] = '*';
+
+       /* Build an ex command, and call the ex expansion routines. */
+       ex_cinit(sp, &cmd, 0, 0, OOBLNO, OOBLNO, 0);
+       if (argv_exp2(sp, &cmd, p, len + 1)) {
+               p[len] = s_ch;
+               return (0);
+       }
+       argc = cmd.argc;
+       argv = cmd.argv;
+
+       p[len] = s_ch;
+
+       switch (argc) {
+       case 0:                         /* No matches. */
+               if (!trydir)
+                       (void)sp->gp->scr_bell(sp);
+               return (0);
+       case 1:                         /* One match. */
+               /* If something changed, do the exchange. */
+               nlen = STRLEN(cmd.argv[0]->bp);
+               if (len != nlen || MEMCMP(cmd.argv[0]->bp, p, len))
+                       break;
+
+               /* If haven't done a directory test, do it now. */
+               INT2CHAR(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
+                        np, nplen);
+               if (!trydir &&
+                   !stat(np, &sb) && S_ISDIR(sb.st_mode)) {
+                       p += len;
+                       goto isdir;
+               }
+
+               /* If nothing changed, period, ring the bell. */
+               if (!trydir)
+                       (void)sp->gp->scr_bell(sp);
+               return (0);
+       default:                        /* Multiple matches. */
+               *redrawp = 1;
+               if (txt_fc_col(sp, argc, argv))
+                       return (1);
+
+               /* Find the length of the shortest match. */
+               for (nlen = cmd.argv[0]->len; --argc > 0;) {
+                       if (cmd.argv[argc]->len < nlen)
+                               nlen = cmd.argv[argc]->len;
+                       for (indx = 0; indx < nlen &&
+                           cmd.argv[argc]->bp[indx] == cmd.argv[0]->bp[indx];
+                           ++indx);
+                       nlen = indx;
+               }
+               break;
+       }
+
+       /* Overwrite the expanded text first. */
+       for (t = cmd.argv[0]->bp; len > 0 && nlen > 0; --len, --nlen)
+               *p++ = *t++;
+
+       /* If lost text, make the remaining old text overwrite characters. */
+       if (len) {
+               tp->cno -= len;
+               tp->owrite += len;
+       }
+
+       /* Overwrite any overwrite characters next. */
+       for (; nlen > 0 && tp->owrite > 0; --nlen, --tp->owrite, ++tp->cno)
+               *p++ = *t++;
+
+       /* Shift remaining text up, and move the cursor to the end. */
+       if (nlen) {
+               off = p - tp->lb;
+               BINC_RETW(sp, tp->lb, tp->lb_len, tp->len + nlen);
+               p = tp->lb + off;
+
+               tp->cno += nlen;
+               tp->len += nlen;
+
+               if (tp->insert != 0)
+                       (void)MEMMOVEW(p + nlen, p, tp->insert);
+               while (nlen--)
+                       *p++ = *t++;
+       }
+
+       /* If a single match and it's a directory, retry it. */
+       INT2CHAR(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1, np, nplen);
+       if (argc == 1 && !stat(np, &sb) && S_ISDIR(sb.st_mode)) {
+isdir:         if (tp->owrite == 0) {
+                       off = p - tp->lb;
+                       BINC_RETW(sp, tp->lb, tp->lb_len, tp->len + 1);
+                       p = tp->lb + off;
+                       if (tp->insert != 0)
+                               (void)MEMMOVEW(p + 1, p, tp->insert);
+                       ++tp->len;
+               } else
+                       --tp->owrite;
+
+               ++tp->cno;
+               *p++ = '/';
+
+               trydir = 1;
+               goto retry;
+       }
+       return (0);
+}
+
+/*
+ * txt_fc_col --
+ *     Display file names for file name completion.
+ */
+static int
+txt_fc_col(SCR *sp, int argc, ARGS **argv)
+{
+       ARGS **av;
+       CHAR_T *p;
+       GS *gp;
+       size_t base, cnt, col, colwidth, numrows, numcols, prefix, row;
+       int ac, nf, reset;
+       const char *np;
+       char *pp;
+       size_t nlen;
+
+       gp = sp->gp;
+
+       /* Trim any directory prefix common to all of the files. */
+       INT2CHAR(sp, argv[0]->bp, argv[0]->len + 1, np, nlen);
+       if ((pp = strrchr(np, '/')) == NULL)
+               prefix = 0;
+       else {
+               prefix = (pp - np) + 1;
+               for (ac = argc - 1, av = argv + 1; ac > 0; --ac, ++av)
+                       if (av[0]->len < prefix ||
+                           MEMCMP(av[0]->bp, argv[0]->bp, 
+                                  prefix)) {
+                               prefix = 0;
+                               break;
+                       }
+       }
+
+       /*
+        * Figure out the column width for the longest name.  Output is done on
+        * 6 character "tab" boundaries for no particular reason.  (Since we
+        * don't output tab characters, we ignore the terminal's tab settings.)
+        * Ignore the user's tab setting because we have no idea how reasonable
+        * it is.
+        */
+       for (ac = argc, av = argv, colwidth = 0; ac > 0; --ac, ++av) {
+               for (col = 0, p = av[0]->bp + prefix; *p != '\0'; ++p)
+                       col += KEY_LEN(sp, *p);
+               if (col > colwidth)
+                       colwidth = col;
+       }
+       colwidth += COL_OFF(colwidth, 6);
+
+       /*
+        * Writing to the bottom line of the screen is always turned off when
+        * SC_TINPUT_INFO is set.  Turn it back on, we know what we're doing.
+        */
+       if (F_ISSET(sp, SC_TINPUT_INFO)) {
+               reset = 1;
+               F_CLR(sp, SC_TINPUT_INFO);
+       } else
+               reset = 0;
+
+#define        CHK_INTR                                                        \
+       if (F_ISSET(gp, G_INTERRUPTED))                                 \
+               goto intr;
+
+       /* If the largest file name is too large, just print them. */
+       if (colwidth > sp->cols) {
+               for (ac = argc, av = argv; ac > 0; --ac, ++av) {
+                       INT2CHAR(sp, av[0]->bp+prefix, av[0]->len+1-prefix,
+                                np, nlen);
+                       pp = msg_print(sp, np, &nf);
+                       (void)ex_printf(sp, "%s\n", pp);
+                       if (F_ISSET(gp, G_INTERRUPTED))
+                               break;
+               }
+               if (nf)
+                       FREE_SPACE(sp, pp, 0);
+               CHK_INTR;
+       } else {
+               /* Figure out the number of columns. */
+               numcols = (sp->cols - 1) / colwidth;
+               if ((size_t)argc > numcols) {
+                       numrows = argc / numcols;
+                       if (argc % numcols)
+                               ++numrows;
+               } else
+                       numrows = 1;
+
+               /* Display the files in sorted order. */
+               for (row = 0; row < numrows; ++row) {
+                       for (base = row, col = 0; col < numcols; ++col) {
+                               INT2CHAR(sp, argv[base]->bp+prefix, 
+                                       argv[base]->len+1-prefix, np, nlen);
+                               pp = msg_print(sp, np, &nf);
+                               cnt = ex_printf(sp, "%s", pp);
+                               if (nf)
+                                       FREE_SPACE(sp, pp, 0);
+                               CHK_INTR;
+                               if ((base += numrows) >= (size_t)argc)
+                                       break;
+                               (void)ex_printf(sp,
+                                   "%*s", (int)(colwidth - cnt), "");
+                               CHK_INTR;
+                       }
+                       (void)ex_puts(sp, "\n");
+                       CHK_INTR;
+               }
+               (void)ex_puts(sp, "\n");
+               CHK_INTR;
+       }
+       (void)ex_fflush(sp);
+
+       if (0) {
+intr:          F_CLR(gp, G_INTERRUPTED);
+       }
+       if (reset)
+               F_SET(sp, SC_TINPUT_INFO);
+
+       return (0);
+}
+
+/*
+ * txt_emark --
+ *     Set the end mark on the line.
+ */
+static int
+txt_emark(SCR *sp, TEXT *tp, size_t cno)
+{
+       CHAR_T ch;
+       unsigned char *kp;
+       size_t chlen, nlen, olen;
+       CHAR_T *p;
+
+       ch = CH_ENDMARK;
+
+       /*
+        * The end mark may not be the same size as the current character.
+        * Don't let the line shift.
+        */
+       nlen = KEY_LEN(sp, ch);
+       if (tp->lb[cno] == '\t')
+               (void)vs_columns(sp, tp->lb, tp->lno, &cno, &olen);
+       else
+               olen = KEY_LEN(sp, tp->lb[cno]);
+
+       /*
+        * If the line got longer, well, it's weird, but it's easy.  If
+        * it's the same length, it's easy.  If it got shorter, we have
+        * to fix it up.
+        */
+       if (olen > nlen) {
+               BINC_RETW(sp, tp->lb, tp->lb_len, tp->len + olen);
+               chlen = olen - nlen;
+               if (tp->insert != 0)
+                       MEMMOVEW(tp->lb + cno + 1 + chlen,
+                           tp->lb + cno + 1, tp->insert);
+
+               tp->len += chlen;
+               tp->owrite += chlen;
+               p = tp->lb + cno;
+               if (tp->lb[cno] == '\t')
+                       for (cno += chlen; chlen--;)
+                               *p++ = ' ';
+               else
+                       for (kp = KEY_NAME(sp, tp->lb[cno]),
+                           cno += chlen; chlen--;)
+                               *p++ = *kp++;
+       }
+       tp->lb[cno] = ch;
+       return (vs_change(sp, tp->lno, LINE_RESET));
+}
+
+/*
+ * txt_err --
+ *     Handle an error during input processing.
+ */
+static void
+txt_err(SCR *sp, TEXTH *tiqh)
+{
+       db_recno_t lno;
+
+       /*
+        * The problem with input processing is that the cursor is at an
+        * indeterminate position since some input may have been lost due
+        * to a malloc error.  So, try to go back to the place from which
+        * the cursor started, knowing that it may no longer be available.
+        *
+        * We depend on at least one line number being set in the text
+        * chain.
+        */
+       for (lno = tiqh->cqh_first->lno;
+           !db_exist(sp, lno) && lno > 0; --lno);
+
+       sp->lno = lno == 0 ? 1 : lno;
+       sp->cno = 0;
+
+       /* Redraw the screen, just in case. */
+       F_SET(sp, SC_SCR_REDRAW);
+}
+
+/*
+ * txt_hex --
+ *     Let the user insert any character value they want.
+ *
+ * !!!
+ * This is an extension.  The pattern "^X[0-9a-fA-F]*" is a way
+ * for the user to specify a character value which their keyboard
+ * may not be able to enter.
+ */
+static int
+txt_hex(SCR *sp, TEXT *tp)
+{
+       CHAR_T savec;
+       size_t len, off;
+       long value;
+       CHAR_T *p, *wp;
+
+       /*
+        * Null-terminate the string.  Since nul isn't a legal hex value,
+        * this should be okay, and lets us use a local routine, which
+        * presumably understands the character set, to convert the value.
+        */
+       savec = tp->lb[tp->cno];
+       tp->lb[tp->cno] = 0;
+
+       /* Find the previous CH_HEX character. */
+       for (off = tp->cno - 1, p = tp->lb + off, len = 0;; --p, --off, ++len) {
+               if (*p == CH_HEX) {
+                       wp = p + 1;
+                       break;
+               }
+               /* Not on this line?  Shouldn't happen. */
+               if (off == tp->ai || off == tp->offset)
+                       goto nothex;
+       }
+
+       /* If length of 0, then it wasn't a hex value. */
+       if (len == 0)
+               goto nothex;
+
+       /* Get the value. */
+       errno = 0;
+       value = STRTOL(wp, NULL, 16);
+       if (errno || value < 0 || value > 0xff) {
+nothex:                tp->lb[tp->cno] = savec;
+               return (0);
+       }
+
+       /* Restore the original character. */
+       tp->lb[tp->cno] = savec;
+
+       /* Adjust the bookkeeping. */
+       tp->cno -= len;
+       tp->len -= len;
+       tp->lb[tp->cno - 1] = value;
+
+       /* Copy down any overwrite characters. */
+       if (tp->owrite)
+               MEMMOVEW(tp->lb + tp->cno, tp->lb + tp->cno + len, 
+                   tp->owrite);
+
+       /* Copy down any insert characters. */
+       if (tp->insert)
+               MEMMOVEW(tp->lb + tp->cno + tp->owrite,
+                   tp->lb + tp->cno + tp->owrite + len, 
+                   tp->insert);
+
+       return (0);
+}
+
+/*
+ * txt_insch --
+ *
+ * !!!
+ * Historic vi did a special screen optimization for tab characters.  As an
+ * example, for the keystrokes "iabcd<esc>0C<tab>", the tab overwrote the
+ * rest of the string when it was displayed.
+ *
+ * Because early versions of this implementation redisplayed the entire line
+ * on each keystroke, the "bcd" was pushed to the right as it ignored that
+ * the user had "promised" to change the rest of the characters.  However,
+ * the historic vi implementation had an even worse bug: given the keystrokes
+ * "iabcd<esc>0R<tab><esc>", the "bcd" disappears, and magically reappears
+ * on the second <esc> key.
+ *
+ * POSIX 1003.2 requires (will require) that this be fixed, specifying that
+ * vi overwrite characters the user has committed to changing, on the basis
+ * of the screen space they require, but that it not overwrite other characters.
+ */
+static int
+txt_insch(SCR *sp, TEXT *tp, ARG_CHAR_T *chp, u_int flags)
+{
+       unsigned char *kp;
+       CHAR_T savech;
+       size_t chlen, cno, copydown, olen, nlen;
+       CHAR_T *p;
+
+       /*
+        * The 'R' command does one-for-one replacement, because there's
+        * no way to know how many characters the user intends to replace.
+        */
+       if (LF_ISSET(TXT_REPLACE)) {
+               if (tp->owrite) {
+                       --tp->owrite;
+                       tp->lb[tp->cno++] = (UCHAR_T)*chp;
+                       return (0);
+               }
+       } else if (tp->owrite) {                /* Overwrite a character. */
+               cno = tp->cno;
+
+               /*
+                * If the old or new characters are tabs, then the length of the
+                * display depends on the character position in the display.  We
+                * don't even try to handle this here, just ask the screen.
+                */
+               if (*chp == '\t') {
+                       savech = tp->lb[cno];
+                       tp->lb[cno] = '\t';
+                       (void)vs_columns(sp, tp->lb, tp->lno, &cno, &nlen);
+                       tp->lb[cno] = savech;
+               } else
+                       nlen = KEY_LEN(sp, *chp);
+
+               /*
+                * Eat overwrite characters until we run out of them or we've
+                * handled the length of the new character.  If we only eat
+                * part of an overwrite character, break it into its component
+                * elements and display the remaining components.
+                */
+               for (copydown = 0; nlen != 0 && tp->owrite != 0;) {
+                       --tp->owrite;
+
+                       if (tp->lb[cno] == '\t')
+                               (void)vs_columns(sp,
+                                   tp->lb, tp->lno, &cno, &olen);
+                       else
+                               olen = KEY_LEN(sp, tp->lb[cno]);
+
+                       if (olen == nlen) {
+                               nlen = 0;
+                               break;
+                       }
+                       if (olen < nlen) {
+                               ++copydown;
+                               nlen -= olen;
+                       } else {
+                               BINC_RETW(sp,
+                                   tp->lb, tp->lb_len, tp->len + olen);
+                               chlen = olen - nlen;
+                               MEMMOVEW(tp->lb + cno + 1 + chlen,
+                                   tp->lb + cno + 1, 
+                                   tp->owrite + tp->insert);
+
+                               tp->len += chlen;
+                               tp->owrite += chlen;
+                               if (tp->lb[cno] == '\t')
+                                       for (p = tp->lb + cno + 1; chlen--;)
+                                               *p++ = ' ';
+                               else
+                                       for (kp =
+                                           KEY_NAME(sp, tp->lb[cno]) + nlen,
+                                           p = tp->lb + cno + 1; chlen--;)
+                                               *p++ = *kp++;
+                               nlen = 0;
+                               break;
+                       }
+               }
+
+               /*
+                * If had to erase several characters, we adjust the total
+                * count, and if there are any characters left, shift them
+                * into position.
+                */
+               if (copydown != 0 && (tp->len -= copydown) != 0)
+                       MEMMOVEW(tp->lb + cno, tp->lb + cno + copydown,
+                           tp->owrite + tp->insert + copydown);
+
+               /* If we had enough overwrite characters, we're done. */
+               if (nlen == 0) {
+                       tp->lb[tp->cno++] = (UCHAR_T)*chp;
+                       return (0);
+               }
+       }
+
+       /* Check to see if the character fits into the input buffer. */
+       BINC_RETW(sp, tp->lb, tp->lb_len, tp->len + 1);
+
+       ++tp->len;
+       if (tp->insert) {                       /* Insert a character. */
+               if (tp->insert == 1)
+                       tp->lb[tp->cno + 1] = tp->lb[tp->cno];
+               else
+                       MEMMOVEW(tp->lb + tp->cno + 1,
+                           tp->lb + tp->cno, tp->owrite + tp->insert);
+       }
+       tp->lb[tp->cno++] = (UCHAR_T)*chp;
+       return (0);
+}
+
+/*
+ * txt_isrch --
+ *     Do an incremental search.
+ */
+static int
+txt_isrch(SCR *sp, VICMD *vp, TEXT *tp, u_int8_t *is_flagsp)
+{
+       MARK start;
+       db_recno_t lno;
+       u_int sf;
+
+       /* If it's a one-line screen, we don't do incrementals. */
+       if (IS_ONELINE(sp)) {
+               FL_CLR(*is_flagsp, IS_RUNNING);
+               return (0);
+       }
+
+       /*
+        * If the user erases back to the beginning of the buffer, there's
+        * nothing to search for.  Reset the cursor to the starting point.
+        */
+       if (tp->cno <= 1) {
+               vp->m_final = vp->m_start;
+               return (0);
+       }
+
+       /*
+        * If it's an RE quote character, and not quoted, ignore it until
+        * we get another character.
+        */
+       if (tp->lb[tp->cno - 1] == '\\' &&
+           (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\'))
+               return (0);
+
+       /*
+        * If it's a magic shell character, and not quoted, reset the cursor
+        * to the starting point.
+        */
+       if (strchr(O_STR(sp, O_SHELLMETA), tp->lb[tp->cno - 1]) != NULL &&
+           (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\'))
+               vp->m_final = vp->m_start;
+
+       /*
+        * If we see the search pattern termination character, then quit doing
+        * an incremental search.  There may be more, e.g., ":/foo/;/bar/",
+        * and we can't handle that incrementally.  Also, reset the cursor to
+        * the original location, the ex search routines don't know anything
+        * about incremental searches.
+        */
+       if (tp->lb[0] == tp->lb[tp->cno - 1] &&
+           (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\')) {
+               vp->m_final = vp->m_start;
+               FL_CLR(*is_flagsp, IS_RUNNING);
+               return (0);
+       }
+               
+       /*
+        * Remember the input line and discard the special input map,
+        * but don't overwrite the input line on the screen.
+        */
+       lno = tp->lno;
+       F_SET(VIP(sp), VIP_S_MODELINE);
+       F_CLR(sp, SC_TINPUT | SC_TINPUT_INFO);
+       if (txt_map_end(sp))
+               return (1);
+
+       /*
+        * Specify a starting point and search.  If we find a match, move to
+        * it and refresh the screen.  If we didn't find the match, then we
+        * beep the screen.  When searching from the original cursor position, 
+        * we have to move the cursor, otherwise, we don't want to move the
+        * cursor in case the text at the current position continues to match.
+        */
+       if (FL_ISSET(*is_flagsp, IS_RESTART)) {
+               start = vp->m_start;
+               sf = SEARCH_SET;
+       } else {
+               start = vp->m_final;
+               sf = SEARCH_INCR | SEARCH_SET;
+       }
+
+       if (tp->lb[0] == '/' ?
+           !f_search(sp,
+           &start, &vp->m_final, tp->lb + 1, tp->cno - 1, NULL, sf) :
+           !b_search(sp,
+           &start, &vp->m_final, tp->lb + 1, tp->cno - 1, NULL, sf)) {
+               sp->lno = vp->m_final.lno;
+               sp->cno = vp->m_final.cno;
+               FL_CLR(*is_flagsp, IS_RESTART);
+
+               if (!KEYS_WAITING(sp) && vs_refresh(sp, 0))
+                       return (1);
+       } else
+               FL_SET(*is_flagsp, IS_RESTART);
+
+       /* Reinstantiate the special input map. */
+       if (txt_map_init(sp))
+               return (1);
+       F_CLR(VIP(sp), VIP_S_MODELINE);
+       F_SET(sp, SC_TINPUT | SC_TINPUT_INFO);
+
+       /* Reset the line number of the input line. */
+       tp->lno = TMAP[0].lno; 
+
+       /*
+        * If the colon command-line moved, i.e. the screen scrolled,
+        * refresh the input line.
+        *
+        * XXX
+        * We shouldn't be calling vs_line, here -- we need dirty bits
+        * on entries in the SMAP array.
+        */
+       if (lno != TMAP[0].lno) {
+               if (vs_line(sp, &TMAP[0], NULL, NULL))
+                       return (1);
+               (void)sp->gp->scr_refresh(sp, 0);
+       }
+       return (0);
+}
+
+/*
+ * txt_resolve --
+ *     Resolve the input text chain into the file.
+ */
+static int
+txt_resolve(SCR *sp, TEXTH *tiqh, u_int32_t flags)
+{
+       VI_PRIVATE *vip;
+       TEXT *tp;
+       db_recno_t lno;
+       int changed;
+
+       /*
+        * The first line replaces a current line, and all subsequent lines
+        * are appended into the file.  Resolve autoindented characters for
+        * each line before committing it.  If the latter causes the line to
+        * change, we have to redisplay it, otherwise the information cached
+        * about the line will be wrong.
+        */
+       vip = VIP(sp);
+       tp = tiqh->cqh_first;
+
+       if (LF_ISSET(TXT_AUTOINDENT))
+               txt_ai_resolve(sp, tp, &changed);
+       else
+               changed = 0;
+       if (db_set(sp, tp->lno, tp->lb, tp->len) ||
+           (changed && vs_change(sp, tp->lno, LINE_RESET)))
+               return (1);
+
+       for (lno = tp->lno; (tp = tp->q.cqe_next) != (void *)&sp->tiq; ++lno) {
+               if (LF_ISSET(TXT_AUTOINDENT))
+                       txt_ai_resolve(sp, tp, &changed);
+               else
+                       changed = 0;
+               if (db_append(sp, 0, lno, tp->lb, tp->len) ||
+                   (changed && vs_change(sp, tp->lno, LINE_RESET)))
+                       return (1);
+       }
+
+       /*
+        * Clear the input flag, the look-aside buffer is no longer valid.
+        * Has to be done as part of text resolution, or upon return we'll
+        * be looking at incorrect data.
+        */
+       F_CLR(sp, SC_TINPUT);
+
+       return (0);
+}
+
+/*
+ * txt_showmatch --
+ *     Show a character match.
+ *
+ * !!!
+ * Historic vi tried to display matches even in the :colon command line.
+ * I think not.
+ */
+static int
+txt_showmatch(SCR *sp, TEXT *tp)
+{
+       GS *gp;
+       VCS cs;
+       MARK m;
+       int cnt, endc, startc;
+
+       gp = sp->gp;
+
+       /*
+        * Do a refresh first, in case we haven't done one in awhile,
+        * so the user can see what we're complaining about.
+        */
+       UPDATE_POSITION(sp, tp);
+       if (vs_refresh(sp, 1))
+               return (1);
+
+       /*
+        * We don't display the match if it's not on the screen.  Find
+        * out what the first character on the screen is.
+        */
+       if (vs_sm_position(sp, &m, 0, P_TOP))
+               return (1);
+
+       /* Initialize the getc() interface. */
+       cs.cs_lno = tp->lno;
+       cs.cs_cno = tp->cno - 1;
+       if (cs_init(sp, &cs))
+               return (1);
+       startc = (endc = cs.cs_ch)  == ')' ? '(' : '{';
+
+       /* Search for the match. */
+       for (cnt = 1;;) {
+               if (cs_prev(sp, &cs))
+                       return (1);
+               if (cs.cs_flags != 0) {
+                       if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF) {
+                               msgq(sp, M_BERR,
+                                   "Unmatched %s", KEY_NAME(sp, endc));
+                               return (0);
+                       }
+                       continue;
+               }
+               if (cs.cs_ch == endc)
+                       ++cnt;
+               else if (cs.cs_ch == startc && --cnt == 0)
+                       break;
+       }
+
+       /* If the match is on the screen, move to it. */
+       if (cs.cs_lno < m.lno || (cs.cs_lno == m.lno && cs.cs_cno < m.cno))
+               return (0);
+       sp->lno = cs.cs_lno;
+       sp->cno = cs.cs_cno;
+       if (vs_refresh(sp, 1))
+               return (1);
+
+       /* Wait for timeout or character arrival. */
+       return (v_event_get(sp,
+           NULL, O_VAL(sp, O_MATCHTIME) * 100, EC_TIMEOUT));
+}
+
+/*
+ * txt_margin --
+ *     Handle margin wrap.
+ */
+static int
+txt_margin(SCR *sp, TEXT *tp, TEXT *wmtp, int *didbreak, u_int32_t flags)
+{
+       VI_PRIVATE *vip;
+       size_t len, off;
+       CHAR_T *p, *wp;
+
+       /* Find the nearest previous blank. */
+       for (off = tp->cno - 1, p = tp->lb + off, len = 0;; --off, --p, ++len) {
+               if (ISBLANK((UCHAR_T)*p)) {
+                       wp = p + 1;
+                       break;
+               }
+
+               /*
+                * If reach the start of the line, there's nowhere to break.
+                *
+                * !!!
+                * Historic vi belled each time a character was entered after
+                * crossing the margin until a space was entered which could
+                * be used to break the line.  I don't as it tends to wake the
+                * cats.
+                */
+               if (off == tp->ai || off == tp->offset) {
+                       *didbreak = 0;
+                       return (0);
+               }
+       }
+
+       /*
+        * Store saved information about the rest of the line in the
+        * wrapmargin TEXT structure.
+        *
+        * !!!
+        * The offset field holds the length of the current characters
+        * that the user entered, but which are getting split to the new
+        * line -- it's going to be used to set the cursor value when we
+        * move to the new line.
+        */
+       vip = VIP(sp);
+       wmtp->lb = p + 1;
+       wmtp->offset = len;
+       wmtp->insert = LF_ISSET(TXT_APPENDEOL) ?  tp->insert - 1 : tp->insert;
+       wmtp->owrite = tp->owrite;
+
+       /* Correct current bookkeeping information. */
+       tp->cno -= len;
+       if (LF_ISSET(TXT_APPENDEOL)) {
+               tp->len -= len + tp->owrite + (tp->insert - 1);
+               tp->insert = 1;
+       } else {
+               tp->len -= len + tp->owrite + tp->insert;
+               tp->insert = 0;
+       }
+       tp->owrite = 0;
+
+       /*
+        * !!!
+        * Delete any trailing whitespace from the current line.
+        */
+       for (;; --p, --off) {
+               if (!ISBLANK((UCHAR_T)*p))
+                       break;
+               --tp->cno;
+               --tp->len;
+               if (off == tp->ai || off == tp->offset)
+                       break;
+       }
+       *didbreak = 1;
+       return (0);
+}
+
+/*
+ * txt_Rresolve --
+ *     Resolve the input line for the 'R' command.
+ */
+static void
+txt_Rresolve(SCR *sp, TEXTH *tiqh, TEXT *tp, const size_t orig_len)
+{
+       TEXT *ttp;
+       size_t input_len, retain;
+       CHAR_T *p;
+
+       /*
+        * Check to make sure that the cursor hasn't moved beyond
+        * the end of the line.
+        */
+       if (tp->owrite == 0)
+               return;
+
+       /*
+        * Calculate how many characters the user has entered,
+        * plus the blanks erased by <carriage-return>/<newline>s.
+        */
+       for (ttp = tiqh->cqh_first, input_len = 0;;) {
+               input_len += ttp == tp ? tp->cno : ttp->len + ttp->R_erase;
+               if ((ttp = ttp->q.cqe_next) == (void *)&sp->tiq)
+                       break;
+       }
+
+       /*
+        * If the user has entered less characters than the original line
+        * was long, restore any overwriteable characters to the original
+        * characters.  These characters are entered as "insert characters",
+        * because they're after the cursor and we don't want to lose them.
+        * (This is okay because the R command has no insert characters.)
+        * We set owrite to 0 so that the insert characters don't get copied
+        * to somewhere else, which means that the line and the length have
+        * to be adjusted here as well.
+        *
+        * We have to retrieve the original line because the original pinned
+        * page has long since been discarded.  If it doesn't exist, that's
+        * okay, the user just extended the file.
+        */
+       if (input_len < orig_len) {
+               retain = MIN(tp->owrite, orig_len - input_len);
+               if (db_get(sp,
+                   tiqh->cqh_first->lno, DBG_FATAL | DBG_NOCACHE, &p, NULL))
+                       return;
+               MEMCPYW(tp->lb + tp->cno, p + input_len, retain);
+               tp->len -= tp->owrite - retain;
+               tp->owrite = 0;
+               tp->insert += retain;
+       }
+}
+
+/*
+ * txt_nomorech --
+ *     No more characters message.
+ */
+static void
+txt_nomorech(SCR *sp)
+{
+       msgq(sp, M_BERR, "194|No more characters to erase");
+}
diff --git a/dist/nvi/vi/v_ulcase.c b/dist/nvi/vi/v_ulcase.c
new file mode 100644 (file)
index 0000000..870eef8
--- /dev/null
@@ -0,0 +1,173 @@
+/*     $NetBSD: v_ulcase.c,v 1.3 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_ulcase.c,v 10.11 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int ulcase __P((SCR *, db_recno_t, CHAR_T *, size_t, size_t, size_t));
+
+/*
+ * v_ulcase -- [count]~
+ *     Toggle upper & lower case letters.
+ *
+ * !!!
+ * Historic vi didn't permit ~ to cross newline boundaries.  I can
+ * think of no reason why it shouldn't, which at least lets the user
+ * auto-repeat through a paragraph.
+ *
+ * !!!
+ * In historic vi, the count was ignored.  It would have been better
+ * if there had been an associated motion, but it's too late to make
+ * that the default now.
+ *
+ * PUBLIC: int v_ulcase __P((SCR *, VICMD *));
+ */
+int
+v_ulcase(SCR *sp, VICMD *vp)
+{
+       db_recno_t lno;
+       size_t cno, lcnt, len;
+       u_long cnt;
+       CHAR_T *p;
+
+       lno = vp->m_start.lno;
+       cno = vp->m_start.cno;
+
+       for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt > 0; cno = 0) {
+               /* SOF is an error, EOF is an infinite count sink. */
+               if (db_get(sp, lno, 0, &p, &len)) {
+                       if (lno == 1) {
+                               v_emsg(sp, NULL, VIM_EMPTY);
+                               return (1);
+                       }
+                       --lno;
+                       break;
+               }
+
+               /* Empty lines decrement the count by one. */
+               if (len == 0) {
+                       --cnt;
+                       vp->m_final.cno = 0;
+                       continue;
+               }
+
+               if (cno + cnt >= len) {
+                       lcnt = len - 1;
+                       cnt -= len - cno;
+
+                       vp->m_final.cno = len - 1;
+               } else {
+                       lcnt = cno + cnt - 1;
+                       cnt = 0;
+
+                       vp->m_final.cno = lcnt + 1;
+               }
+
+               if (ulcase(sp, lno, p, len, cno, lcnt))
+                       return (1);
+
+               if (cnt > 0)
+                       ++lno;
+       }
+
+       vp->m_final.lno = lno;
+       return (0);
+}
+
+/*
+ * v_mulcase -- [count]~[count]motion
+ *     Toggle upper & lower case letters over a range.
+ *
+ * PUBLIC: int v_mulcase __P((SCR *, VICMD *));
+ */
+int
+v_mulcase(SCR *sp, VICMD *vp)
+{
+       CHAR_T *p;
+       size_t len;
+       db_recno_t lno;
+
+       for (lno = vp->m_start.lno;;) {
+               if (db_get(sp, lno, DBG_FATAL, &p, &len))
+                       return (1);
+               if (len != 0 && ulcase(sp, lno, p, len,
+                   lno == vp->m_start.lno ? vp->m_start.cno : 0,
+                   !F_ISSET(vp, VM_LMODE) &&
+                   lno == vp->m_stop.lno ? vp->m_stop.cno : len))
+                       return (1);
+
+               if (++lno > vp->m_stop.lno)
+                       break;
+       }
+
+       /*
+        * XXX
+        * I didn't create a new motion command when I added motion semantics
+        * for ~.  While that's the correct way to do it, that choice would
+        * have required changes all over the vi directory for little gain.
+        * Instead, we pretend it's a yank command.  Note, this means that we
+        * follow the cursor motion rules for yank commands, but that seems
+        * reasonable to me.
+        */
+       return (0);
+}
+
+/*
+ * ulcase --
+ *     Change part of a line's case.
+ */
+static int
+ulcase(SCR *sp, db_recno_t lno, CHAR_T *lp, size_t len, size_t scno, size_t ecno)
+{
+       size_t blen;
+       int change, rval;
+       ARG_CHAR_T ch;
+       CHAR_T *p, *t, *bp;
+
+       GET_SPACE_RETW(sp, bp, blen, len);
+       MEMMOVEW(bp, lp, len);
+
+       change = rval = 0;
+       for (p = bp + scno, t = bp + ecno + 1; p < t; ++p) {
+               ch = (UCHAR_T)*p;
+               if (ISLOWER(ch)) {
+                       *p = TOUPPER(ch);
+                       change = 1;
+               } else if (ISUPPER(ch)) {
+                       *p = TOLOWER(ch);
+                       change = 1;
+               }
+       }
+
+       if (change && db_set(sp, lno, bp, len))
+               rval = 1;
+
+       FREE_SPACEW(sp, bp, blen);
+       return (rval);
+}
diff --git a/dist/nvi/vi/v_undo.c b/dist/nvi/vi/v_undo.c
new file mode 100644 (file)
index 0000000..ff958c0
--- /dev/null
@@ -0,0 +1,137 @@
+/*     $NetBSD: v_undo.c,v 1.1.1.2 2008/05/18 14:31:47 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_undo.c,v 10.6 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_Undo -- U
+ *     Undo changes to this line.
+ *
+ * PUBLIC: int v_Undo __P((SCR *, VICMD *));
+ */
+int
+v_Undo(SCR *sp, VICMD *vp)
+{
+       /*
+        * Historically, U reset the cursor to the first column in the line
+        * (not the first non-blank).  This seems a bit non-intuitive, but,
+        * considering that we may have undone multiple changes, anything
+        * else (including the cursor position stored in the logging records)
+        * is going to appear random.
+        */
+       vp->m_final.cno = 0;
+
+       /*
+        * !!!
+        * Set up the flags so that an immediately subsequent 'u' will roll
+        * forward, instead of backward.  In historic vi, a 'u' following a
+        * 'U' redid all of the changes to the line.  Given that the user has
+        * explicitly discarded those changes by entering 'U', it seems likely
+        * that the user wants something between the original and end forms of
+        * the line, so starting to replay the changes seems the best way to
+        * get to there.
+        */
+       F_SET(sp->ep, F_UNDO);
+       sp->ep->lundo = BACKWARD;
+
+       return (log_setline(sp));
+}
+
+/*
+ * v_undo -- u
+ *     Undo the last change.
+ *
+ * PUBLIC: int v_undo __P((SCR *, VICMD *));
+ */
+int
+v_undo(SCR *sp, VICMD *vp)
+{
+       EXF *ep;
+
+       /* Set the command count. */
+       VIP(sp)->u_ccnt = sp->ccnt;
+
+       /*
+        * !!!
+        * In historic vi, 'u' toggled between "undo" and "redo", i.e. 'u'
+        * undid the last undo.  However, if there has been a change since
+        * the last undo/redo, we always do an undo.  To make this work when
+        * the user can undo multiple operations, we leave the old semantic
+        * unchanged, but make '.' after a 'u' do another undo/redo operation.
+        * This has two problems.
+        *
+        * The first is that 'u' didn't set '.' in historic vi.  So, if a
+        * user made a change, realized it was in the wrong place, does a
+        * 'u' to undo it, moves to the right place and then does '.', the
+        * change was reapplied.  To make this work, we only apply the '.'
+        * to the undo command if it's the command immediately following an
+        * undo command.  See vi/vi.c:getcmd() for the details.
+        *
+        * The second is that the traditional way to view the numbered cut
+        * buffers in vi was to enter the commands "1pu.u.u.u. which will
+        * no longer work because the '.' immediately follows the 'u' command.
+        * Since we provide a much better method of viewing buffers, and
+        * nobody can think of a better way of adding in multiple undo, this
+        * remains broken.
+        *
+        * !!!
+        * There is change to historic practice for the final cursor position
+        * in this implementation.  In historic vi, if an undo was isolated to
+        * a single line, the cursor moved to the start of the change, and
+        * then, subsequent 'u' commands would not move it again. (It has been
+        * pointed out that users used multiple undo commands to get the cursor
+        * to the start of the changed text.)  Nvi toggles between the cursor
+        * position before and after the change was made.  One final issue is
+        * that historic vi only did this if the user had not moved off of the
+        * line before entering the undo command; otherwise, vi would move the
+        * cursor to the most attractive position on the changed line.
+        *
+        * It would be difficult to match historic practice in this area. You
+        * not only have to know that the changes were isolated to one line,
+        * but whether it was the first or second undo command as well.  And,
+        * to completely match historic practice, we'd have to track users line
+        * changes, too.  This isn't worth the effort.
+        */
+       ep = sp->ep;
+       if (!F_ISSET(ep, F_UNDO)) {
+               F_SET(ep, F_UNDO);
+               ep->lundo = BACKWARD;
+       } else if (!F_ISSET(vp, VC_ISDOT))
+               ep->lundo = ep->lundo == BACKWARD ? FORWARD : BACKWARD;
+
+       switch (ep->lundo) {
+       case BACKWARD:
+               return (log_backward(sp, &vp->m_final));
+       case FORWARD:
+               return (log_forward(sp, &vp->m_final));
+       default:
+               abort();
+       }
+       /* NOTREACHED */
+}
diff --git a/dist/nvi/vi/v_util.c b/dist/nvi/vi/v_util.c
new file mode 100644 (file)
index 0000000..0335bc9
--- /dev/null
@@ -0,0 +1,169 @@
+/*     $NetBSD: v_util.c,v 1.3 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_util.c,v 10.14 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_eof --
+ *     Vi end-of-file error.
+ *
+ * PUBLIC: void v_eof __P((SCR *, MARK *));
+ */
+void
+v_eof(SCR *sp, MARK *mp)
+{
+       db_recno_t lno;
+
+       if (mp == NULL)
+               v_emsg(sp, NULL, VIM_EOF);
+       else {
+               if (db_last(sp, &lno))
+                       return;
+               if (mp->lno >= lno)
+                       v_emsg(sp, NULL, VIM_EOF);
+               else
+                       msgq(sp, M_BERR, "195|Movement past the end-of-file");
+       }
+}
+
+/*
+ * v_eol --
+ *     Vi end-of-line error.
+ *
+ * PUBLIC: void v_eol __P((SCR *, MARK *));
+ */
+void
+v_eol(SCR *sp, MARK *mp)
+{
+       size_t len;
+
+       if (mp == NULL)
+               v_emsg(sp, NULL, VIM_EOL);
+       else {
+               if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
+                       return;
+               if (mp->cno == len - 1)
+                       v_emsg(sp, NULL, VIM_EOL);
+               else
+                       msgq(sp, M_BERR, "196|Movement past the end-of-line");
+       }
+}
+
+/*
+ * v_nomove --
+ *     Vi no cursor movement error.
+ *
+ * PUBLIC: void v_nomove __P((SCR *));
+ */
+void
+v_nomove(SCR *sp)
+{
+       msgq(sp, M_BERR, "197|No cursor movement made");
+}
+
+/*
+ * v_sof --
+ *     Vi start-of-file error.
+ *
+ * PUBLIC: void v_sof __P((SCR *, MARK *));
+ */
+void
+v_sof(SCR *sp, MARK *mp)
+{
+       if (mp == NULL || mp->lno == 1)
+               msgq(sp, M_BERR, "198|Already at the beginning of the file");
+       else
+               msgq(sp, M_BERR, "199|Movement past the beginning of the file");
+}
+
+/*
+ * v_sol --
+ *     Vi start-of-line error.
+ *
+ * PUBLIC: void v_sol __P((SCR *));
+ */
+void
+v_sol(SCR *sp)
+{
+       msgq(sp, M_BERR, "200|Already in the first column");
+}
+
+/*
+ * v_isempty --
+ *     Return if the line contains nothing but white-space characters.
+ *
+ * PUBLIC: int v_isempty __P((CHAR_T *, size_t));
+ */
+int
+v_isempty(CHAR_T *p, size_t len)
+{
+       for (; len--; ++p)
+               if (!ISBLANK((UCHAR_T)*p))
+                       return (0);
+       return (1);
+}
+
+/*
+ * v_emsg --
+ *     Display a few common vi messages.
+ *
+ * PUBLIC: void v_emsg __P((SCR *, const char *, vim_t));
+ */
+void
+v_emsg(SCR *sp, const char *p, vim_t which)
+{
+       switch (which) {
+       case VIM_COMBUF:
+               msgq(sp, M_ERR,
+                   "201|Buffers should be specified before the command");
+               break;
+       case VIM_EMPTY:
+               msgq(sp, M_BERR, "209|The file is empty");
+               break;
+       case VIM_EOF:
+               msgq(sp, M_BERR, "202|Already at end-of-file");
+               break;
+       case VIM_EOL:
+               msgq(sp, M_BERR, "203|Already at end-of-line");
+               break;
+       case VIM_NOCOM:
+       case VIM_NOCOM_B:
+               msgq(sp,
+                   which == VIM_NOCOM_B ? M_BERR : M_ERR,
+                   "204|%s isn't a vi command", p);
+               break;
+       case VIM_WRESIZE:
+               msgq(sp, M_ERR, "Window resize interrupted text input mode");
+               break;
+       case VIM_USAGE:
+               msgq(sp, M_ERR, "205|Usage: %s", p);
+               break;
+       }
+}
diff --git a/dist/nvi/vi/v_word.c b/dist/nvi/vi/v_word.c
new file mode 100644 (file)
index 0000000..33d4881
--- /dev/null
@@ -0,0 +1,528 @@
+/*     $NetBSD: v_word.c,v 1.3 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_word.c,v 10.6 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * There are two types of "words".  Bigwords are easy -- groups of anything
+ * delimited by whitespace.  Normal words are trickier.  They are either a
+ * group of characters, numbers and underscores, or a group of anything but,
+ * delimited by whitespace.  When for a word, if you're in whitespace, it's
+ * easy, just remove the whitespace and go to the beginning or end of the
+ * word.  Otherwise, figure out if the next character is in a different group.
+ * If it is, go to the beginning or end of that group, otherwise, go to the
+ * beginning or end of the current group.  The historic version of vi didn't
+ * get this right, so, for example, there were cases where "4e" was not the
+ * same as "eeee" -- in particular, single character words, and commands that
+ * began in whitespace were almost always handled incorrectly.  To get it right
+ * you have to resolve the cursor after each search so that the look-ahead to
+ * figure out what type of "word" the cursor is in will be correct.
+ *
+ * Empty lines, and lines that consist of only white-space characters count
+ * as a single word, and the beginning and end of the file counts as an
+ * infinite number of words.
+ *
+ * Movements associated with commands are different than movement commands.
+ * For example, in "abc  def", with the cursor on the 'a', "cw" is from
+ * 'a' to 'c', while "w" is from 'a' to 'd'.  In general, trailing white
+ * space is discarded from the change movement.  Another example is that,
+ * in the same string, a "cw" on any white space character replaces that
+ * single character, and nothing else.  Ain't nothin' in here that's easy.
+ *
+ * One historic note -- in the original vi, the 'w', 'W' and 'B' commands
+ * would treat groups of empty lines as individual words, i.e. the command
+ * would move the cursor to each new empty line.  The 'e' and 'E' commands
+ * would treat groups of empty lines as a single word, i.e. the first use
+ * would move past the group of lines.  The 'b' command would just beep at
+ * you, or, if you did it from the start of the line as part of a motion
+ * command, go absolutely nuts.  If the lines contained only white-space
+ * characters, the 'w' and 'W' commands would just beep at you, and the 'B',
+ * 'b', 'E' and 'e' commands would treat the group as a single word, and
+ * the 'B' and 'b' commands will treat the lines as individual words.  This
+ * implementation treats all of these cases as a single white-space word.
+ */
+
+enum which {BIGWORD, LITTLEWORD};
+
+static int bword __P((SCR *, VICMD *, enum which));
+static int eword __P((SCR *, VICMD *, enum which));
+static int fword __P((SCR *, VICMD *, enum which));
+
+/*
+ * v_wordW -- [count]W
+ *     Move forward a bigword at a time.
+ *
+ * PUBLIC: int v_wordW __P((SCR *, VICMD *));
+ */
+int
+v_wordW(SCR *sp, VICMD *vp)
+{
+       return (fword(sp, vp, BIGWORD));
+}
+
+/*
+ * v_wordw -- [count]w
+ *     Move forward a word at a time.
+ *
+ * PUBLIC: int v_wordw __P((SCR *, VICMD *));
+ */
+int
+v_wordw(SCR *sp, VICMD *vp)
+{
+       return (fword(sp, vp, LITTLEWORD));
+}
+
+/*
+ * fword --
+ *     Move forward by words.
+ */
+static int
+fword(SCR *sp, VICMD *vp, enum which type)
+{
+       enum { INWORD, NOTWORD } state;
+       VCS cs;
+       u_long cnt;
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       cs.cs_lno = vp->m_start.lno;
+       cs.cs_cno = vp->m_start.cno;
+       if (cs_init(sp, &cs))
+               return (1);
+
+       /*
+        * If in white-space:
+        *      If the count is 1, and it's a change command, we're done.
+        *      Else, move to the first non-white-space character, which
+        *      counts as a single word move.  If it's a motion command,
+        *      don't move off the end of the line.
+        */
+       if (cs.cs_flags == CS_EMP || (cs.cs_flags == 0 && ISBLANK2(cs.cs_ch))) {
+               if (ISMOTION(vp) && cs.cs_flags != CS_EMP && cnt == 1) {
+                       if (ISCMD(vp->rkp, 'c'))
+                               return (0);
+                       if (ISCMD(vp->rkp, 'd') || ISCMD(vp->rkp, 'y')) {
+                               if (cs_fspace(sp, &cs))
+                                       return (1);
+                               goto ret;
+                       }
+               }
+               if (cs_fblank(sp, &cs))
+                       return (1);
+               --cnt;
+       }
+
+       /*
+        * Cyclically move to the next word -- this involves skipping
+        * over word characters and then any trailing non-word characters.
+        * Note, for the 'w' command, the definition of a word keeps
+        * switching.
+        */
+       if (type == BIGWORD)
+               while (cnt--) {
+                       for (;;) {
+                               if (cs_next(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_EOF)
+                                       goto ret;
+                               if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                                       break;
+                       }
+                       /*
+                        * If a motion command and we're at the end of the
+                        * last word, we're done.  Delete and yank eat any
+                        * trailing blanks, but we don't move off the end
+                        * of the line regardless.
+                        */
+                       if (cnt == 0 && ISMOTION(vp)) {
+                               if ((ISCMD(vp->rkp, 'd') ||
+                                   ISCMD(vp->rkp, 'y')) &&
+                                   cs_fspace(sp, &cs))
+                                       return (1);
+                               break;
+                       }
+
+                       /* Eat whitespace characters. */
+                       if (cs_fblank(sp, &cs))
+                               return (1);
+                       if (cs.cs_flags == CS_EOF)
+                               goto ret;
+               }
+       else
+               while (cnt--) {
+                       state = cs.cs_flags == 0 &&
+                           inword(cs.cs_ch) ? INWORD : NOTWORD;
+                       for (;;) {
+                               if (cs_next(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_EOF)
+                                       goto ret;
+                               if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                                       break;
+                               if (state == INWORD) {
+                                       if (!inword(cs.cs_ch))
+                                               break;
+                               } else
+                                       if (inword(cs.cs_ch))
+                                               break;
+                       }
+                       /* See comment above. */
+                       if (cnt == 0 && ISMOTION(vp)) {
+                               if ((ISCMD(vp->rkp, 'd') ||
+                                   ISCMD(vp->rkp, 'y')) &&
+                                   cs_fspace(sp, &cs))
+                                       return (1);
+                               break;
+                       }
+
+                       /* Eat whitespace characters. */
+                       if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                               if (cs_fblank(sp, &cs))
+                                       return (1);
+                       if (cs.cs_flags == CS_EOF)
+                               goto ret;
+               }
+
+       /*
+        * If we didn't move, we must be at EOF.
+        *
+        * !!!
+        * That's okay for motion commands, however.
+        */
+ret:   if (!ISMOTION(vp) &&
+           cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
+               v_eof(sp, &vp->m_start);
+               return (1);
+       }
+
+       /* Adjust the end of the range for motion commands. */
+       vp->m_stop.lno = cs.cs_lno;
+       vp->m_stop.cno = cs.cs_cno;
+       if (ISMOTION(vp) && cs.cs_flags == 0)
+               --vp->m_stop.cno;
+
+       /*
+        * Non-motion commands move to the end of the range.  Delete
+        * and yank stay at the start, ignore others.
+        */
+       vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_wordE -- [count]E
+ *     Move forward to the end of the bigword.
+ *
+ * PUBLIC: int v_wordE __P((SCR *, VICMD *));
+ */
+int
+v_wordE(SCR *sp, VICMD *vp)
+{
+       return (eword(sp, vp, BIGWORD));
+}
+
+/*
+ * v_worde -- [count]e
+ *     Move forward to the end of the word.
+ *
+ * PUBLIC: int v_worde __P((SCR *, VICMD *));
+ */
+int
+v_worde(SCR *sp, VICMD *vp)
+{
+       return (eword(sp, vp, LITTLEWORD));
+}
+
+/*
+ * eword --
+ *     Move forward to the end of the word.
+ */
+static int
+eword(SCR *sp, VICMD *vp, enum which type)
+{
+       enum { INWORD, NOTWORD } state;
+       VCS cs;
+       u_long cnt;
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       cs.cs_lno = vp->m_start.lno;
+       cs.cs_cno = vp->m_start.cno;
+       if (cs_init(sp, &cs))
+               return (1);
+
+       /*
+        * !!!
+        * If in whitespace, or the next character is whitespace, move past
+        * it.  (This doesn't count as a word move.)  Stay at the character
+        * past the current one, it sets word "state" for the 'e' command.
+        */
+       if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch)) {
+               if (cs_next(sp, &cs))
+                       return (1);
+               if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch))
+                       goto start;
+       }
+       if (cs_fblank(sp, &cs))
+               return (1);
+
+       /*
+        * Cyclically move to the next word -- this involves skipping
+        * over word characters and then any trailing non-word characters.
+        * Note, for the 'e' command, the definition of a word keeps
+        * switching.
+        */
+start: if (type == BIGWORD)
+               while (cnt--) {
+                       for (;;) {
+                               if (cs_next(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_EOF)
+                                       goto ret;
+                               if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                                       break;
+                       }
+                       /*
+                        * When we reach the start of the word after the last
+                        * word, we're done.  If we changed state, back up one
+                        * to the end of the previous word.
+                        */
+                       if (cnt == 0) {
+                               if (cs.cs_flags == 0 && cs_prev(sp, &cs))
+                                       return (1);
+                               break;
+                       }
+
+                       /* Eat whitespace characters. */
+                       if (cs_fblank(sp, &cs))
+                               return (1);
+                       if (cs.cs_flags == CS_EOF)
+                               goto ret;
+               }
+       else
+               while (cnt--) {
+                       state = cs.cs_flags == 0 &&
+                           inword(cs.cs_ch) ? INWORD : NOTWORD;
+                       for (;;) {
+                               if (cs_next(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_EOF)
+                                       goto ret;
+                               if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                                       break;
+                               if (state == INWORD) {
+                                       if (!inword(cs.cs_ch))
+                                               break;
+                               } else
+                                       if (inword(cs.cs_ch))
+                                               break;
+                       }
+                       /* See comment above. */
+                       if (cnt == 0) {
+                               if (cs.cs_flags == 0 && cs_prev(sp, &cs))
+                                       return (1);
+                               break;
+                       }
+
+                       /* Eat whitespace characters. */
+                       if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                               if (cs_fblank(sp, &cs))
+                                       return (1);
+                       if (cs.cs_flags == CS_EOF)
+                               goto ret;
+               }
+
+       /*
+        * If we didn't move, we must be at EOF.
+        *
+        * !!!
+        * That's okay for motion commands, however.
+        */
+ret:   if (!ISMOTION(vp) &&
+           cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
+               v_eof(sp, &vp->m_start);
+               return (1);
+       }
+
+       /* Set the end of the range for motion commands. */
+       vp->m_stop.lno = cs.cs_lno;
+       vp->m_stop.cno = cs.cs_cno;
+
+       /*
+        * Non-motion commands move to the end of the range.
+        * Delete and yank stay at the start, ignore others.
+        */
+       vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+       return (0);
+}
+
+/*
+ * v_WordB -- [count]B
+ *     Move backward a bigword at a time.
+ *
+ * PUBLIC: int v_wordB __P((SCR *, VICMD *));
+ */
+int
+v_wordB(SCR *sp, VICMD *vp)
+{
+       return (bword(sp, vp, BIGWORD));
+}
+
+/*
+ * v_wordb -- [count]b
+ *     Move backward a word at a time.
+ *
+ * PUBLIC: int v_wordb __P((SCR *, VICMD *));
+ */
+int
+v_wordb(SCR *sp, VICMD *vp)
+{
+       return (bword(sp, vp, LITTLEWORD));
+}
+
+/*
+ * bword --
+ *     Move backward by words.
+ */
+static int
+bword(SCR *sp, VICMD *vp, enum which type)
+{
+       enum { INWORD, NOTWORD } state;
+       VCS cs;
+       u_long cnt;
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       cs.cs_lno = vp->m_start.lno;
+       cs.cs_cno = vp->m_start.cno;
+       if (cs_init(sp, &cs))
+               return (1);
+
+       /*
+        * !!!
+        * If in whitespace, or the previous character is whitespace, move
+        * past it.  (This doesn't count as a word move.)  Stay at the
+        * character before the current one, it sets word "state" for the
+        * 'b' command.
+        */
+       if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch)) {
+               if (cs_prev(sp, &cs))
+                       return (1);
+               if (cs.cs_flags == 0 && !ISBLANK2(cs.cs_ch))
+                       goto start;
+       }
+       if (cs_bblank(sp, &cs))
+               return (1);
+
+       /*
+        * Cyclically move to the beginning of the previous word -- this
+        * involves skipping over word characters and then any trailing
+        * non-word characters.  Note, for the 'b' command, the definition
+        * of a word keeps switching.
+        */
+start: if (type == BIGWORD)
+               while (cnt--) {
+                       for (;;) {
+                               if (cs_prev(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_SOF)
+                                       goto ret;
+                               if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                                       break;
+                       }
+                       /*
+                        * When we reach the end of the word before the last
+                        * word, we're done.  If we changed state, move forward
+                        * one to the end of the next word.
+                        */
+                       if (cnt == 0) {
+                               if (cs.cs_flags == 0 && cs_next(sp, &cs))
+                                       return (1);
+                               break;
+                       }
+
+                       /* Eat whitespace characters. */
+                       if (cs_bblank(sp, &cs))
+                               return (1);
+                       if (cs.cs_flags == CS_SOF)
+                               goto ret;
+               }
+       else
+               while (cnt--) {
+                       state = cs.cs_flags == 0 &&
+                           inword(cs.cs_ch) ? INWORD : NOTWORD;
+                       for (;;) {
+                               if (cs_prev(sp, &cs))
+                                       return (1);
+                               if (cs.cs_flags == CS_SOF)
+                                       goto ret;
+                               if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                                       break;
+                               if (state == INWORD) {
+                                       if (!inword(cs.cs_ch))
+                                               break;
+                               } else
+                                       if (inword(cs.cs_ch))
+                                               break;
+                       }
+                       /* See comment above. */
+                       if (cnt == 0) {
+                               if (cs.cs_flags == 0 && cs_next(sp, &cs))
+                                       return (1);
+                               break;
+                       }
+
+                       /* Eat whitespace characters. */
+                       if (cs.cs_flags != 0 || ISBLANK2(cs.cs_ch))
+                               if (cs_bblank(sp, &cs))
+                                       return (1);
+                       if (cs.cs_flags == CS_SOF)
+                               goto ret;
+               }
+
+       /* If we didn't move, we must be at SOF. */
+ret:   if (cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
+               v_sof(sp, &vp->m_start);
+               return (1);
+       }
+
+       /* Set the end of the range for motion commands. */
+       vp->m_stop.lno = cs.cs_lno;
+       vp->m_stop.cno = cs.cs_cno;
+
+       /*
+        * All commands move to the end of the range.  Motion commands
+        * adjust the starting point to the character before the current
+        * one.
+        *
+        * !!!
+        * The historic vi didn't get this right -- the `yb' command yanked
+        * the right stuff and even updated the cursor value, but the cursor
+        * was not actually updated on the screen.
+        */
+       vp->m_final = vp->m_stop;
+       if (ISMOTION(vp))
+               --vp->m_start.cno;
+       return (0);
+}
diff --git a/dist/nvi/vi/v_xchar.c b/dist/nvi/vi/v_xchar.c
new file mode 100644 (file)
index 0000000..a47ad68
--- /dev/null
@@ -0,0 +1,105 @@
+/*     $NetBSD: v_xchar.c,v 1.1.1.2 2008/05/18 14:31:48 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_xchar.c,v 10.10 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_xchar -- [buffer] [count]x
+ *     Deletes the character(s) on which the cursor sits.
+ *
+ * PUBLIC: int v_xchar __P((SCR *, VICMD *));
+ */
+int
+v_xchar(SCR *sp, VICMD *vp)
+{
+       size_t len;
+       int isempty;
+
+       if (db_eget(sp, vp->m_start.lno, NULL, &len, &isempty)) {
+               if (isempty)
+                       goto nodel;
+               return (1);
+       }
+       if (len == 0) {
+nodel:         msgq(sp, M_BERR, "206|No characters to delete");
+               return (1);
+       }
+
+       /*
+        * Delete from the cursor toward the end of line, w/o moving the
+        * cursor.
+        *
+        * !!!
+        * Note, "2x" at EOL isn't the same as "xx" because the left movement
+        * of the cursor as part of the 'x' command isn't taken into account.
+        * Historically correct.
+        */
+       if (F_ISSET(vp, VC_C1SET))
+               vp->m_stop.cno += vp->count - 1;
+       if (vp->m_stop.cno >= len - 1) {
+               vp->m_stop.cno = len - 1;
+               vp->m_final.cno = vp->m_start.cno ? vp->m_start.cno - 1 : 0;
+       } else
+               vp->m_final.cno = vp->m_start.cno;
+
+       if (cut(sp,
+           F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+           &vp->m_start, &vp->m_stop, 0))
+               return (1);
+       return (del(sp, &vp->m_start, &vp->m_stop, 0));
+}
+
+/*
+ * v_Xchar -- [buffer] [count]X
+ *     Deletes the character(s) immediately before the current cursor
+ *     position.
+ *
+ * PUBLIC: int v_Xchar __P((SCR *, VICMD *));
+ */
+int
+v_Xchar(SCR *sp, VICMD *vp)
+{
+       u_long cnt;
+
+       if (vp->m_start.cno == 0) {
+               v_sol(sp);
+               return (1);
+       }
+
+       cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+       if (cnt >= vp->m_start.cno)
+               vp->m_start.cno = 0;
+       else
+               vp->m_start.cno -= cnt;
+       --vp->m_stop.cno;
+       vp->m_final.cno = vp->m_start.cno;
+
+       if (cut(sp,
+           F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+           &vp->m_start, &vp->m_stop, 0))
+               return (1);
+       return (del(sp, &vp->m_start, &vp->m_stop, 0));
+}
diff --git a/dist/nvi/vi/v_yank.c b/dist/nvi/vi/v_yank.c
new file mode 100644 (file)
index 0000000..19d08cb
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $NetBSD: v_yank.c,v 1.1.1.2 2008/05/18 14:31:48 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_yank.c,v 10.10 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_yank -- [buffer][count]y[count][motion]
+ *          [buffer][count]Y
+ *     Yank text (or lines of text) into a cut buffer.
+ *
+ * !!!
+ * Historic vi moved the cursor to the from MARK if it was before the current
+ * cursor and on a different line, e.g., "yk" moves the cursor but "yj" and
+ * "yl" do not.  Unfortunately, it's too late to change this now.  Matching
+ * the historic semantics isn't easy.  The line number was always changed and
+ * column movement was usually relative.  However, "y'a" moved the cursor to
+ * the first non-blank of the line marked by a, while "y`a" moved the cursor
+ * to the line and column marked by a.  Hopefully, the motion component code
+ * got it right...   Unlike delete, we make no adjustments here.
+ *
+ * PUBLIC: int v_yank __P((SCR *, VICMD *));
+ */
+int
+v_yank(SCR *sp, VICMD *vp)
+{
+       size_t len;
+
+       if (cut(sp,
+           F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start,
+           &vp->m_stop, F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0))
+               return (1);
+       sp->rptlines[L_YANKED] += (vp->m_stop.lno - vp->m_start.lno) + 1;
+
+       /*
+        * One special correction, in case we've deleted the current line or
+        * character.  We check it here instead of checking in every command
+        * that can be a motion component.
+        */
+       if (db_get(sp, vp->m_final.lno, DBG_FATAL, NULL, &len))
+               return (1);
+
+       /*
+        * !!!
+        * Cursor movements, other than those caused by a line mode command
+        * moving to another line, historically reset the relative position.
+        *
+        * This currently matches the check made in v_delete(), I'm hoping
+        * that they should be consistent...
+        */  
+       if (!F_ISSET(vp, VM_LMODE)) {
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(vp, VM_RCM_SET);
+
+               /* Make sure the set cursor position exists. */
+               if (vp->m_final.cno >= len)
+                       vp->m_final.cno = len ? len - 1 : 0;
+       }
+       return (0);
+}
diff --git a/dist/nvi/vi/v_z.c b/dist/nvi/vi/v_z.c
new file mode 100644 (file)
index 0000000..0f9595a
--- /dev/null
@@ -0,0 +1,147 @@
+/*     $NetBSD: v_z.c,v 1.2 2011/11/23 19:18:53 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_z.c,v 10.12 2001/06/25 15:19:36 skimo Exp (Berkeley) Date: 2001/06/25 15:19:36";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_z -- [count]z[count][-.+^<CR>]
+ *     Move the screen.
+ *
+ * PUBLIC: int v_z __P((SCR *, VICMD *));
+ */
+int
+v_z(SCR *sp, VICMD *vp)
+{
+       db_recno_t lno;
+       e_key_t value;
+
+       /*
+        * The first count is the line to use.  If the value doesn't
+        * exist, use the last line.
+        */
+       if (F_ISSET(vp, VC_C1SET)) {
+               lno = vp->count;
+               if (!db_exist(sp, lno) && db_last(sp, &lno))
+                       return (1);
+       } else
+               lno = vp->m_start.lno;
+
+       /* Set default return cursor line. */
+       vp->m_final.lno = lno;
+       vp->m_final.cno = vp->m_start.cno;
+
+       /*
+        * The second count is the displayed window size, i.e. the 'z' command
+        * is another way to get artificially small windows.  Note, you can't
+        * grow beyond the size of the window.
+        *
+        * !!!
+        * A window size of 0 was historically allowed, and simply ignored.
+        * This could be much more simply done by modifying the value of the
+        * O_WINDOW option, but that's not how it worked historically.
+        */
+       if (F_ISSET(vp, VC_C2SET) && vp->count2 != 0) {
+               if (vp->count2 > O_VAL(sp, O_WINDOW))
+                       vp->count2 = O_VAL(sp, O_WINDOW);
+               if (vs_crel(sp, vp->count2))
+                       return (1);
+       }
+
+       switch (vp->character) {
+       case '-':               /* Put the line at the bottom. */
+               if (vs_sm_fill(sp, lno, P_BOTTOM))
+                       return (1);
+               break;
+       case '.':               /* Put the line in the middle. */
+               if (vs_sm_fill(sp, lno, P_MIDDLE))
+                       return (1);
+               break;
+       case '+':
+               /*
+                * If the user specified a line number, put that line at the
+                * top and move the cursor to it.  Otherwise, scroll forward
+                * a screen from the current screen.
+                */
+               if (F_ISSET(vp, VC_C1SET)) {
+                       if (vs_sm_fill(sp, lno, P_TOP))
+                               return (1);
+                       if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
+                               return (1);
+               } else
+                       if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_PLUS))
+                               return (1);
+               break;
+       case '^':
+               /*
+                * If the user specified a line number, put that line at the
+                * bottom, move the cursor to it, and then display the screen
+                * before that one.  Otherwise, scroll backward a screen from
+                * the current screen.
+                *
+                * !!!
+                * Note, we match the off-by-one characteristics of historic
+                * vi, here.
+                */
+               if (F_ISSET(vp, VC_C1SET)) {
+                       if (vs_sm_fill(sp, lno, P_BOTTOM))
+                               return (1);
+                       if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
+                               return (1);
+                       if (vs_sm_fill(sp, vp->m_final.lno, P_BOTTOM))
+                               return (1);
+               } else
+                       if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_CARAT))
+                               return (1);
+               break;
+       default:                /* Put the line at the top for <cr>. */
+               value = KEY_VAL(sp, vp->character);
+               if (value != K_CR && value != K_NL) {
+                       v_emsg(sp, vp->kp->usage, VIM_USAGE);
+                       return (1);
+               }
+               if (vs_sm_fill(sp, lno, P_TOP))
+                       return (1);
+               break;
+       }
+       return (0);
+}
+
+/*
+ * vs_crel --
+ *     Change the relative size of the current screen.
+ *
+ * PUBLIC: int vs_crel __P((SCR *, long));
+ */
+int
+vs_crel(SCR *sp, long int count)
+{
+       sp->t_minrows = sp->t_rows = count;
+       if (sp->t_rows > sp->rows - 1)
+               sp->t_minrows = sp->t_rows = sp->rows - 1;
+       TMAP = HMAP + (sp->t_rows - 1);
+       F_SET(sp, SC_SCR_REDRAW);
+       return (0);
+}
diff --git a/dist/nvi/vi/v_zexit.c b/dist/nvi/vi/v_zexit.c
new file mode 100644 (file)
index 0000000..0277da0
--- /dev/null
@@ -0,0 +1,54 @@
+/*     $NetBSD: v_zexit.c,v 1.1.1.2 2008/05/18 14:31:48 aymeric Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: v_zexit.c,v 10.7 2001/06/25 15:19:37 skimo Exp (Berkeley) Date: 2001/06/25 15:19:37";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_zexit -- ZZ
+ *     Save the file and exit.
+ *
+ * PUBLIC: int v_zexit __P((SCR *, VICMD *));
+ */
+int
+v_zexit(SCR *sp, VICMD *vp)
+{
+       /* Write back any modifications. */
+       if (F_ISSET(sp->ep, F_MODIFIED) &&
+           file_write(sp, NULL, NULL, NULL, FS_ALL))
+               return (1);
+
+       /* Check to make sure it's not a temporary file. */
+       if (file_m3(sp, 0))
+               return (1);
+
+       /* Check for more files to edit. */
+       if (ex_ncheck(sp, 0))
+               return (1);
+
+       F_SET(sp, SC_EXIT);
+       return (0);
+}
diff --git a/dist/nvi/vi/vi.c b/dist/nvi/vi/vi.c
new file mode 100644 (file)
index 0000000..44e6403
--- /dev/null
@@ -0,0 +1,1266 @@
+/*     $NetBSD: vi.c,v 1.4 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vi.c,v 10.73 2002/04/11 19:49:30 skimo Exp (Berkeley) Date: 2002/04/11 19:49:30";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+typedef enum {
+       GC_ERR, GC_ERR_NOFLUSH, GC_EVENT, GC_FATAL, GC_INTERRUPT, GC_OK
+} gcret_t;
+
+static VIKEYS const
+              *v_alias __P((SCR *, VICMD *, VIKEYS const *));
+static gcret_t v_cmd __P((SCR *, VICMD *, VICMD *, VICMD *, int *, int *));
+static int     v_count __P((SCR *, VICMD *, ARG_CHAR_T, u_long *));
+static void    v_dtoh __P((SCR *));
+static int     v_init __P((SCR *));
+static gcret_t v_key __P((SCR *, VICMD *, int, u_int32_t));
+static int     v_motion __P((SCR *, VICMD *, VICMD *, int *));
+
+#if defined(DEBUG) && defined(COMLOG)
+static void    v_comlog __P((SCR *, VICMD *));
+#endif
+
+/*
+ * Side-effect:
+ *     The dot structure can be set by the underlying vi functions,
+ *     see v_Put() and v_put().
+ */
+#define        DOT             (&VIP(sp)->sdot)
+#define        DOTMOTION       (&VIP(sp)->sdotmotion)
+
+/*
+ * vi --
+ *     Main vi command loop.
+ *
+ * PUBLIC: int vi __P((SCR **));
+ */
+int
+vi(SCR **spp)
+{
+       GS *gp;
+       WIN *wp;
+       MARK abst;
+       SCR *next, *sp;
+       VICMD cmd, *vp;
+       VI_PRIVATE *vip;
+       int comcount, mapped, rval;
+
+       /* Get the first screen. */
+       sp = *spp;
+       wp = sp->wp;
+       gp = sp->gp;
+
+       /* Initialize the command structure. */
+       vp = &cmd;
+       memset(vp, 0, sizeof(VICMD));
+
+       /* Reset strange attraction. */
+       F_SET(vp, VM_RCM_SET);
+
+       /* Initialize the vi screen. */
+       if (v_init(sp))
+               return (1);
+
+       /* Set the focus. */
+       (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+       for (vip = VIP(sp), rval = 0;;) {
+               /* Resolve messages. */
+               if (!MAPPED_KEYS_WAITING(sp) && vs_resolve(sp, NULL, 0))
+                       goto ret;
+
+               /*
+                * If not skipping a refresh, return to command mode and
+                * refresh the screen.
+                */
+               if (F_ISSET(vip, VIP_S_REFRESH))
+                       F_CLR(vip, VIP_S_REFRESH);
+               else {
+                       sp->showmode = SM_COMMAND;
+                       if (vs_refresh(sp, 0))
+                               goto ret;
+               }
+
+               /* Set the new favorite position. */
+               if (F_ISSET(vp, VM_RCM_SET | VM_RCM_SETFNB | VM_RCM_SETNNB)) {
+                       F_CLR(vip, VIP_RCM_LAST);
+                       (void)vs_column(sp, &sp->rcm);
+               }
+
+               /*
+                * If not currently in a map, log the cursor position,
+                * and set a flag so that this command can become the
+                * DOT command.
+                */
+               if (MAPPED_KEYS_WAITING(sp))
+                       mapped = 1;
+               else {
+                       if (log_cursor(sp))
+                               goto err;
+                       mapped = 0;
+               }
+
+               /*
+                * There may be an ex command waiting, and we returned here
+                * only because we exited a screen or file.  In this case,
+                * we simply go back into the ex parser.
+                */
+               if (EXCMD_RUNNING(wp)) {
+                       vp->kp = &vikeys[':'];
+                       goto ex_continue;
+               }
+
+               /* Refresh the command structure. */
+               memset(vp, 0, sizeof(VICMD));
+
+               /*
+                * We get a command, which may or may not have an associated
+                * motion.  If it does, we get it too, calling its underlying
+                * function to get the resulting mark.  We then call the
+                * command setting the cursor to the resulting mark.
+                *
+                * !!!
+                * Vi historically flushed mapped characters on error, but
+                * entering extra <escape> characters at the beginning of
+                * a map wasn't considered an error -- in fact, users would
+                * put leading <escape> characters in maps to clean up vi
+                * state before the map was interpreted.  Beauty!
+                */
+               switch (v_cmd(sp, DOT, vp, NULL, &comcount, &mapped)) {
+               case GC_ERR:
+                       goto err;
+               case GC_ERR_NOFLUSH:
+                       goto gc_err_noflush;
+               case GC_FATAL:
+                       goto ret;
+               case GC_INTERRUPT:
+                       goto intr;
+               case GC_EVENT:
+               case GC_OK:
+                       break;
+               }
+
+               /* Check for security setting. */
+               if (F_ISSET(vp->kp, V_SECURE) && O_ISSET(sp, O_SECURE)) {
+                       ex_emsg(sp, (const char *)KEY_NAME(sp, vp->key),
+                           EXM_SECURE);
+                       goto err;
+               }
+
+               /*
+                * Historical practice: if a dot command gets a new count,
+                * any motion component goes away, i.e. "d3w2." deletes a
+                * total of 5 words.
+                */
+               if (F_ISSET(vp, VC_ISDOT) && comcount)
+                       DOTMOTION->count = 1;
+
+               /* Copy the key flags into the local structure. */
+               F_SET(vp, vp->kp->flags);
+
+               /* Prepare to set the previous context. */
+               if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)) {
+                       abst.lno = sp->lno;
+                       abst.cno = sp->cno;
+               }
+
+               /*
+                * Set the three cursor locations to the current cursor.  The
+                * underlying routines don't bother if the cursor doesn't move.
+                * This also handles line commands (e.g. Y) defaulting to the
+                * current line.
+                */
+               vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno;
+               vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno;
+
+               /*
+                * Do any required motion; v_motion sets the from MARK and the
+                * line mode flag, as well as the VM_RCM flags.
+                */
+               if (F_ISSET(vp, V_MOTION) &&
+                   v_motion(sp, DOTMOTION, vp, &mapped)) {
+                       if (INTERRUPTED(sp))
+                               goto intr;
+                       goto err;
+               }
+
+               /*
+                * If a count is set and the command is line oriented, set the
+                * to MARK here relative to the cursor/from MARK.  This is for
+                * commands that take both counts and motions, i.e. "4yy" and
+                * "y%".  As there's no way the command can know which the user
+                * did, we have to do it here.  (There are commands that are
+                * line oriented and that take counts ("#G", "#H"), for which
+                * this calculation is either completely meaningless or wrong.
+                * Each command must validate the value for itself.
+                */
+               if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE))
+                       vp->m_stop.lno += vp->count - 1;
+
+               /* Increment the command count. */
+               ++sp->ccnt;
+
+#if defined(DEBUG) && defined(COMLOG)
+               v_comlog(sp, vp);
+#endif
+               /* Call the function. */
+ex_continue:   if (vp->kp->func(sp, vp))
+                       goto err;
+#ifdef DEBUG
+               /* Make sure no function left the temporary space locked. */
+               if (F_ISSET(wp, W_TMP_INUSE)) {
+                       F_CLR(wp, W_TMP_INUSE);
+                       msgq(sp, M_ERR,
+                           "232|vi: temporary buffer not released");
+               }
+#endif
+               /*
+                * If we're exiting this screen, move to the next one, or, if
+                * there aren't any more, return to the main editor loop.  The
+                * ordering is careful, don't discard the contents of sp until
+                * the end.
+                */
+               if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+                       if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
+                               goto ret;
+                       if (vs_discard(sp, &next))
+                               goto ret;
+                       if (next == NULL && vs_swap(sp, &next, NULL))
+                               goto ret;
+                       *spp = next;
+                       if (screen_end(sp))
+                               goto ret;
+                       if (next == NULL)
+                               break;
+
+                       /* Switch screens, change focus. */
+                       sp = next;
+                       vip = VIP(sp);
+                       (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+                       /* Don't trust the cursor. */
+                       F_SET(vip, VIP_CUR_INVALID);
+
+                       continue;
+               }
+
+               /*
+                * Set the dot command structure.
+                *
+                * !!!
+                * Historically, commands which used mapped keys did not
+                * set the dot command, with the exception of the text
+                * input commands.
+                */
+               if (F_ISSET(vp, V_DOT) && !mapped) {
+                       *DOT = cmd;
+                       F_SET(DOT, VC_ISDOT);
+
+                       /*
+                        * If a count was supplied for both the command and
+                        * its motion, the count was used only for the motion.
+                        * Turn the count back on for the dot structure.
+                        */
+                       if (F_ISSET(vp, VC_C1RESET))
+                               F_SET(DOT, VC_C1SET);
+
+                       /* VM flags aren't retained. */
+                       F_CLR(DOT, VM_COMMASK | VM_RCM_MASK);
+               }
+
+               /*
+                * Some vi row movements are "attracted" to the last position
+                * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET
+                * commands' candle.  If the movement is to the EOL the vi
+                * command handles it.  If it's to the beginning, we handle it
+                * here.
+                *
+                * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB
+                * flag, but do the work themselves.  The reason is that they
+                * have to modify the column in case they're being used as a
+                * motion component.  Other similar commands (e.g. +, -) don't
+                * have to modify the column because they are always line mode
+                * operations when used as motions, so the column number isn't
+                * of any interest.
+                *
+                * Does this totally violate the screen and editor layering?
+                * You betcha.  As they say, if you think you understand it,
+                * you don't.
+                */
+               switch (F_ISSET(vp, VM_RCM_MASK)) {
+               case 0:
+               case VM_RCM_SET:
+                       break;
+               case VM_RCM:
+                       vp->m_final.cno = vs_rcm(sp,
+                           vp->m_final.lno, F_ISSET(vip, VIP_RCM_LAST));
+                       break;
+               case VM_RCM_SETLAST:
+                       F_SET(vip, VIP_RCM_LAST);
+                       break;
+               case VM_RCM_SETFNB:
+                       vp->m_final.cno = 0;
+                       /* FALLTHROUGH */
+               case VM_RCM_SETNNB:
+                       if (nonblank(sp, vp->m_final.lno, &vp->m_final.cno))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+
+               /* Update the cursor. */
+               sp->lno = vp->m_final.lno;
+               sp->cno = vp->m_final.cno;
+
+               /*
+                * Set the absolute mark -- set even if a tags or similar
+                * command, since the tag may be moving to the same file.
+                */
+               if ((F_ISSET(vp, V_ABS) ||
+                   (F_ISSET(vp, V_ABS_L) && sp->lno != abst.lno) ||
+                   (F_ISSET(vp, V_ABS_C) &&
+                   (sp->lno != abst.lno || sp->cno != abst.cno))) &&
+                   mark_set(sp, ABSMARK1, &abst, 1))
+                       goto err;
+
+               if (0) {
+err:                   if (v_event_flush(sp, CH_MAPPED))
+                               msgq(sp, M_BERR,
+                           "110|Vi command failed: mapped keys discarded");
+               }
+
+               /*
+                * Check and clear interrupts.  There's an obvious race, but
+                * it's not worth fixing.
+                */
+gc_err_noflush:        if (INTERRUPTED(sp)) {
+intr:                  CLR_INTERRUPT(sp);
+                       if (v_event_flush(sp, CH_MAPPED))
+                               msgq(sp, M_ERR,
+                                   "231|Interrupted: mapped keys discarded");
+                       else
+                               msgq(sp, M_ERR, "236|Interrupted");
+               }
+
+               /* If the last command switched screens, update. */
+               if (F_ISSET(sp, SC_SSWITCH)) {
+                       F_CLR(sp, SC_SSWITCH);
+
+                       /*
+                        * If the current screen is still displayed, it will
+                        * need a new status line.
+                        */
+                       F_SET(sp, SC_STATUS);
+
+                       /* Switch screens, change focus. */
+                       sp = sp->nextdisp;
+                       vip = VIP(sp);
+                       (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+                       /* Don't trust the cursor. */
+                       F_SET(vip, VIP_CUR_INVALID);
+
+                       /* Refresh so we can display messages. */
+                       if (vs_refresh(sp, 1))
+                               return (1);
+               }
+
+               /* If the last command switched files, change focus. */
+               if (F_ISSET(sp, SC_FSWITCH)) {
+                       F_CLR(sp, SC_FSWITCH);
+                       (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+               }
+
+               /* If leaving vi, return to the main editor loop. */
+               if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_EX)) {
+                       *spp = sp;
+                       v_dtoh(sp);
+                       gp->scr_discard(sp, NULL);
+                       break;
+               }
+       }
+       if (0)
+ret:           rval = 1;
+       return (rval);
+}
+
+#define        KEY(key, ec_flags) {                                            \
+       if ((gcret = v_key(sp, vp, 0, ec_flags)) != GC_OK)              \
+               return (gcret);                                         \
+       if (vp->ev.e_value == K_ESCAPE)                                 \
+               goto esc;                                               \
+       if (FL_ISSET(vp->ev.e_flags, CH_MAPPED))                        \
+               *mappedp = 1;                                           \
+       key = vp->ev.e_c;                                               \
+}
+
+/*
+ * The O_TILDEOP option makes the ~ command take a motion instead
+ * of a straight count.  This is the replacement structure we use
+ * instead of the one currently in the VIKEYS table.
+ *
+ * XXX
+ * This should probably be deleted -- it's not all that useful, and
+ * we get help messages wrong.
+ */
+VIKEYS const tmotion = {
+       v_mulcase,      V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
+       "[count]~[count]motion",
+       " ~ change case to motion"
+};
+
+/*
+ * v_cmd --
+ *     Get a vi command.
+ */
+static gcret_t
+v_cmd(SCR *sp, VICMD *dp, VICMD *vp, VICMD *ismotion, int *comcountp, int *mappedp)
+               
+                      
+                               /* Previous key if getting motion component. */
+                                
+{
+       enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart;
+       ARG_CHAR_T key;
+       VIKEYS const *kp;
+       gcret_t gcret;
+       u_int flags;
+       const char *s;
+
+       /*
+        * Get an event command or a key.  Event commands are simple, and
+        * don't have any additional information.
+        */
+       cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL;
+       gcret = v_key(sp, vp, 1, EC_MAPCOMMAND);
+       if (gcret != GC_OK) {
+               if (gcret != GC_EVENT)
+                       return (gcret);
+               if (v_event(sp, vp))
+                       return (GC_ERR);
+               if (ismotion != NULL && !F_ISSET(vp->kp, V_MOVE))
+                       v_event_err(sp, &vp->ev);
+               return (GC_EVENT);
+       }
+
+       /*
+        * Keys are not simple.  (Although vi's command structure less complex
+        * than ex (and don't think I'm not grateful!)  The command syntax is:
+        *
+        *      [count] [buffer] [count] key [[motion] | [buffer] [character]]
+        *
+        * and there are, of course, several special cases.  The motion value
+        * is itself a vi command, with the syntax:
+        *
+        *      [count] key [character]
+        *
+        * <escape> cancels partial commands, i.e. a command where at least
+        * one non-numeric character has been entered.  Otherwise, it beeps
+        * the terminal.
+        *
+        * !!!
+        * POSIX 1003.2-1992 explicitly disallows cancelling commands where
+        * all that's been entered is a number, requiring that the terminal
+        * be alerted.
+        */
+       if (vp->ev.e_value == K_ESCAPE)
+               goto esc;
+
+       /*
+        * Commands that are mapped are treated differently (e.g., they
+        * don't set the dot command.  Pass that information back.
+        */
+       if (FL_ISSET(vp->ev.e_flags, CH_MAPPED))
+               *mappedp = 1;
+       key = vp->ev.e_c;
+
+       if (ismotion == NULL)
+               cpart = NOTPARTIAL;
+
+       /* Pick up an optional buffer. */
+       if (key == '"') {
+               cpart = ISPARTIAL;
+               if (ismotion != NULL) {
+                       v_emsg(sp, NULL, VIM_COMBUF);
+                       return (GC_ERR);
+               }
+               KEY(vp->buffer, 0);
+               F_SET(vp, VC_BUFFER);
+
+               KEY(key, EC_MAPCOMMAND);
+       }
+
+       /*
+        * Pick up an optional count, where a leading 0 isn't a count, it's
+        * a command.  When a count is specified, the dot command behaves
+        * differently, pass the information back.
+        */
+       if (ISDIGIT(key) && key != '0') {
+               if (v_count(sp, vp, key, &vp->count))
+                       return (GC_ERR);
+
+               F_SET(vp, VC_C1SET);
+               *comcountp = 1;
+
+               KEY(key, EC_MAPCOMMAND);
+       } else
+               *comcountp = 0;
+
+       /* Pick up optional buffer. */
+       if (key == '"') {
+               cpart = ISPARTIAL;
+               if (F_ISSET(vp, VC_BUFFER)) {
+                       msgq(sp, M_ERR, "234|Only one buffer may be specified");
+                       return (GC_ERR);
+               }
+               if (ismotion != NULL) {
+                       v_emsg(sp, NULL, VIM_COMBUF);
+                       return (GC_ERR);
+               }
+               KEY(vp->buffer, 0);
+               F_SET(vp, VC_BUFFER);
+
+               KEY(key, EC_MAPCOMMAND);
+       }
+
+       /* Check for an OOB command key. */
+       cpart = ISPARTIAL;
+       if (key > MAXVIKEY) {
+               v_emsg(sp, (const char *)KEY_NAME(sp, key), VIM_NOCOM);
+               return (GC_ERR);
+       }
+       kp = &vikeys[vp->key = key];
+
+       /*
+        * !!!
+        * Historically, D accepted and then ignored a count.  Match it.
+        */
+       if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) {
+               *comcountp = 0;
+               vp->count = 0;
+               F_CLR(vp, VC_C1SET);
+       }
+
+       /*
+        * There are several commands that we implement as aliases, both
+        * to match historic practice and to ensure consistency.  Check
+        * for command aliases.
+        */
+       if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL)
+               return (GC_ERR);
+
+       /* The tildeop option makes the ~ command take a motion. */
+       if (key == '~' && O_ISSET(sp, O_TILDEOP))
+               kp = &tmotion;
+
+       vp->kp = kp;
+
+       /*
+        * Find the command.  The only legal command with no underlying
+        * function is dot.  It's historic practice that <escape> doesn't
+        * just erase the preceding number, it beeps the terminal as well.
+        * It's a common problem, so just beep the terminal unless verbose
+        * was set.
+        */
+       if (kp->func == NULL) {
+               if (key != '.') {
+                       v_emsg(sp, (const char *)KEY_NAME(sp, key),
+                           vp->ev.e_value == K_ESCAPE ?
+                           VIM_NOCOM_B : VIM_NOCOM);
+                       return (GC_ERR);
+               }
+
+               /* If called for a motion command, stop now. */
+               if (dp == NULL)
+                       goto usage;
+
+               /*
+                * !!!
+                * If a '.' is immediately entered after an undo command, we
+                * replay the log instead of redoing the last command.  This
+                * is necessary because 'u' can't set the dot command -- see
+                * vi/v_undo.c:v_undo for details.
+                */
+               if (VIP(sp)->u_ccnt == sp->ccnt) {
+                       vp->kp = &vikeys['u'];
+                       F_SET(vp, VC_ISDOT);
+                       return (GC_OK);
+               }
+
+               /* Otherwise, a repeatable command must have been executed. */
+               if (!F_ISSET(dp, VC_ISDOT)) {
+                       msgq(sp, M_ERR, "208|No command to repeat");
+                       return (GC_ERR);
+               }
+
+               /* Set new count/buffer, if any, and return. */
+               if (F_ISSET(vp, VC_C1SET)) {
+                       F_SET(dp, VC_C1SET);
+                       dp->count = vp->count;
+               }
+               if (F_ISSET(vp, VC_BUFFER))
+                       dp->buffer = vp->buffer;
+
+               *vp = *dp;
+               return (GC_OK);
+       }
+
+       /* Set the flags based on the command flags. */
+       flags = kp->flags;
+
+       /* Check for illegal count. */
+       if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))
+               goto usage;
+
+       /* Illegal motion command. */
+       if (ismotion == NULL) {
+               /* Illegal buffer. */
+               if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER))
+                       goto usage;
+
+               /* Required buffer. */
+               if (LF_ISSET(V_RBUF)) {
+                       KEY(vp->buffer, 0);
+                       F_SET(vp, VC_BUFFER);
+               }
+       }
+
+       /*
+        * Special case: '[', ']' and 'Z' commands.  Doesn't the fact that
+        * the *single* characters don't mean anything but the *doubled*
+        * characters do, just frost your shorts?
+        */
+       if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {
+               /*
+                * Historically, half entered [[, ]] or Z commands weren't
+                * cancelled by <escape>, the terminal was beeped instead.
+                * POSIX.2-1992 probably didn't notice, and requires that
+                * they be cancelled instead of beeping.  Seems fine to me.
+                *
+                * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular
+                * vi meta-character, and we don't want the user to wait while
+                * we time out a possible mapping.  This *appears* to match
+                * historic vi practice, but with mapping characters, You Just
+                * Never Know.
+                */
+               KEY(key, 0);
+
+               if (vp->key != key) {
+usage:                 if (ismotion == NULL)
+                               s = kp->usage;
+                       else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP))
+                               s = tmotion.usage;
+                       else
+                               s = vikeys[ismotion->key].usage;
+                       v_emsg(sp, s, VIM_USAGE);
+                       return (GC_ERR);
+               }
+       }
+       /* Special case: 'z' command. */
+       if (vp->key == 'z') {
+               KEY(vp->character, 0);
+               if (ISDIGIT(vp->character)) {
+                       if (v_count(sp, vp, vp->character, &vp->count2))
+                               return (GC_ERR);
+                       F_SET(vp, VC_C2SET);
+                       KEY(vp->character, 0);
+               }
+       }
+
+       /*
+        * Commands that have motion components can be doubled to imply the
+        * current line.
+        */
+       if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) {
+               msgq(sp, M_ERR, "210|%s may not be used as a motion command",
+                   KEY_NAME(sp, key));
+               return (GC_ERR);
+       }
+
+       /* Pick up required trailing character. */
+       if (LF_ISSET(V_CHAR))
+               KEY(vp->character, 0);
+
+       /* Get any associated cursor word. */
+       if (F_ISSET(kp, V_KEYW) && v_curword(sp))
+               return (GC_ERR);
+
+       return (GC_OK);
+
+esc:   switch (cpart) {
+       case COMMANDMODE:
+               msgq(sp, M_BERR, "211|Already in command mode");
+               return (GC_ERR_NOFLUSH);
+       case ISPARTIAL:
+               break;
+       case NOTPARTIAL:
+               (void)sp->gp->scr_bell(sp);
+               break;
+       }
+       return (GC_ERR);
+}
+
+/*
+ * v_motion --
+ *
+ * Get resulting motion mark.
+ */
+static int
+v_motion(SCR *sp, VICMD *dm, VICMD *vp, int *mappedp)
+{
+       VICMD motion;
+       gcret_t gcret;
+       size_t len;
+       u_long cnt;
+       u_int flags;
+       int tilde_reset, notused;
+
+       /*
+        * If '.' command, use the dot motion, else get the motion command.
+        * Clear any line motion flags, the subsequent motion isn't always
+        * the same, i.e. "/aaa" may or may not be a line motion.
+        */
+       if (F_ISSET(vp, VC_ISDOT)) {
+               motion = *dm;
+               F_SET(&motion, VC_ISDOT);
+               F_CLR(&motion, VM_COMMASK);
+               gcret = GC_OK;
+       } else {
+               memset(&motion, 0, sizeof(VICMD));
+               gcret = v_cmd(sp, NULL, &motion, vp, &notused, mappedp);
+               if (gcret != GC_OK && gcret != GC_EVENT)
+                       return (1);
+       }
+
+       /*
+        * A count may be provided both to the command and to the motion, in
+        * which case the count is multiplicative.  For example, "3y4y" is the
+        * same as "12yy".  This count is provided to the motion command and
+        * not to the regular function.
+        */
+       cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1;
+       if (F_ISSET(vp, VC_C1SET)) {
+               motion.count *= vp->count;
+               F_SET(&motion, VC_C1SET);
+
+               /*
+                * Set flags to restore the original values of the command
+                * structure so dot commands can change the count values,
+                * e.g. "2dw" "3." deletes a total of five words.
+                */
+               F_CLR(vp, VC_C1SET);
+               F_SET(vp, VC_C1RESET);
+       }
+
+       /*
+        * Some commands can be repeated to indicate the current line.  In
+        * this case, or if the command is a "line command", set the flags
+        * appropriately.  If not a doubled command, run the function to get
+        * the resulting mark.
+        */
+       if (gcret != GC_EVENT && vp->key == motion.key) {
+               F_SET(vp, VM_LDOUBLE | VM_LMODE);
+
+               /* Set the origin of the command. */
+               vp->m_start.lno = sp->lno;
+               vp->m_start.cno = 0;
+
+               /*
+                * Set the end of the command.
+                *
+                * If the current line is missing, i.e. the file is empty,
+                * historic vi permitted a "cc" or "!!" command to insert
+                * text.
+                */
+               vp->m_stop.lno = sp->lno + motion.count - 1;
+               if (db_get(sp, vp->m_stop.lno, 0, NULL, &len)) {
+                       if (vp->m_stop.lno != 1 ||
+                          (vp->key != 'c' && vp->key != '!')) {
+                               v_emsg(sp, NULL, VIM_EMPTY);
+                               return (1);
+                       }
+                       vp->m_stop.cno = 0;
+               } else
+                       vp->m_stop.cno = len ? len - 1 : 0;
+       } else {
+               /*
+                * Motion commands change the underlying movement (*snarl*).
+                * For example, "l" is illegal at the end of a line, but "dl"
+                * is not.  Set flags so the function knows the situation.
+                */
+               motion.rkp = vp->kp;
+
+               /*
+                * XXX
+                * Use yank instead of creating a new motion command, it's a
+                * lot easier for now.
+                */
+               if (vp->kp == &tmotion) {
+                       tilde_reset = 1;
+                       vp->kp = &vikeys['y'];
+               } else
+                       tilde_reset = 0;
+
+               /*
+                * Copy the key flags into the local structure, except for the
+                * RCM flags -- the motion command will set the RCM flags in
+                * the vp structure if necessary.  This means that the motion
+                * command is expected to determine where the cursor ends up!
+                * However, we save off the current RCM mask and restore it if
+                * it no RCM flags are set by the motion command, with a small
+                * modification.
+                *
+                * We replace the VM_RCM_SET flag with the VM_RCM flag.  This
+                * is so that cursor movement doesn't set the relative position
+                * unless the motion command explicitly specified it.  This
+                * appears to match historic practice, but I've never been able
+                * to develop a hard-and-fast rule.
+                */
+               flags = F_ISSET(vp, VM_RCM_MASK);
+               if (LF_ISSET(VM_RCM_SET)) {
+                       LF_SET(VM_RCM);
+                       LF_CLR(VM_RCM_SET);
+               }
+               F_CLR(vp, VM_RCM_MASK);
+               F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK);
+
+               /*
+                * Set the three cursor locations to the current cursor.  This
+                * permits commands like 'j' and 'k', that are line oriented
+                * motions and have special cursor suck semantics when they are
+                * used as standalone commands, to ignore column positioning.
+                */
+               motion.m_final.lno =
+                   motion.m_stop.lno = motion.m_start.lno = sp->lno;
+               motion.m_final.cno =
+                   motion.m_stop.cno = motion.m_start.cno = sp->cno;
+
+               /* Run the function. */
+               if ((motion.kp->func)(sp, &motion))
+                       return (1);
+
+               /*
+                * If the current line is missing, i.e. the file is empty,
+                * historic vi allowed "c<motion>" or "!<motion>" to insert
+                * text.  Otherwise fail -- most motion commands will have
+                * already failed, but some, e.g. G, succeed in empty files.
+                */
+               if (!db_exist(sp, vp->m_stop.lno)) {
+                       if (vp->m_stop.lno != 1 ||
+                          (vp->key != 'c' && vp->key != '!')) {
+                               v_emsg(sp, NULL, VIM_EMPTY);
+                               return (1);
+                       }
+                       vp->m_stop.cno = 0;
+               }
+
+               /*
+                * XXX
+                * See above.
+                */
+               if (tilde_reset)
+                       vp->kp = &tmotion;
+
+               /*
+                * Copy cut buffer, line mode and cursor position information
+                * from the motion command structure, i.e. anything that the
+                * motion command can set for us.  The commands can flag the
+                * movement as a line motion (see v_sentence) as well as set
+                * the VM_RCM_* flags explicitly.
+                */
+               F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK));
+
+               /*
+                * If the motion command set no relative motion flags, use
+                * the (slightly) modified previous values.
+                */
+               if (!F_ISSET(vp, VM_RCM_MASK))
+                       F_SET(vp, flags);
+
+               /*
+                * Commands can change behaviors based on the motion command
+                * used, for example, the ! command repeated the last bang
+                * command if N or n was used as the motion.
+                */
+               vp->rkp = motion.kp;
+
+               /*
+                * Motion commands can reset all of the cursor information.
+                * If the motion is in the reverse direction, switch the
+                * from and to MARK's so that it's in a forward direction.
+                * Motions are from the from MARK to the to MARK (inclusive).
+                */
+               if (motion.m_start.lno > motion.m_stop.lno ||
+                   (motion.m_start.lno == motion.m_stop.lno &&
+                   motion.m_start.cno > motion.m_stop.cno)) {
+                       vp->m_start = motion.m_stop;
+                       vp->m_stop = motion.m_start;
+               } else {
+                       vp->m_start = motion.m_start;
+                       vp->m_stop = motion.m_stop;
+               }
+               vp->m_final = motion.m_final;
+       }
+
+       /*
+        * If the command sets dot, save the motion structure.  The motion
+        * count was changed above and needs to be reset, that's why this
+        * is done here, and not in the calling routine.
+        */
+       if (F_ISSET(vp->kp, V_DOT)) {
+               *dm = motion;
+               dm->count = cnt;
+       }
+       return (0);
+}
+
+/*
+ * v_init --
+ *     Initialize the vi screen.
+ */
+static int
+v_init(SCR *sp)
+{
+       GS *gp;
+       VI_PRIVATE *vip;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+
+       /* Switch into vi. */
+       if (gp->scr_screen(sp, SC_VI))
+               return (1);
+       (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
+
+       F_CLR(sp, SC_EX | SC_SCR_EX);
+       F_SET(sp, SC_VI);
+
+       /*
+        * Initialize screen values.
+        *
+        * Small windows: see vs_refresh(), section 6a.
+        *
+        * Setup:
+        *      t_minrows is the minimum rows to display
+        *      t_maxrows is the maximum rows to display (rows - 1)
+        *      t_rows is the rows currently being displayed
+        */
+       sp->rows = vip->srows = O_VAL(sp, O_LINES);
+       sp->cols = O_VAL(sp, O_COLUMNS);
+       sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW);
+       if (sp->rows != 1) {
+               if (sp->t_rows > sp->rows - 1) {
+                       sp->t_minrows = sp->t_rows = sp->rows - 1;
+                       msgq(sp, M_INFO,
+                           "214|Windows option value is too large, max is %zu",
+                           sp->t_rows);
+               }
+               sp->t_maxrows = sp->rows - 1;
+       } else
+               sp->t_maxrows = 1;
+       sp->roff = sp->coff = 0;
+
+       /* Create a screen map. */
+       CALLOC_RET(sp, HMAP, SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
+       TMAP = HMAP + (sp->t_rows - 1);
+       HMAP->lno = sp->lno;
+       HMAP->coff = 0;
+       HMAP->soff = 1;
+
+       /*
+        * Fill the screen map from scratch -- try and center the line.  That
+        * way if we're starting with a file we've seen before, we'll put the
+        * line in the middle, otherwise, it won't work and we'll end up with
+        * the line at the top.
+        */
+       F_CLR(sp, SC_SCR_TOP);
+       F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER);
+
+       /* Invalidate the cursor. */
+       F_SET(vip, VIP_CUR_INVALID);
+
+       /* Paint the screen image from scratch. */
+       F_SET(vip, VIP_N_EX_PAINT);
+
+       return (0);
+}
+
+/*
+ * v_dtoh --
+ *     Move all but the current screen to the hidden queue.
+ */
+static void
+v_dtoh(SCR *sp)
+{
+       GS *gp;
+       SCR *tsp;
+       WIN *wp;
+       int hidden;
+
+       /* Move all screens to the hidden queue, tossing screen maps. */
+       for (hidden = 0, gp = sp->gp, wp = sp->wp;
+           (tsp = wp->scrq.cqh_first) != (void *)&wp->scrq; ++hidden) {
+               if (_HMAP(tsp) != NULL) {
+                       free(_HMAP(tsp));
+                       _HMAP(tsp) = NULL;
+               }
+               CIRCLEQ_REMOVE(&wp->scrq, tsp, q);
+               CIRCLEQ_INSERT_TAIL(&gp->hq, tsp, q);
+               /* XXXX Change if hidden screens per window */
+               tsp->wp = 0;
+               gp->scr_discard(tsp, NULL);
+       }
+
+       /* Move current screen back to the display queue. */
+       CIRCLEQ_REMOVE(&gp->hq, sp, q);
+       CIRCLEQ_INSERT_TAIL(&wp->scrq, sp, q);
+       sp->wp = wp;
+
+       if (hidden > 1)
+               msgq(sp, M_INFO,
+                   "319|%d screens backgrounded; use :display to list them",
+                   hidden - 1);
+}
+
+/*
+ * v_curword --
+ *     Get the word (or non-word) the cursor is on.
+ *
+ * PUBLIC: int v_curword __P((SCR *));
+ */
+int
+v_curword(SCR *sp)
+{
+       VI_PRIVATE *vip;
+       size_t beg, end, len;
+       int moved, state;
+       CHAR_T *p;
+
+       if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
+               return (1);
+
+       /*
+        * !!!
+        * Historically, tag commands skipped over any leading whitespace
+        * characters.  Make this true in general when using cursor words.
+        * If movement, getting a cursor word implies moving the cursor to
+        * its beginning.  Refresh now.
+        *
+        * !!!
+        * Find the beginning/end of the keyword.  Keywords are currently
+        * used for cursor-word searching and for tags.  Historical vi
+        * only used the word in a tag search from the cursor to the end
+        * of the word, i.e. if the cursor was on the 'b' in " abc ", the
+        * tag was "bc".  For consistency, we make cursor word searches
+        * follow the same rule.
+        */
+       for (moved = 0,
+           beg = sp->cno; beg < len && ISSPACE((UCHAR_T)p[beg]); moved = 1, ++beg);
+       if (beg >= len) {
+               msgq(sp, M_BERR, "212|Cursor not in a word");
+               return (1);
+       }
+       if (moved) {
+               sp->cno = beg;
+               (void)vs_refresh(sp, 0);
+       }
+
+       /* Find the end of the word. */
+       for (state = inword(p[beg]),
+           end = beg; ++end < len && state == inword(p[end]););
+
+       vip = VIP(sp);
+       len = (end - beg);
+       BINC_RETW(sp, vip->keyw, vip->klen, len+1);
+       MEMMOVEW(vip->keyw, p + beg, len);
+       vip->keyw[len] = '\0';                          /* XXX */
+       return (0);
+}
+
+/*
+ * v_alias --
+ *     Check for a command alias.
+ */
+static VIKEYS const *
+v_alias(SCR *sp, VICMD *vp, const VIKEYS *kp)
+{
+       CHAR_T push;
+
+       switch (vp->key) {
+       case 'C':                       /* C -> c$ */
+               push = '$';
+               vp->key = 'c';
+               break;
+       case 'D':                       /* D -> d$ */
+               push = '$';
+               vp->key = 'd';
+               break;
+       case 'S':                       /* S -> c_ */
+               push = '_';
+               vp->key = 'c';
+               break;
+       case 'Y':                       /* Y -> y_ */
+               push = '_';
+               vp->key = 'y';
+               break;
+       default:
+               return (kp);
+       }
+       return (v_event_push(sp,
+           NULL, &push, 1, CH_NOMAP | CH_QUOTED) ? NULL : &vikeys[vp->key]);
+}
+
+/*
+ * v_count --
+ *     Return the next count.
+ */
+static int
+v_count(SCR *sp, VICMD *vp, ARG_CHAR_T fkey, u_long *countp)
+{
+       u_long count, tc;
+
+       vp->ev.e_c = fkey;
+       count = tc = 0;
+       do {
+               /*
+                * XXX
+                * Assume that overflow results in a smaller number.
+                */
+               tc = count * 10 + vp->ev.e_c - '0';
+               if (count > tc) {
+                       /* Toss to the next non-digit. */
+                       do {
+                               if (v_key(sp, vp, 0,
+                                   EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
+                                       return (1);
+                       } while (ISDIGIT(vp->ev.e_c));
+                       msgq(sp, M_ERR,
+                           "235|Number larger than %lu", ULONG_MAX);
+                       return (1);
+               }
+               count = tc;
+               if (v_key(sp, vp, 0, EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
+                       return (1);
+       } while (ISDIGIT(vp->ev.e_c));
+       *countp = count;
+       return (0);
+}
+
+/*
+ * v_key --
+ *     Return the next event.
+ */
+static gcret_t
+v_key(SCR *sp, VICMD *vp, int events_ok, u_int32_t ec_flags)
+{
+       EVENT *evp;
+       u_int32_t quote;
+
+       for (evp = &vp->ev, quote = 0;;) {
+               if (v_event_get(sp, evp, 0, ec_flags | quote))
+                       return (GC_FATAL);
+               quote = 0;
+
+               switch (evp->e_event) {
+               case E_CHARACTER:
+                       /*
+                        * !!!
+                        * Historically, ^V was ignored in the command stream,
+                        * although it had a useful side-effect of interrupting
+                        * mappings.  Adding a quoting bit to the call probably
+                        * extends historic practice, but it feels right.
+                        */
+                       if (evp->e_value == K_VLNEXT) {
+                               quote = EC_QUOTED;
+                               break;
+                       }
+                       return (GC_OK);
+               case E_ERR:
+               case E_EOF:
+                       return (GC_FATAL);
+               case E_INTERRUPT:
+                       /*
+                        * !!!
+                        * Historically, vi beeped on command level interrupts.
+                        *
+                        * Historically, vi exited to ex mode if no file was
+                        * named on the command line, and two interrupts were
+                        * generated in a row.  (I figured you might want to
+                        * know that, just in case there's a quiz later.)
+                        */
+                       (void)sp->gp->scr_bell(sp);
+                       return (GC_INTERRUPT);
+               case E_REPAINT:
+                       if (v_erepaint(sp, evp))
+                               return (GC_FATAL);
+                       break;
+               case E_WRESIZE:
+                       /*
+                        * !!!
+                        * We don't do anything here, just return an error.
+                        * The vi loop will return because of this, and then
+                        * the main loop will realize that we had to restart
+                        * the world and will call the vi loop again.
+                        */
+                       return (GC_ERR);
+               case E_IPCOMMAND:
+                       if (events_ok)
+                               return (GC_EVENT);
+                       /* FALLTHROUGH */
+               default:
+                       v_event_err(sp, evp);
+                       return (GC_ERR);
+               }
+       }
+       /* NOTREACHED */
+}
+
+#if defined(DEBUG) && defined(COMLOG)
+/*
+ * v_comlog --
+ *     Log the contents of the command structure.
+ */
+static void
+v_comlog(sp, vp)
+       SCR *sp;
+       VICMD *vp;
+{
+       vtrace(sp, "vcmd: "WC, vp->key);
+       if (F_ISSET(vp, VC_BUFFER))
+               vtrace(sp, " buffer: "WC, vp->buffer);
+       if (F_ISSET(vp, VC_C1SET))
+               vtrace(sp, " c1: %lu", vp->count);
+       if (F_ISSET(vp, VC_C2SET))
+               vtrace(sp, " c2: %lu", vp->count2);
+       vtrace(sp, " flags: 0x%x\n", vp->flags);
+}
+#endif
diff --git a/dist/nvi/vi/vi.h b/dist/nvi/vi/vi.h
new file mode 100644 (file)
index 0000000..540b006
--- /dev/null
@@ -0,0 +1,387 @@
+/*     $NetBSD: vi.h,v 1.4 2011/03/21 14:53:04 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ *     Id: vi.h,v 10.27 2002/01/19 21:59:07 skimo Exp (Berkeley) Date: 2002/01/19 21:59:07
+ */
+
+/* Definition of a vi "word". */
+#define        inword(ch)      ((ch) == '_' || (ISGRAPH((UCHAR_T)ch) && !ISPUNCT((UCHAR_T)ch)))
+
+typedef struct _vikeys VIKEYS;
+
+/* Structure passed around to functions implementing vi commands. */
+typedef struct _vicmd {
+       ARG_CHAR_T key;                 /* Command key. */
+       ARG_CHAR_T buffer;              /* Buffer. */
+       ARG_CHAR_T character;           /* Character. */
+       u_long  count;                  /* Count. */
+       u_long  count2;                 /* Second count (only used by z). */
+       EVENT   ev;                     /* Associated event. */
+
+#define        ISCMD(p, key)   ((p) == &vikeys[key])
+       VIKEYS const *kp;               /* Command/Motion VIKEYS entry. */
+#define        ISMOTION(vp)    (vp->rkp != NULL && F_ISSET(vp->rkp, V_MOTION))
+       VIKEYS const *rkp;              /* Related C/M VIKEYS entry. */
+
+       /*
+        * Historic vi allowed "dl" when the cursor was on the last column,
+        * deleting the last character, and similarly allowed "dw" when
+        * the cursor was on the last column of the file.  It didn't allow
+        * "dh" when the cursor was on column 1, although these cases are
+        * not strictly analogous.  The point is that some movements would
+        * succeed if they were associated with a motion command, and fail
+        * otherwise.  This is part of the off-by-1 schizophrenia that
+        * plagued vi.  Other examples are that "dfb" deleted everything
+        * up to and including the next 'b' character, while "d/b" deleted
+        * everything up to the next 'b' character.  While this implementation
+        * regularizes the interface to the extent possible, there are many
+        * special cases that can't be fixed.  The special cases are handled
+        * by setting flags per command so that the underlying command and
+        * motion routines know what's really going on.
+        *
+        * The VM_* flags are set in the vikeys array and by the underlying
+        * functions (motion component or command) as well.  For this reason,
+        * the flags in the VICMD and VIKEYS structures live in the same name
+        * space.
+        */
+#define        VM_CMDFAILED    0x00000001      /* Command failed. */
+#define        VM_CUTREQ       0x00000002      /* Always cut into numeric buffers. */
+#define        VM_LDOUBLE      0x00000004      /* Doubled command for line mode. */
+#define        VM_LMODE        0x00000008      /* Motion is line oriented. */
+#define        VM_COMMASK      0x0000000f      /* Mask for VM flags. */
+
+       /*
+        * The VM_RCM_* flags are single usage, i.e. if you set one, you have
+        * to clear the others.
+        */
+#define        VM_RCM          0x00000010      /* Use relative cursor movment (RCM). */
+#define        VM_RCM_SET      0x00000020      /* RCM: set to current position. */
+#define        VM_RCM_SETFNB   0x00000040      /* RCM: set to first non-blank (FNB). */
+#define        VM_RCM_SETLAST  0x00000080      /* RCM: set to last character. */
+#define        VM_RCM_SETNNB   0x00000100      /* RCM: set to next non-blank. */
+#define        VM_RCM_MASK     0x000001f0      /* Mask for RCM flags. */
+
+       /* Flags for the underlying function. */
+#define        VC_BUFFER       0x00000200      /* The buffer was set. */
+#define        VC_C1RESET      0x00000400      /* Reset C1SET flag for dot commands. */
+#define        VC_C1SET        0x00000800      /* Count 1 was set. */
+#define        VC_C2SET        0x00001000      /* Count 2 was set. */
+#define        VC_ISDOT        0x00002000      /* Command was the dot command. */
+       u_int32_t flags;
+
+       /*
+        * There are four cursor locations that we worry about: the initial
+        * cursor position, the start of the range, the end of the range,
+        * and the final cursor position.  The initial cursor position and
+        * the start of the range are both m_start, and are always the same.
+        * All locations are initialized to the starting cursor position by
+        * the main vi routines, and the underlying functions depend on this.
+        *
+        * Commands that can be motion components set the end of the range
+        * cursor position, m_stop.  All commands must set the ending cursor
+        * position, m_final.  The reason that m_stop isn't the same as m_final
+        * is that there are situations where the final position of the cursor
+        * is outside of the cut/delete range (e.g. 'd[[' from the first column
+        * of a line).  The final cursor position often varies based on the
+        * direction of the movement, as well as the command.  The only special
+        * case that the delete code handles is that it will make adjustments
+        * if the final cursor position is deleted.
+        *
+        * The reason for all of this is that the historic vi semantics were
+        * defined command-by-command.  Every function has to roll its own
+        * starting and stopping positions, and adjust them if it's being used
+        * as a motion component.  The general rules are as follows:
+        *
+        *      1: If not a motion component, the final cursor is at the end
+        *         of the range.
+        *      2: If moving backward in the file, delete and yank move the
+        *         final cursor to the end of the range.
+        *      3: If moving forward in the file, delete and yank leave the
+        *         final cursor at the start of the range.
+        *
+        * Usually, if moving backward in the file and it's a motion component,
+        * the starting cursor is decremented by a single character (or, in a
+        * few cases, to the end of the previous line) so that the starting
+        * cursor character isn't cut or deleted.  No cursor adjustment is
+        * needed for moving forward, because the cut/delete routines handle
+        * m_stop inclusively, i.e. the last character in the range is cut or
+        * deleted.  This makes cutting to the EOF/EOL reasonable.
+        *
+        * The 'c', '<', '>', and '!' commands are special cases.  We ignore
+        * the final cursor position for all of them: for 'c', the text input
+        * routines set the cursor to the last character inserted; for '<',
+        * '>' and '!', the underlying ex commands that do the operation will
+        * set the cursor for us, usually to something related to the first
+        * <nonblank>.
+        */
+       MARK     m_start;               /* mark: initial cursor, range start. */
+       MARK     m_stop;                /* mark: range end. */
+       MARK     m_final;               /* mark: final cursor position. */
+} VICMD;
+
+/* Vi command table structure. */
+struct _vikeys {                       /* Underlying function. */
+       int      (*func) __P((SCR *, VICMD *));
+#define        V_ABS           0x00004000      /* Absolute movement, set '' mark. */
+#define        V_ABS_C         0x00008000      /* V_ABS: if the line/column changed. */
+#define        V_ABS_L         0x00010000      /* V_ABS: if the line changed. */
+#define        V_CHAR          0x00020000      /* Character (required, trailing). */
+#define        V_CNT           0x00040000      /* Count (optional, leading). */
+#define        V_DOT           0x00080000      /* On success, sets dot command. */
+#define        V_KEYW          0x00100000      /* Cursor referenced word. */
+#define        V_MOTION        0x00200000      /* Motion (required, trailing). */
+#define        V_MOVE          0x00400000      /* Command defines movement. */
+#define        V_OBUF          0x00800000      /* Buffer (optional, leading). */
+#define        V_RBUF          0x01000000      /* Buffer (required, trailing). */
+#define        V_SECURE        0x02000000      /* Permission denied if O_SECURE set. */
+       u_int32_t flags;
+       const char *usage;              /* Usage line. */
+       const char *help;               /* Help line. */
+};
+#define        MAXVIKEY        126             /* List of vi commands. */
+extern VIKEYS const vikeys[MAXVIKEY + 1];
+extern VIKEYS const tmotion;           /* XXX Hacked ~ command. */
+
+/* Character stream structure, prototypes. */
+typedef struct _vcs {
+       db_recno_t       cs_lno;                /* Line. */
+       size_t   cs_cno;                /* Column. */
+       CHAR_T  *cs_bp;                 /* Buffer. */
+       size_t   cs_len;                /* Length. */
+       ARG_CHAR_T cs_ch;               /* Character. */
+#define        CS_EMP  1                       /* Empty line. */
+#define        CS_EOF  2                       /* End-of-file. */
+#define        CS_EOL  3                       /* End-of-line. */
+#define        CS_SOF  4                       /* Start-of-file. */
+       int      cs_flags;              /* Return flags. */
+} VCS;
+
+int    cs_bblank __P((SCR *, VCS *));
+int    cs_fblank __P((SCR *, VCS *));
+int    cs_fspace __P((SCR *, VCS *));
+int    cs_init __P((SCR *, VCS *));
+int    cs_next __P((SCR *, VCS *));
+int    cs_prev __P((SCR *, VCS *));
+
+/*
+ * We use a single "window" for each set of vi screens.  The model would be
+ * simpler with two windows (one for the text, and one for the modeline)
+ * because scrolling the text window down would work correctly then, not
+ * affecting the mode line.  As it is we have to play games to make it look
+ * right.  The reason for this choice is that it would be difficult for
+ * curses to optimize the movement, i.e. detect that the downward scroll
+ * isn't going to change the modeline, set the scrolling region on the
+ * terminal and only scroll the first part of the text window.
+ *
+ * Structure for mapping lines to the screen.  An SMAP is an array, with one
+ * structure element per screen line, which holds information describing the
+ * physical line which is displayed in the screen line.  The first two fields
+ * (lno and off) are all that are necessary to describe a line.  The rest of
+ * the information is useful to keep information from being re-calculated.
+ *
+ * The SMAP always has an entry for each line of the physical screen, plus a
+ * slot for the colon command line, so there is room to add any screen into
+ * another one at screen exit.
+ *
+ * Lno is the line number.  If doing the historic vi long line folding, soff
+ * is the screen offset into the line.  For example, the pair 2:1 would be
+ * the first screen of line 2, and 2:2 would be the second.  In the case of
+ * long lines, the screen map will tend to be staggered, e.g., 1:1, 1:2, 1:3,
+ * 2:1, 3:1, etc.  If doing left-right scrolling, the coff field is the screen
+ * column offset into the lines, and can take on any value, as it's adjusted
+ * by the user set value O_SIDESCROLL.
+ */
+typedef struct _smap {
+       db_recno_t  lno;        /* 1-N: Physical file line number. */
+       size_t   coff;          /* 0-N: Column offset in the line. */
+       size_t   soff;          /* 1-N: Screen offset in the line. */
+
+                               /* vs_line() cache information. */
+       size_t   c_sboff;       /* 0-N: offset of first character on screen. */
+       size_t   c_eboff;       /* 0-N: offset of  last character on screen. */
+       u_int8_t c_scoff;       /* 0-N: offset into the first character. */
+                               /* 255: no character of line visible. */
+       u_int8_t c_eclen;       /* 1-N: columns from the last character. */
+       u_int8_t c_ecsize;      /* 1-N: size of the last character. */
+} SMAP;
+                               /* Macros to flush/test cached information. */
+#define        SMAP_CACHE(smp)         ((smp)->c_ecsize != 0)
+#define        SMAP_FLUSH(smp)         ((smp)->c_ecsize = 0)
+
+                               /* Character search information. */
+typedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t;
+
+typedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t;
+typedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t;
+
+/* Vi private, per-screen memory. */
+typedef struct _vi_private {
+       VICMD   cmd;            /* Current command, motion. */
+       VICMD   motion;
+
+       /*
+        * !!!
+        * The saved command structure can be modified by the underlying
+        * vi functions, see v_Put() and v_put().
+        */
+       VICMD   sdot;           /* Saved dot, motion command. */
+       VICMD   sdotmotion;
+
+       CHAR_T *keyw;           /* Keyword buffer. */
+       size_t  klen;           /* Keyword length. */
+       size_t  keywlen;        /* Keyword buffer length. */
+
+       CHAR_T  rlast;          /* Last 'r' replacement character. */
+       e_key_t rvalue;         /* Value of last replacement character. */
+
+       EVENT  *rep;            /* Input replay buffer. */
+       size_t  rep_len;        /* Input replay buffer length. */
+       size_t  rep_cnt;        /* Input replay buffer characters. */
+
+       mtype_t mtype;          /* Last displayed message type. */
+       size_t  linecount;      /* 1-N: Output overwrite count. */
+       size_t  lcontinue;      /* 1-N: Output line continue value. */
+       size_t  totalcount;     /* 1-N: Output overwrite count. */
+
+                               /* Busy state. */
+       int     busy_ref;       /* Busy reference count. */
+       int     busy_ch;        /* Busy character. */
+       size_t  busy_fx;        /* Busy character x coordinate. */
+       size_t  busy_oldy;      /* Saved y coordinate. */
+       size_t  busy_oldx;      /* Saved x coordinate. */
+       struct timeval busy_tv; /* Busy timer. */
+
+       MARK    sel;            /* Select start position. */
+
+       char   *ps;             /* Paragraph plus section list. */
+
+       u_long  u_ccnt;         /* Undo command count. */
+
+       CHAR_T  lastckey;       /* Last search character. */
+       cdir_t  csearchdir;     /* Character search direction. */
+
+       SMAP   *h_smap;         /* First slot of the line map. */
+       SMAP   *t_smap;         /* Last slot of the line map. */
+
+       /*
+        * One extra slot is always allocated for the map so that we can use
+        * it to do vi :colon command input; see v_tcmd().
+        */
+       db_recno_t      sv_tm_lno;      /* tcmd: saved TMAP lno field. */
+       size_t  sv_tm_coff;     /* tcmd: saved TMAP coff field. */
+       size_t  sv_tm_soff;     /* tcmd: saved TMAP soff field. */
+       size_t  sv_t_maxrows;   /* tcmd: saved t_maxrows. */
+       size_t  sv_t_minrows;   /* tcmd: saved t_minrows. */
+       size_t  sv_t_rows;      /* tcmd: saved t_rows. */
+#define        SIZE_HMAP(sp)   (VIP(sp)->srows + 1)
+
+       /*
+        * Macros to get to the head/tail of the smap.  If the screen only has
+        * one line, HMAP can be equal to TMAP, so the code has to understand
+        * the off-by-one errors that can result.  If stepping through an SMAP
+        * and operating on each entry, use sp->t_rows as the count of slots,
+        * don't use a loop that compares <= TMAP.
+        */
+#define        _HMAP(sp)       (VIP(sp)->h_smap)
+#define        HMAP            _HMAP(sp)
+#define        _TMAP(sp)       (VIP(sp)->t_smap)
+#define        TMAP            _TMAP(sp)
+
+       db_recno_t      ss_lno; /* 1-N: vi_opt_screens cached line number. */
+       size_t  ss_screens;     /* vi_opt_screens cached return value. */
+#define        VI_SCR_CFLUSH(vip)      vip->ss_lno = OOBLNO
+
+       size_t  srows;          /* 1-N: rows in the terminal/window. */
+       db_recno_t      olno;           /* 1-N: old cursor file line. */
+       size_t  ocno;           /* 0-N: old file cursor column. */
+       size_t  sc_col;         /* 0-N: LOGICAL screen column. */
+       SMAP   *sc_smap;        /* SMAP entry where sc_col occurs. */
+
+#define        VIP_CUR_INVALID 0x0001  /* Cursor position is unknown. */
+#define        VIP_DIVIDER     0x0002  /* Divider line was displayed. */
+#define        VIP_N_EX_PAINT  0x0004  /* Clear and repaint when ex finishes. */
+#define        VIP_N_EX_REDRAW 0x0008  /* Schedule SC_SCR_REDRAW when ex finishes. */
+#define        VIP_N_REFRESH   0x0010  /* Repaint (from SMAP) on the next refresh. */
+#define        VIP_N_RENUMBER  0x0020  /* Renumber screen on the next refresh. */
+#define        VIP_RCM_LAST    0x0040  /* Cursor drawn to the last column. */
+#define        VIP_S_MODELINE  0x0080  /* Skip next modeline refresh. */
+#define        VIP_S_REFRESH   0x0100  /* Skip next refresh. */
+       u_int16_t flags;
+} VI_PRIVATE;
+
+/* Vi private area. */
+#define        VIP(sp) ((VI_PRIVATE *)((sp)->vi_private))
+
+#define        O_NUMBER_FMT    "%7lu "                 /* O_NUMBER format, length. */
+#define        O_NUMBER_LENGTH 8
+#define        SCREEN_COLS(sp)                         /* Screen columns. */   \
+       ((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols))
+
+/*
+ * LASTLINE is the zero-based, last line in the screen.  Note that it is correct
+ * regardless of the changes in the screen to permit text input on the last line
+ * of the screen, or the existence of small screens.
+ */
+#define LASTLINE(sp) \
+       ((sp)->t_maxrows < (sp)->rows ? (sp)->t_maxrows : (sp)->rows - 1)
+
+/*
+ * Small screen (see vs_refresh.c, section 6a) and one-line screen test.
+ * Note, both cannot be true for the same screen.
+ */
+#define        IS_SMALL(sp)    ((sp)->t_minrows != (sp)->t_maxrows)
+#define        IS_ONELINE(sp)  ((sp)->rows == 1)
+
+#define        HALFTEXT(sp)                            /* Half text. */        \
+       ((sp)->t_rows == 1 ? 1 : (sp)->t_rows / 2)
+#define        HALFSCREEN(sp)                          /* Half text screen. */ \
+       ((sp)->t_maxrows == 1 ? 1 : (sp)->t_maxrows / 2)
+
+/*
+ * Next tab offset.
+ *
+ * !!!
+ * There are problems with how the historical vi handled tabs.  For example,
+ * by doing "set ts=3" and building lines that fold, you can get it to step
+ * through tabs as if they were spaces and move inserted characters to new
+ * positions when <esc> is entered.  I believe that nvi does tabs correctly,
+ * but there are some historical incompatibilities.
+ */
+#define        TAB_OFF(c)      COL_OFF((c), O_VAL(sp, O_TABSTOP))
+
+/* If more than one horizontal screen being shown. */
+#define        IS_HSPLIT(sp)                                                   \
+       ((sp)->rows != O_VAL(sp, O_LINES))
+/* If more than one vertical screen being shown. */
+#define        IS_VSPLIT(sp)                                                   \
+       ((sp)->cols != O_VAL(sp, O_COLUMNS))
+/* If more than one screen being shown. */
+#define        IS_SPLIT(sp)                                                    \
+       (IS_HSPLIT(sp) || IS_VSPLIT(sp))
+
+/* Screen adjustment operations. */
+typedef enum { A_DECREASE, A_INCREASE, A_SET } adj_t;
+
+/* Screen position operations. */
+typedef enum { P_BOTTOM, P_FILL, P_MIDDLE, P_TOP } pos_t;
+
+/* Scrolling operations. */
+typedef enum {
+       CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F,
+       CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS
+} scroll_t;
+
+/* Vi common error messages. */
+typedef enum {
+       VIM_COMBUF, VIM_EMPTY, VIM_EOF, VIM_EOL,
+       VIM_NOCOM, VIM_NOCOM_B, VIM_USAGE, VIM_WRESIZE
+} vim_t;
+
+#include "extern.h"
diff --git a/dist/nvi/vi/vs_line.c b/dist/nvi/vi/vs_line.c
new file mode 100644 (file)
index 0000000..1b3467b
--- /dev/null
@@ -0,0 +1,546 @@
+/*     $NetBSD: vs_line.c,v 1.6 2011/11/16 14:24:43 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vs_line.c,v 10.38 2002/01/19 21:59:07 skimo Exp (Berkeley) Date: 2002/01/19 21:59:07";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+#ifdef VISIBLE_TAB_CHARS
+#define        TABCH   '-'
+#else
+#define        TABCH   ' '
+#endif
+
+/*
+ * vs_line --
+ *     Update one line on the screen.
+ *
+ * PUBLIC: int vs_line __P((SCR *, SMAP *, size_t *, size_t *));
+ */
+int
+vs_line(SCR *sp, SMAP *smp, size_t *yp, size_t *xp)
+{
+       unsigned char *kp;
+       GS *gp;
+       SMAP *tsmp;
+       size_t chlen = 0, cno_cnt, cols_per_screen, len, nlen;
+       size_t offset_in_char, offset_in_line, oldx, oldy;
+       size_t scno, skip_cols, skip_screens;
+       int dne, is_cached, is_partial, is_tab, no_draw;
+       int list_tab, list_dollar;
+       CHAR_T *p;
+       CHAR_T *cbp, *ecbp, cbuf[128];
+       ARG_CHAR_T ch = L('\0');
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "vs_line: row %u: line: %u off: %u\n",
+           smp - HMAP, smp->lno, smp->off);
+#endif
+       /*
+        * If ex modifies the screen after ex output is already on the screen,
+        * don't touch it -- we'll get scrolling wrong, at best.
+        */
+       no_draw = 0;
+       if (!F_ISSET(sp, SC_TINPUT_INFO) && VIP(sp)->totalcount > 1)
+               no_draw = 1;
+       if (F_ISSET(sp, SC_SCR_EXWROTE) && (size_t)(smp - HMAP) != LASTLINE(sp))
+               no_draw = 1;
+
+       /*
+        * Assume that, if the cache entry for the line is filled in, the
+        * line is already on the screen, and all we need to do is return
+        * the cursor position.  If the calling routine doesn't need the
+        * cursor position, we can just return.
+        */
+       is_cached = SMAP_CACHE(smp);
+       if (yp == NULL && (is_cached || no_draw))
+               return (0);
+
+       /*
+        * A nasty side effect of this routine is that it returns the screen
+        * position for the "current" character.  Not pretty, but this is the
+        * only routine that really knows what's out there.
+        *
+        * Move to the line.  This routine can be called by vs_sm_position(),
+        * which uses it to fill in the cache entry so it can figure out what
+        * the real contents of the screen are.  Because of this, we have to
+        * return to whereever we started from.
+        */
+       gp = sp->gp;
+       (void)gp->scr_cursor(sp, &oldy, &oldx);
+       (void)gp->scr_move(sp, smp - HMAP, 0);
+
+       /* Get the line. */
+       dne = db_get(sp, smp->lno, 0, &p, &len);
+
+       /*
+        * Special case if we're printing the info/mode line.  Skip printing
+        * the leading number, as well as other minor setup.  The only time
+        * this code paints the mode line is when the user is entering text
+        * for a ":" command, so we can put the code here instead of dealing
+        * with the empty line logic below.  This is a kludge, but it's pretty
+        * much confined to this module.
+        *
+        * Set the number of columns for this screen.
+        * Set the number of chars or screens to skip until a character is to
+        * be displayed.
+        */
+       cols_per_screen = sp->cols;
+       if (O_ISSET(sp, O_LEFTRIGHT)) {
+               skip_screens = 0;
+               skip_cols = smp->coff;
+       } else {
+               skip_screens = smp->soff - 1;
+               skip_cols = skip_screens * cols_per_screen;
+       }
+
+       list_tab = O_ISSET(sp, O_LIST);
+       if (F_ISSET(sp, SC_TINPUT_INFO))
+               list_dollar = 0;
+       else {
+               list_dollar = list_tab;
+
+               /*
+                * If O_NUMBER is set, the line doesn't exist and it's line
+                * number 1, i.e., an empty file, display the line number.
+                *
+                * If O_NUMBER is set, the line exists and the first character
+                * on the screen is the first character in the line, display
+                * the line number.
+                *
+                * !!!
+                * If O_NUMBER set, decrement the number of columns in the
+                * first screen.  DO NOT CHANGE THIS -- IT'S RIGHT!  The
+                * rest of the code expects this to reflect the number of
+                * columns in the first screen, regardless of the number of
+                * columns we're going to skip.
+                */
+               if (O_ISSET(sp, O_NUMBER)) {
+                       cols_per_screen -= O_NUMBER_LENGTH;
+                       if ((!dne || smp->lno == 1) && skip_cols == 0) {
+                               nlen = snprintf((char*)cbuf,
+                                   sizeof(cbuf), O_NUMBER_FMT,
+                                   (unsigned long)smp->lno);
+                               (void)gp->scr_addstr(sp, (char*)cbuf, nlen);
+                       }
+               }
+       }
+
+       /*
+        * Special case non-existent lines and the first line of an empty
+        * file.  In both cases, the cursor position is 0, but corrected
+        * as necessary for the O_NUMBER field, if it was displayed.
+        */
+       if (dne || len == 0) {
+               /* Fill in the cursor. */
+               if (yp != NULL && smp->lno == sp->lno) {
+                       *yp = smp - HMAP;
+                       *xp = sp->cols - cols_per_screen;
+               }
+
+               /* If the line is on the screen, quit. */
+               if (is_cached || no_draw)
+                       goto ret1;
+
+               /* Set line cache information. */
+               smp->c_sboff = smp->c_eboff = 0;
+               smp->c_scoff = smp->c_eclen = 0;
+
+               /*
+                * Lots of special cases for empty lines, but they only apply
+                * if we're displaying the first screen of the line.
+                */
+               if (skip_cols == 0) {
+                       if (dne) {
+                               if (smp->lno == 1) {
+                                       if (list_dollar) {
+                                               ch = L('$');
+                                               goto empty;
+                                       }
+                               } else {
+                                       ch = L('~');
+                                       goto empty;
+                               }
+                       } else
+                               if (list_dollar) {
+                                       ch = L('$');
+empty:                                 (void)gp->scr_addstr(sp,
+                                           (const char *)KEY_NAME(sp, ch),
+                                           KEY_LEN(sp, ch));
+                               }
+               }
+
+               (void)gp->scr_clrtoeol(sp);
+               (void)gp->scr_move(sp, oldy, oldx);
+               return (0);
+       }
+
+       /* If we shortened this line in another screen, the cursor
+        * position may have fallen off.
+        */
+       if (sp->lno == smp->lno && sp->cno >= len)
+           sp->cno = len - 1;
+
+       /*
+        * If we just wrote this or a previous line, we cached the starting
+        * and ending positions of that line.  The way it works is we keep
+        * information about the lines displayed in the SMAP.  If we're
+        * painting the screen in the forward direction, this saves us from
+        * reformatting the physical line for every line on the screen.  This
+        * wins big on binary files with 10K lines.
+        *
+        * Test for the first screen of the line, then the current screen line,
+        * then the line behind us, then do the hard work.  Note, it doesn't
+        * do us any good to have a line in front of us -- it would be really
+        * hard to try and figure out tabs in the reverse direction, i.e. how
+        * many spaces a tab takes up in the reverse direction depends on
+        * what characters preceded it.
+        *
+        * Test for the first screen of the line.
+        */
+       if (skip_cols == 0) {
+               smp->c_sboff = offset_in_line = 0;
+               smp->c_scoff = offset_in_char = 0;
+               p = &p[offset_in_line];
+               goto display;
+       }
+
+       /* Test to see if we've seen this exact line before. */
+       if (is_cached) {
+               offset_in_line = smp->c_sboff;
+               offset_in_char = smp->c_scoff;
+               p = &p[offset_in_line];
+
+               /* Set cols_per_screen to 2nd and later line length. */
+               if (O_ISSET(sp, O_LEFTRIGHT) || skip_cols > cols_per_screen)
+                       cols_per_screen = sp->cols;
+               goto display;
+       }
+
+       /* Test to see if we saw an earlier part of this line before. */
+       if (smp != HMAP &&
+           SMAP_CACHE(tsmp = smp - 1) && tsmp->lno == smp->lno) {
+               if (tsmp->c_eclen != tsmp->c_ecsize) {
+                       offset_in_line = tsmp->c_eboff;
+                       offset_in_char = tsmp->c_eclen;
+               } else {
+                       offset_in_line = tsmp->c_eboff + 1;
+                       offset_in_char = 0;
+               }
+
+               /* Put starting info for this line in the cache. */
+               smp->c_sboff = offset_in_line;
+               smp->c_scoff = offset_in_char;
+               p = &p[offset_in_line];
+
+               /* Set cols_per_screen to 2nd and later line length. */
+               if (O_ISSET(sp, O_LEFTRIGHT) || skip_cols > cols_per_screen)
+                       cols_per_screen = sp->cols;
+               goto display;
+       }
+
+       scno = 0;
+       offset_in_line = 0;
+       offset_in_char = 0;
+
+       /* Do it the hard way, for leftright scrolling screens. */
+       if (O_ISSET(sp, O_LEFTRIGHT)) {
+               for (; offset_in_line < len; ++offset_in_line) {
+                       chlen = (ch = (UCHAR_T)*p++) == L('\t') && !list_tab ?
+                           TAB_OFF(scno) : KEY_COL(sp, ch);
+                       if ((scno += chlen) >= skip_cols)
+                               break;
+               }
+
+               /* Set cols_per_screen to 2nd and later line length. */
+               cols_per_screen = sp->cols;
+
+               /* Put starting info for this line in the cache. */
+               if (offset_in_line >= len) {
+                       smp->c_sboff = offset_in_line;
+                       smp->c_scoff = 255;
+               } else if (scno != skip_cols) {
+                       smp->c_sboff = offset_in_line;
+                       smp->c_scoff =
+                           offset_in_char = chlen - (scno - skip_cols);
+                       --p;
+               } else {
+                       smp->c_sboff = ++offset_in_line;
+                       smp->c_scoff = 0;
+               }
+       }
+
+       /* Do it the hard way, for historic line-folding screens. */
+       else {
+               for (; offset_in_line < len; ++offset_in_line) {
+                       chlen = (ch = (UCHAR_T)*p++) == L('\t') && !list_tab ?
+                           TAB_OFF(scno) : KEY_COL(sp, ch);
+                       if ((scno += chlen) < cols_per_screen)
+                               continue;
+                       scno -= cols_per_screen;
+
+                       /* Set cols_per_screen to 2nd and later line length. */
+                       cols_per_screen = sp->cols;
+
+                       /*
+                        * If crossed the last skipped screen boundary, start
+                        * displaying the characters.
+                        */
+                       if (--skip_screens == 0)
+                               break;
+               }
+
+               /* Put starting info for this line in the cache. */
+               if (scno != 0) {
+                       smp->c_sboff = offset_in_line;
+                       smp->c_scoff = offset_in_char = chlen - scno;
+                       --p;
+               } else {
+                       smp->c_sboff = ++offset_in_line;
+                       smp->c_scoff = 0;
+               }
+       }
+
+display:
+       /*
+        * Set the number of characters to skip before reaching the cursor
+        * character.  Offset by 1 and use 0 as a flag value.  Vs_line is
+        * called repeatedly with a valid pointer to a cursor position.
+        * Don't fill anything in unless it's the right line and the right
+        * character, and the right part of the character...
+        */
+       if (yp == NULL ||
+           smp->lno != sp->lno || sp->cno < offset_in_line ||
+           offset_in_line + cols_per_screen < sp->cno) {
+               cno_cnt = 0;
+               /* If the line is on the screen, quit. */
+               if (is_cached || no_draw)
+                       goto ret1;
+       } else
+               cno_cnt = (sp->cno - offset_in_line) + 1;
+
+       /* This is the loop that actually displays characters. */
+       ecbp = (cbp = cbuf) + sizeof(cbuf)/sizeof(CHAR_T) - 1;
+       for (is_partial = 0, scno = 0;
+           offset_in_line < len; ++offset_in_line, offset_in_char = 0) {
+               if ((ch = (UCHAR_T)*p++) == L('\t') && !list_tab) {
+                       scno += chlen = TAB_OFF(scno) - offset_in_char;
+                       is_tab = 1;
+               } else {
+                       scno += chlen = KEY_COL(sp, ch) - offset_in_char;
+                       is_tab = 0;
+               }
+
+               /*
+                * Only display up to the right-hand column.  Set a flag if
+                * the entire character wasn't displayed for use in setting
+                * the cursor.  If reached the end of the line, set the cache
+                * info for the screen.  Don't worry about there not being
+                * characters to display on the next screen, its lno/off won't
+                * match up in that case.
+                */
+               if (scno >= cols_per_screen) {
+                       if (is_tab == 1) {
+                               chlen -= scno - cols_per_screen;
+                               smp->c_ecsize = smp->c_eclen = chlen;
+                               scno = cols_per_screen;
+                       } else {
+                               smp->c_ecsize = chlen;
+                               chlen -= scno - cols_per_screen;
+                               smp->c_eclen = chlen;
+
+                               if (scno > cols_per_screen)
+                                       is_partial = 1;
+                       }
+                       smp->c_eboff = offset_in_line;
+
+                       /* Terminate the loop. */
+                       offset_in_line = len;
+               }
+
+               /*
+                * If the caller wants the cursor value, and this was the
+                * cursor character, set the value.  There are two ways to
+                * put the cursor on a character -- if it's normal display
+                * mode, it goes on the last column of the character.  If
+                * it's input mode, it goes on the first.  In normal mode,
+                * set the cursor only if the entire character was displayed.
+                */
+               if (cno_cnt &&
+                   --cno_cnt == 0 && (F_ISSET(sp, SC_TINPUT) || !is_partial)) {
+                       *yp = smp - HMAP;
+                       if (F_ISSET(sp, SC_TINPUT))
+                               if (is_partial)
+                                       *xp = scno - smp->c_ecsize;
+                               else
+                                       *xp = scno - chlen;
+                       else
+                               *xp = scno - 1;
+                       if (O_ISSET(sp, O_NUMBER) &&
+                           !F_ISSET(sp, SC_TINPUT_INFO) && skip_cols == 0)
+                               *xp += O_NUMBER_LENGTH;
+
+                       /* If the line is on the screen, quit. */
+                       if (is_cached || no_draw)
+                               goto ret1;
+               }
+
+               /* If the line is on the screen, don't display anything. */
+               if (is_cached || no_draw)
+                       continue;
+
+#define        FLUSH {                                                         \
+       *cbp = '\0';                                                    \
+       (void)gp->scr_waddstr(sp, cbuf, cbp - cbuf);                    \
+       cbp = cbuf;                                                     \
+}
+               /*
+                * Display the character.  We do tab expansion here because
+                * the screen interface doesn't have any way to set the tab
+                * length.  Note, it's theoretically possible for chlen to
+                * be larger than cbuf, if the user set a impossibly large
+                * tabstop.
+                */
+               if (is_tab)
+                       while (chlen--) {
+                               if (cbp >= ecbp)
+                                       FLUSH;
+                               *cbp++ = TABCH;
+                       }
+               else {
+                       if (cbp + chlen >= ecbp)
+                               FLUSH;
+
+                       /* don't display half a wide character */
+                       if (is_partial && CHAR_WIDTH(sp, ch) > 1) {
+                               *cbp++ = ' ';
+                               break;
+                       }
+
+                       /* XXXX this needs some rethinking */
+                       if (INTISWIDE(ch)) {
+                               /* Put a space before non-spacing char. */
+                               if (CHAR_WIDTH(sp, ch) <= 0)
+                                       *cbp++ = L(' ');
+                               *cbp++ = ch;
+                       } else
+                               for (kp = KEY_NAME(sp, ch) + offset_in_char; 
+                                    chlen--;)
+                                       *cbp++ = (u_char)*kp++;
+               }
+       }
+
+       if (scno < cols_per_screen) {
+               /* If didn't paint the whole line, update the cache. */
+               smp->c_ecsize = smp->c_eclen = KEY_LEN(sp, ch);
+               smp->c_eboff = len - 1;
+
+               /*
+                * If not the info/mode line, and O_LIST set, and at the
+                * end of the line, and the line ended on this screen,
+                * add a trailing $.
+                */
+               if (list_dollar) {
+                       ++scno;
+
+                       chlen = KEY_LEN(sp, L('$'));
+                       if (cbp + chlen >= ecbp)
+                               FLUSH;
+                       for (kp = KEY_NAME(sp, L('$')); chlen--;)
+                               *cbp++ = *kp++;
+               }
+
+               /* If still didn't paint the whole line, clear the rest. */
+               if (scno < cols_per_screen)
+                       (void)gp->scr_clrtoeol(sp);
+       }
+
+       /* Flush any buffered characters. */
+       if (cbp > cbuf)
+               FLUSH;
+
+ret1:  (void)gp->scr_move(sp, oldy, oldx);
+       return (0);
+}
+
+/*
+ * vs_number --
+ *     Repaint the numbers on all the lines.
+ *
+ * PUBLIC: int vs_number __P((SCR *));
+ */
+int
+vs_number(SCR *sp)
+{
+       GS *gp;
+       SMAP *smp;
+       VI_PRIVATE *vip;
+       size_t len, oldy, oldx;
+       int exist;
+       char nbuf[10];
+
+       gp = sp->gp;
+       vip = VIP(sp);
+
+       /* No reason to do anything if we're in input mode on the info line. */
+       if (F_ISSET(sp, SC_TINPUT_INFO))
+               return (0);
+
+       /*
+        * Try and avoid getting the last line in the file, by getting the
+        * line after the last line in the screen -- if it exists, we know
+        * we have to to number all the lines in the screen.  Get the one
+        * after the last instead of the last, so that the info line doesn't
+        * fool us.  (The problem is that file_lline will lie, and tell us
+        * that the info line is the last line in the file.) If that test
+        * fails, we have to check each line for existence.
+        */
+       exist = db_exist(sp, TMAP->lno + 1);
+
+       (void)gp->scr_cursor(sp, &oldy, &oldx);
+       for (smp = HMAP; smp <= TMAP; ++smp) {
+               /* Numbers are only displayed for the first screen line. */
+               if (O_ISSET(sp, O_LEFTRIGHT)) {
+                       if (smp->coff != 0)
+                               continue;
+               } else
+                       if (smp->soff != 1)
+                               continue;
+
+               /*
+                * The first line of an empty file gets numbered, otherwise
+                * number any existing line.
+                */
+               if (smp->lno != 1 && !exist && !db_exist(sp, smp->lno))
+                       break;
+
+               (void)gp->scr_move(sp, smp - HMAP, 0);
+               len = snprintf(nbuf, sizeof(nbuf), O_NUMBER_FMT,
+                   (unsigned long)smp->lno);
+               (void)gp->scr_addstr(sp, nbuf, len);
+       }
+       (void)gp->scr_move(sp, oldy, oldx);
+       return (0);
+}
diff --git a/dist/nvi/vi/vs_msg.c b/dist/nvi/vi/vs_msg.c
new file mode 100644 (file)
index 0000000..fb83708
--- /dev/null
@@ -0,0 +1,910 @@
+/*     $NetBSD: vs_msg.c,v 1.5 2012/02/25 00:13:00 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vs_msg.c,v 10.85 2001/07/29 19:07:31 skimo Exp (Berkeley) Date: 2001/07/29 19:07:31";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+typedef enum {
+       SCROLL_W,                       /* User wait. */
+       SCROLL_W_EX,                    /* User wait, or enter : to continue. */
+       SCROLL_W_QUIT                   /* User wait, or enter q to quit. */
+                                       /*
+                                        * SCROLL_W_QUIT has another semantic
+                                        * -- only wait if the screen is full
+                                        */
+} sw_t;
+
+static void    vs_divider __P((SCR *));
+static void    vs_msgsave __P((SCR *, mtype_t, char *, size_t));
+static void    vs_output __P((SCR *, mtype_t, const char *, int));
+static void    vs_scroll __P((SCR *, int *, sw_t));
+static void    vs_wait __P((SCR *, int *, sw_t));
+
+/*
+ * vs_busy --
+ *     Display, update or clear a busy message.
+ *
+ * This routine is the default editor interface for vi busy messages.  It
+ * implements a standard strategy of stealing lines from the bottom of the
+ * vi text screen.  Screens using an alternate method of displaying busy
+ * messages, e.g. X11 clock icons, should set their scr_busy function to the
+ * correct function before calling the main editor routine.
+ *
+ * PUBLIC: void vs_busy __P((SCR *, const char *, busy_t));
+ */
+void
+vs_busy(SCR *sp, const char *msg, busy_t btype)
+{
+       GS *gp;
+       VI_PRIVATE *vip;
+       static const char flagc[] = "|/-\\";
+       struct timeval tv;
+       size_t len, notused;
+       const char *p;
+
+       /* Ex doesn't display busy messages. */
+       if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE))
+               return;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+
+       /*
+        * Most of this routine is to deal with the screen sharing real estate
+        * between the normal edit messages and the busy messages.  Logically,
+        * all that's needed is something that puts up a message, periodically
+        * updates it, and then goes away.
+        */
+       switch (btype) {
+       case BUSY_ON:
+               ++vip->busy_ref;
+               if (vip->totalcount != 0 || vip->busy_ref != 1)
+                       break;
+
+               /* Initialize state for updates. */
+               vip->busy_ch = 0;
+               (void)gettimeofday(&vip->busy_tv, NULL);
+
+               /* Save the current cursor. */
+               (void)gp->scr_cursor(sp, &vip->busy_oldy, &vip->busy_oldx);
+
+               /* Display the busy message. */
+               p = msg_cat(sp, msg, &len);
+               (void)gp->scr_move(sp, LASTLINE(sp), 0);
+               (void)gp->scr_addstr(sp, p, len);
+               (void)gp->scr_cursor(sp, &notused, &vip->busy_fx);
+               (void)gp->scr_clrtoeol(sp);
+               (void)gp->scr_move(sp, LASTLINE(sp), vip->busy_fx);
+               break;
+       case BUSY_OFF:
+               if (vip->busy_ref == 0)
+                       break;
+               --vip->busy_ref;
+
+               /*
+                * If the line isn't in use for another purpose, clear it.
+                * Always return to the original position.
+                */
+               if (vip->totalcount == 0 && vip->busy_ref == 0) {
+                       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+                       (void)gp->scr_clrtoeol(sp);
+               }
+               (void)gp->scr_move(sp, vip->busy_oldy, vip->busy_oldx);
+               break;
+       case BUSY_UPDATE:
+               if (vip->totalcount != 0 || vip->busy_ref == 0)
+                       break;
+
+               /* Update no more than every 1/8 of a second. */
+               (void)gettimeofday(&tv, NULL);
+               if (((tv.tv_sec - vip->busy_tv.tv_sec) * 1000000 +
+                   (tv.tv_usec - vip->busy_tv.tv_usec)) < 125000)
+                       return;
+               vip->busy_tv = tv;
+
+               /* Display the update. */
+               if (vip->busy_ch == sizeof(flagc) - 1)
+                       vip->busy_ch = 0;
+               (void)gp->scr_move(sp, LASTLINE(sp), vip->busy_fx);
+               (void)gp->scr_addstr(sp, flagc + vip->busy_ch++, 1);
+               (void)gp->scr_move(sp, LASTLINE(sp), vip->busy_fx);
+               break;
+       }
+       (void)gp->scr_refresh(sp, 0);
+}
+
+/* 
+ * vs_home --
+ *     Home the cursor to the bottom row, left-most column.
+ *
+ * PUBLIC: void vs_home __P((SCR *));
+ */
+void
+vs_home(SCR *sp)
+{
+       (void)sp->gp->scr_move(sp, LASTLINE(sp), 0);
+       (void)sp->gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_update --
+ *     Update a command.
+ *
+ * PUBLIC: void vs_update __P((SCR *, const char *, const CHAR_T *));
+ */
+void
+vs_update(SCR *sp, const char *m1, const CHAR_T *m2)
+{
+       GS *gp;
+       size_t len, mlen, oldx, oldy;
+       const char *np;
+       size_t nlen;
+
+       gp = sp->gp;
+
+       /*
+        * This routine displays a message on the bottom line of the screen,
+        * without updating any of the command structures that would keep it
+        * there for any period of time, i.e. it is overwritten immediately.
+        *
+        * It's used by the ex read and ! commands when the user's command is
+        * expanded, and by the ex substitution confirmation prompt.
+        */
+       if (F_ISSET(sp, SC_SCR_EXWROTE)) {
+               if (m2 != NULL)
+                       INT2CHAR(sp, m2, STRLEN(m2) + 1, np, nlen);
+               (void)ex_printf(sp,
+                   "%s%s\n", m1 == NULL? "" : m1, m2 == NULL ? "" : np);
+               (void)ex_fflush(sp);
+       }
+
+       /*
+        * Save the cursor position, the substitute-with-confirmation code
+        * will have already set it correctly.
+        */
+       (void)gp->scr_cursor(sp, &oldy, &oldx);
+
+       /* Clear the bottom line. */
+       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+       (void)gp->scr_clrtoeol(sp);
+
+       /*
+        * XXX
+        * Don't let long file names screw up the screen.
+        */
+       if (m1 != NULL) {
+               mlen = len = strlen(m1);
+               if (len > sp->cols - 2)
+                       mlen = len = sp->cols - 2;
+               (void)gp->scr_addstr(sp, m1, mlen);
+       } else
+               len = 0;
+       if (m2 != NULL) {
+               mlen = STRLEN(m2);
+               if (len + mlen > sp->cols - 2)
+                       mlen = (sp->cols - 2) - len;
+               (void)gp->scr_waddstr(sp, m2, mlen);
+       }
+
+       (void)gp->scr_move(sp, oldy, oldx);
+       (void)gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_msg --
+ *     Display ex output or error messages for the screen.
+ *
+ * This routine is the default editor interface for all ex output, and all ex
+ * and vi error/informational messages.  It implements the standard strategy
+ * of stealing lines from the bottom of the vi text screen.  Screens using an
+ * alternate method of displaying messages, e.g. dialog boxes, should set their
+ * scr_msg function to the correct function before calling the editor.
+ *
+ * PUBLIC: void vs_msg __P((SCR *, mtype_t, char *, size_t));
+ */
+void
+vs_msg(SCR *sp, mtype_t mtype, char *line, size_t len)
+{
+       GS *gp;
+       VI_PRIVATE *vip;
+       size_t maxcols, oldx, oldy, padding;
+       const char *e, *s, *t;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+
+       /*
+        * Ring the bell if it's scheduled.
+        *
+        * XXX
+        * Shouldn't we save this, too?
+        */
+       if (F_ISSET(sp, SC_TINPUT_INFO) || F_ISSET(gp, G_BELLSCHED)) {
+               if (F_ISSET(sp, SC_SCR_VI)) {
+                       F_CLR(gp, G_BELLSCHED);
+                       (void)gp->scr_bell(sp);
+               } else
+                       F_SET(gp, G_BELLSCHED);
+       }
+
+       /*
+        * If vi is using the error line for text input, there's no screen
+        * real-estate for the error message.  Nothing to do without some
+        * information as to how important the error message is.
+        */
+       if (F_ISSET(sp, SC_TINPUT_INFO))
+               return;
+
+       /*
+        * Ex or ex controlled screen output.
+        *
+        * If output happens during startup, e.g., a .exrc file, we may be
+        * in ex mode but haven't initialized the screen.  Initialize here,
+        * and in this case, stay in ex mode.
+        *
+        * If the SC_SCR_EXWROTE bit is set, then we're switching back and
+        * forth between ex and vi, but the screen is trashed and we have
+        * to respect that.  Switch to ex mode long enough to put out the
+        * message.
+        *
+        * If the SC_EX_WAIT_NO bit is set, turn it off -- we're writing to
+        * the screen, so previous opinions are ignored.
+        */
+       if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) {
+               if (!F_ISSET(sp, SC_SCR_EX)) {
+                       if (F_ISSET(sp, SC_SCR_EXWROTE)) {
+                               if (sp->gp->scr_screen(sp, SC_EX))
+                                       return;
+                       } else
+                               if (ex_init(sp))
+                                       return;
+               }
+
+               if (mtype == M_ERR)
+                       (void)gp->scr_attr(sp, SA_INVERSE, 1);
+               (void)printf("%.*s", (int)len, line);
+               if (mtype == M_ERR)
+                       (void)gp->scr_attr(sp, SA_INVERSE, 0);
+               (void)fflush(stdout);
+
+               F_CLR(sp, SC_EX_WAIT_NO);
+
+               if (!F_ISSET(sp, SC_SCR_EX))
+                       (void)sp->gp->scr_screen(sp, SC_VI);
+               return;
+       }
+
+       /* If the vi screen isn't ready, save the message. */
+       if (!F_ISSET(sp, SC_SCR_VI)) {
+               (void)vs_msgsave(sp, mtype, line, len);
+               return;
+       }
+
+       /* Save the cursor position. */
+       (void)gp->scr_cursor(sp, &oldy, &oldx);
+
+       /* If it's an ex output message, just write it out. */
+       if (mtype == M_NONE) {
+               vs_output(sp, mtype, line, len);
+               goto ret;
+       }
+
+       /*
+        * If it's a vi message, strip the trailing <newline> so we can
+        * try and paste messages together.
+        */
+       if (line[len - 1] == '\n')
+               --len;
+
+       /*
+        * If a message won't fit on a single line, try to split on a <blank>.
+        * If a subsequent message fits on the same line, write a separator
+        * and output it.  Otherwise, put out a newline.
+        *
+        * Need up to two padding characters normally; a semi-colon and a
+        * separating space.  If only a single line on the screen, add some
+        * more for the trailing continuation message.
+        *
+        * XXX
+        * Assume that periods and semi-colons take up a single column on the
+        * screen.
+        *
+        * XXX
+        * There are almost certainly pathological cases that will break this
+        * code.
+        */
+       if (IS_ONELINE(sp))
+               (void)msg_cmsg(sp, CMSG_CONT_S, &padding);
+       else
+               padding = 0;
+       padding += 2;
+
+       maxcols = sp->cols - 1;
+       if (vip->lcontinue != 0) {
+               if (len + vip->lcontinue + padding > maxcols)
+                       vs_output(sp, vip->mtype, ".\n", 2);
+               else  {
+                       vs_output(sp, vip->mtype, ";", 1);
+                       vs_output(sp, M_NONE, " ", 1);
+               }
+       }
+       vip->mtype = mtype;
+       for (s = line;; s = t) {
+               for (; len > 0 && isblank((unsigned char)*s); --len, ++s);
+               if (len == 0)
+                       break;
+               if (len + vip->lcontinue > maxcols) {
+                       for (e = s + (maxcols - vip->lcontinue);
+                           e > s && !isblank((unsigned char)*e); --e);
+                       if (e == s)
+                                e = t = s + (maxcols - vip->lcontinue);
+                       else
+                               for (t = e; isblank((unsigned char)e[-1]); --e);
+               } else
+                       e = t = s + len;
+
+               /*
+                * If the message ends in a period, discard it, we want to
+                * gang messages where possible.
+                */
+               len -= t - s;
+               if (len == 0 && (e - s) > 1 && s[(e - s) - 1] == '.')
+                       --e;
+               vs_output(sp, mtype, s, e - s);
+
+               if (len != 0)
+                       vs_output(sp, M_NONE, "\n", 1);
+
+               if (INTERRUPTED(sp))
+                       break;
+       }
+
+ret:   (void)gp->scr_move(sp, oldy, oldx);
+       (void)gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_output --
+ *     Output the text to the screen.
+ */
+static void
+vs_output(SCR *sp, mtype_t mtype, const char *line, int llen)
+{
+       unsigned char *kp;
+       GS *gp;
+       VI_PRIVATE *vip;
+       size_t chlen, notused;
+       int ch, len, rlen, tlen;
+       const char *p, *t;
+       char *cbp, *ecbp, cbuf[128];
+
+       gp = sp->gp;
+       vip = VIP(sp);
+       for (p = line, rlen = llen; llen > 0;) {
+               /* Get the next physical line. */
+               if ((p = memchr(line, '\n', llen)) == NULL)
+                       len = llen;
+               else
+                       len = p - line;
+
+               /*
+                * The max is sp->cols characters, and we may have already
+                * written part of the line.
+                */
+               if (len + vip->lcontinue > sp->cols)
+                       len = sp->cols - vip->lcontinue;
+
+               /*
+                * If the first line output, do nothing.  If the second line
+                * output, draw the divider line.  If drew a full screen, we
+                * remove the divider line.  If it's a continuation line, move
+                * to the continuation point, else, move the screen up.
+                */
+               if (vip->lcontinue == 0) {
+                       if (!IS_ONELINE(sp)) {
+                               if (vip->totalcount == 1) {
+                                       (void)gp->scr_move(sp,
+                                           LASTLINE(sp) - 1, 0);
+                                       (void)gp->scr_clrtoeol(sp);
+                                       (void)vs_divider(sp);
+                                       F_SET(vip, VIP_DIVIDER);
+                                       ++vip->totalcount;
+                                       ++vip->linecount;
+                               }
+                               if (vip->totalcount == sp->t_maxrows &&
+                                   F_ISSET(vip, VIP_DIVIDER)) {
+                                       --vip->totalcount;
+                                       --vip->linecount;
+                                       F_CLR(vip, VIP_DIVIDER);
+                               }
+                       }
+                       if (vip->totalcount != 0)
+                               vs_scroll(sp, NULL, SCROLL_W_QUIT);
+
+                       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+                       ++vip->totalcount;
+                       ++vip->linecount;
+
+                       if (INTERRUPTED(sp))
+                               break;
+               } else
+                       (void)gp->scr_move(sp, LASTLINE(sp), vip->lcontinue);
+
+               /* Error messages are in inverse video. */
+               if (mtype == M_ERR)
+                       (void)gp->scr_attr(sp, SA_INVERSE, 1);
+
+               /* Display the line, doing character translation. */
+#define        FLUSH {                                                         \
+       *cbp = '\0';                                                    \
+       (void)gp->scr_addstr(sp, cbuf, cbp - cbuf);                     \
+       cbp = cbuf;                                                     \
+}
+               ecbp = (cbp = cbuf) + sizeof(cbuf) - 1;
+               for (t = line, tlen = len; tlen--; ++t) {
+                       ch = *t;
+                       /*
+                        * Replace tabs with spaces, there are places in
+                        * ex that do column calculations without looking
+                        * at <tabs> -- and all routines that care about
+                        * <tabs> do their own expansions.  This catches
+                        * <tabs> in things like tag search strings.
+                        */
+                       if (ch == '\t')
+                               ch = ' ';
+                       chlen = KEY_LEN(sp, ch);
+                       if (cbp + chlen >= ecbp)
+                               FLUSH;
+                       for (kp = KEY_NAME(sp, ch); chlen--;)
+                               *cbp++ = *kp++;
+               }
+               if (cbp > cbuf)
+                       FLUSH;
+               if (mtype == M_ERR)
+                       (void)gp->scr_attr(sp, SA_INVERSE, 0);
+
+               /* Clear the rest of the line. */
+               (void)gp->scr_clrtoeol(sp);
+
+               /* If we loop, it's a new line. */
+               vip->lcontinue = 0;
+
+               /* Reset for the next line. */
+               line += len;
+               llen -= len;
+               if (p != NULL) {
+                       ++line;
+                       --llen;
+               }
+       }
+
+       /* Set up next continuation line. */
+       if (p == NULL)
+               gp->scr_cursor(sp, &notused, &vip->lcontinue);
+}
+
+/*
+ * vs_ex_resolve --
+ *     Deal with ex message output.
+ *
+ * This routine is called when exiting a colon command to resolve any ex
+ * output that may have occurred.
+ *
+ * PUBLIC: int vs_ex_resolve __P((SCR *, int *));
+ */
+int
+vs_ex_resolve(SCR *sp, int *continuep)
+{
+       EVENT ev;
+       GS *gp;
+       VI_PRIVATE *vip;
+       sw_t wtype;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+       *continuep = 0;
+
+       /* If we ran any ex command, we can't trust the cursor position. */
+       F_SET(vip, VIP_CUR_INVALID);
+
+       /* Terminate any partially written message. */
+       if (vip->lcontinue != 0) {
+               vs_output(sp, vip->mtype, ".", 1);
+               vip->lcontinue = 0;
+
+               vip->mtype = M_NONE;
+       }
+
+       /*
+        * If we switched out of the vi screen into ex, switch back while we
+        * figure out what to do with the screen and potentially get another
+        * command to execute.
+        *
+        * If we didn't switch into ex, we're not required to wait, and less
+        * than 2 lines of output, we can continue without waiting for the
+        * wait.
+        *
+        * Note, all other code paths require waiting, so we leave the report
+        * of modified lines until later, so that we won't wait for no other
+        * reason than a threshold number of lines were modified.  This means
+        * we display cumulative line modification reports for groups of ex
+        * commands.  That seems right to me (well, at least not wrong).
+        */
+       if (F_ISSET(sp, SC_SCR_EXWROTE)) {
+               if (sp->gp->scr_screen(sp, SC_VI))
+                       return (1);
+       } else
+               if (!F_ISSET(sp, SC_EX_WAIT_YES) && vip->totalcount < 2) {
+                       F_CLR(sp, SC_EX_WAIT_NO);
+                       return (0);
+               }
+
+       /* Clear the required wait flag, it's no longer needed. */
+       F_CLR(sp, SC_EX_WAIT_YES);
+
+       /*
+        * Wait, unless explicitly told not to wait or the user interrupted
+        * the command.  If the user is leaving the screen, for any reason,
+        * they can't continue with further ex commands.
+        */
+       if (!F_ISSET(sp, SC_EX_WAIT_NO) && !INTERRUPTED(sp)) {
+               wtype = F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE |
+                   SC_FSWITCH | SC_SSWITCH) ? SCROLL_W : SCROLL_W_EX;
+               if (F_ISSET(sp, SC_SCR_EXWROTE))
+                       vs_wait(sp, continuep, wtype);
+               else
+                       vs_scroll(sp, continuep, wtype);
+               if (*continuep)
+                       return (0);
+       }
+
+       /* If ex wrote on the screen, refresh the screen image. */
+       if (F_ISSET(sp, SC_SCR_EXWROTE))
+               F_SET(vip, VIP_N_EX_PAINT);
+
+       /*
+        * If we're not the bottom of the split screen stack, the screen
+        * image itself is wrong, so redraw everything.
+        */
+       if (sp->q.cqe_next != (void *)&sp->wp->scrq)
+               F_SET(sp, SC_SCR_REDRAW);
+
+       /* If ex changed the underlying file, the map itself is wrong. */
+       if (F_ISSET(vip, VIP_N_EX_REDRAW))
+               F_SET(sp, SC_SCR_REFORMAT);
+
+       /* Ex may have switched out of the alternate screen, return. */
+       (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
+
+       /*
+        * Whew.  We're finally back home, after what feels like years.
+        * Kiss the ground.
+        */
+       F_CLR(sp, SC_SCR_EXWROTE | SC_EX_WAIT_NO);
+
+       /*
+        * We may need to repaint some of the screen, e.g.:
+        *
+        *      :set
+        *      :!ls
+        *
+        * gives us a combination of some lines that are "wrong", and a need
+        * for a full refresh.
+        */
+       if (vip->totalcount > 1) {
+               /* Set up the redraw of the overwritten lines. */
+               ev.e_event = E_REPAINT;
+               ev.e_flno = vip->totalcount >=
+                   sp->rows ? 1 : sp->rows - vip->totalcount;
+               ev.e_tlno = sp->rows;
+
+               /* Reset the count of overwriting lines. */
+               vip->linecount = vip->lcontinue = vip->totalcount = 0;
+
+               /* Redraw. */
+               (void)v_erepaint(sp, &ev);
+       } else
+               /* Reset the count of overwriting lines. */
+               vip->linecount = vip->lcontinue = vip->totalcount = 0;
+
+       return (0);
+}
+
+/*
+ * vs_resolve --
+ *     Deal with message output.
+ *
+ * PUBLIC: int vs_resolve __P((SCR *, SCR *, int));
+ */
+int
+vs_resolve(SCR *sp, SCR *csp, int forcewait)
+{
+       EVENT ev;
+       GS *gp;
+       WIN *wp;
+       MSGS *mp;
+       VI_PRIVATE *vip;
+       size_t oldy, oldx;
+       int redraw;
+
+       /*
+        * Vs_resolve is called from the main vi loop and the refresh function
+        * to periodically ensure that the user has seen any messages that have
+        * been displayed and that any status lines are correct.  The sp screen
+        * is the screen we're checking, usually the current screen.  When it's
+        * not, csp is the current screen, used for final cursor positioning.
+        */
+       gp = sp->gp;
+       wp = sp->wp;
+       vip = VIP(sp);
+       if (csp == NULL)
+               csp = sp;
+
+       /* Save the cursor position. */
+       (void)gp->scr_cursor(csp, &oldy, &oldx);
+
+       /* Ring the bell if it's scheduled. */
+       if (F_ISSET(gp, G_BELLSCHED)) {
+               F_CLR(gp, G_BELLSCHED);
+               (void)gp->scr_bell(sp);
+       }
+
+       /* Display new file status line. */
+       if (F_ISSET(sp, SC_STATUS)) {
+               F_CLR(sp, SC_STATUS);
+               msgq_status(sp, sp->lno, MSTAT_TRUNCATE);
+       }
+
+       /* Report on line modifications. */
+       mod_rpt(sp);
+
+       /*
+        * Flush any saved messages.  If the screen isn't ready, refresh
+        * it.  (A side-effect of screen refresh is that we can display
+        * messages.)  Once this is done, don't trust the cursor.  That
+        * extra refresh screwed the pooch.
+        */
+       if (gp->msgq.lh_first != NULL) {
+               if (!F_ISSET(sp, SC_SCR_VI) && vs_refresh(sp, 1))
+                       return (1);
+               while ((mp = gp->msgq.lh_first) != NULL) {
+                       wp->scr_msg(sp, mp->mtype, mp->buf, mp->len);
+                       LIST_REMOVE(mp, q);
+                       free(mp->buf);
+                       free(mp);
+               }
+               F_SET(vip, VIP_CUR_INVALID);
+       }
+
+       switch (vip->totalcount) {
+       case 0:
+               redraw = 0;
+               break;
+       case 1:
+               /*
+                * If we're switching screens, we have to wait for messages,
+                * regardless.  If we don't wait, skip updating the modeline.
+                */
+               if (forcewait)
+                       vs_scroll(sp, NULL, SCROLL_W);
+               else
+                       F_SET(vip, VIP_S_MODELINE);
+
+               redraw = 0;
+               break;
+       default:
+               /*
+                * If >1 message line in use, prompt the user to continue and
+                * repaint overwritten lines.
+                */
+               vs_scroll(sp, NULL, SCROLL_W);
+
+               ev.e_event = E_REPAINT;
+               ev.e_flno = vip->totalcount >=
+                   sp->rows ? 1 : sp->rows - vip->totalcount;
+               ev.e_tlno = sp->rows;
+
+               redraw = 1;
+               break;
+       }
+
+       /* Reset the count of overwriting lines. */
+       vip->linecount = vip->lcontinue = vip->totalcount = 0;
+
+       /* Redraw. */
+       if (redraw)
+               (void)v_erepaint(sp, &ev);
+
+       /* Restore the cursor position. */
+       (void)gp->scr_move(csp, oldy, oldx);
+
+       return (0);
+}
+
+/*
+ * vs_scroll --
+ *     Scroll the screen for output.
+ */
+static void
+vs_scroll(SCR *sp, int *continuep, sw_t wtype)
+{
+       GS *gp;
+       VI_PRIVATE *vip;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+       if (!IS_ONELINE(sp)) {
+               /*
+                * Scroll the screen.  Instead of scrolling the entire screen,
+                * delete the line above the first line output so preserve the
+                * maximum amount of the screen.
+                */
+               (void)gp->scr_move(sp, vip->totalcount <
+                   sp->rows ? LASTLINE(sp) - vip->totalcount : 0, 0);
+               (void)gp->scr_deleteln(sp);
+
+               /* If there are screens below us, push them back into place. */
+               if (sp->q.cqe_next != (void *)&sp->wp->scrq) {
+                       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+                       (void)gp->scr_insertln(sp);
+               }
+       }
+       if (wtype == SCROLL_W_QUIT && vip->linecount < sp->t_maxrows)
+               return;
+       vs_wait(sp, continuep, wtype);
+}
+
+/*
+ * vs_wait --
+ *     Prompt the user to continue.
+ */
+static void
+vs_wait(SCR *sp, int *continuep, sw_t wtype)
+{
+       EVENT ev;
+       VI_PRIVATE *vip;
+       const char *p;
+       GS *gp;
+       size_t len;
+
+       gp = sp->gp;
+       vip = VIP(sp);
+
+       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+       if (IS_ONELINE(sp))
+               p = msg_cmsg(sp, CMSG_CONT_S, &len);
+       else
+               switch (wtype) {
+               case SCROLL_W_QUIT:
+                       p = msg_cmsg(sp, CMSG_CONT_Q, &len);
+                       break;
+               case SCROLL_W_EX:
+                       p = msg_cmsg(sp, CMSG_CONT_EX, &len);
+                       break;
+               case SCROLL_W:
+                       p = msg_cmsg(sp, CMSG_CONT, &len);
+                       break;
+               default:
+                       abort();
+                       /* NOTREACHED */
+               }
+       (void)gp->scr_addstr(sp, p, len);
+
+       ++vip->totalcount;
+       vip->linecount = 0;
+
+       (void)gp->scr_clrtoeol(sp);
+       (void)gp->scr_refresh(sp, 0);
+
+       /* Get a single character from the terminal. */
+       if (continuep != NULL)
+               *continuep = 0;
+       for (;;) {
+               if (v_event_get(sp, &ev, 0, 0))
+                       return;
+               if (ev.e_event == E_CHARACTER)
+                       break;
+               if (ev.e_event == E_INTERRUPT) {
+                       ev.e_c = CH_QUIT;
+                       F_SET(gp, G_INTERRUPTED);
+                       break;
+               }
+               (void)gp->scr_bell(sp);
+       }
+       switch (wtype) {
+       case SCROLL_W_QUIT:
+               if (ev.e_c == CH_QUIT)
+                       F_SET(gp, G_INTERRUPTED);
+               break;
+       case SCROLL_W_EX:
+               if (ev.e_c == ':' && continuep != NULL)
+                       *continuep = 1;
+               break;
+       case SCROLL_W:
+               break;
+       }
+}
+
+/*
+ * vs_divider --
+ *     Draw a dividing line between the screen and the output.
+ */
+static void
+vs_divider(SCR *sp)
+{
+       GS *gp;
+       size_t len;
+
+#define        DIVIDESTR       "+=+=+=+=+=+=+=+"
+       len =
+           sizeof(DIVIDESTR) - 1 > sp->cols ? sp->cols : sizeof(DIVIDESTR) - 1;
+       gp = sp->gp;
+       (void)gp->scr_attr(sp, SA_INVERSE, 1);
+       (void)gp->scr_addstr(sp, DIVIDESTR, len);
+       (void)gp->scr_attr(sp, SA_INVERSE, 0);
+}
+
+/*
+ * vs_msgsave --
+ *     Save a message for later display.
+ */
+static void
+vs_msgsave(SCR *sp, mtype_t mt, char *p, size_t len)
+{
+       GS *gp;
+       MSGS *mp_c, *mp_n;
+
+       /*
+        * We have to handle messages before we have any place to put them.
+        * If there's no screen support yet, allocate a msg structure, copy
+        * in the message, and queue it on the global structure.  If we can't
+        * allocate memory here, we're genuinely screwed, dump the message
+        * to stderr in the (probably) vain hope that someone will see it.
+        */
+       CALLOC_GOTO(sp, mp_n, MSGS *, 1, sizeof(MSGS));
+       MALLOC_GOTO(sp, mp_n->buf, char *, len);
+
+       memmove(mp_n->buf, p, len);
+       mp_n->len = len;
+       mp_n->mtype = mt;
+
+       gp = sp->gp;
+       if ((mp_c = gp->msgq.lh_first) == NULL) {
+               LIST_INSERT_HEAD(&gp->msgq, mp_n, q);
+       } else {
+               while (mp_c->q.le_next != NULL)
+                       mp_c = mp_c->q.le_next;
+               LIST_INSERT_AFTER(mp_c, mp_n, q);
+       }
+       return;
+
+alloc_err:
+       if (mp_n != NULL)
+               free(mp_n);
+       (void)fprintf(stderr, "%.*s\n", (int)len, p);
+}
diff --git a/dist/nvi/vi/vs_refresh.c b/dist/nvi/vi/vs_refresh.c
new file mode 100644 (file)
index 0000000..d052c82
--- /dev/null
@@ -0,0 +1,869 @@
+/*     $NetBSD: vs_refresh.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vs_refresh.c,v 10.50 2001/06/25 15:19:37 skimo Exp (Berkeley) Date: 2001/06/25 15:19:37";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+#define        UPDATE_CURSOR   0x01                    /* Update the cursor. */
+#define        UPDATE_SCREEN   0x02                    /* Flush to screen. */
+
+static void    vs_modeline __P((SCR *));
+static int     vs_paint __P((SCR *, u_int));
+
+/*
+ * vs_refresh --
+ *     Refresh all screens.
+ *
+ * PUBLIC: int vs_refresh __P((SCR *, int));
+ */
+int
+vs_refresh(SCR *sp, int forcepaint)
+{
+       GS *gp;
+       SCR *tsp;
+       int need_refresh;
+       u_int priv_paint, pub_paint;
+
+       gp = sp->gp;
+
+       /*
+        * 1: Refresh the screen.
+        *
+        * If SC_SCR_REDRAW is set in the current screen, repaint everything
+        * that we can find, including status lines.
+        */
+       if (F_ISSET(sp, SC_SCR_REDRAW))
+               for (tsp = sp->wp->scrq.cqh_first;
+                   tsp != (void *)&sp->wp->scrq; tsp = tsp->q.cqe_next)
+                       if (tsp != sp)
+                               F_SET(tsp, SC_SCR_REDRAW | SC_STATUS);
+
+       /*
+        * 2: Related or dirtied screens, or screens with messages.
+        *
+        * If related screens share a view into a file, they may have been
+        * modified as well.  Refresh any screens that aren't exiting that
+        * have paint or dirty bits set.  Always update their screens, we
+        * are not likely to get another chance.  Finally, if we refresh any
+        * screens other than the current one, the cursor will be trashed.
+        */
+       pub_paint = SC_SCR_REFORMAT | SC_SCR_REDRAW;
+       priv_paint = VIP_CUR_INVALID | VIP_N_REFRESH;
+       if (O_ISSET(sp, O_NUMBER))
+               priv_paint |= VIP_N_RENUMBER;
+       for (tsp = sp->wp->scrq.cqh_first;
+           tsp != (void *)&sp->wp->scrq; tsp = tsp->q.cqe_next)
+               if (tsp != sp && !F_ISSET(tsp, SC_EXIT | SC_EXIT_FORCE) &&
+                   (F_ISSET(tsp, pub_paint) ||
+                   F_ISSET(VIP(tsp), priv_paint))) {
+                       (void)vs_paint(tsp,
+                           (F_ISSET(VIP(tsp), VIP_CUR_INVALID) ?
+                           UPDATE_CURSOR : 0) | UPDATE_SCREEN);
+                       F_SET(VIP(sp), VIP_CUR_INVALID);
+               }
+
+       /*
+        * 3: Refresh the current screen.
+        *
+        * Always refresh the current screen, it may be a cursor movement.
+        * Also, always do it last -- that way, SC_SCR_REDRAW can be set
+        * in the current screen only, and the screen won't flash.
+        */
+       if (vs_paint(sp, UPDATE_CURSOR | (!forcepaint &&
+           F_ISSET(sp, SC_SCR_VI) && KEYS_WAITING(sp) ? 0 : UPDATE_SCREEN)))
+               return (1);
+
+       /*
+        * 4: Paint any missing status lines.
+        *
+        * XXX
+        * This is fairly evil.  Status lines are written using the vi message
+        * mechanism, since we have no idea how long they are.  Since we may be
+        * painting screens other than the current one, we don't want to make
+        * the user wait.  We depend heavily on there not being any other lines
+        * currently waiting to be displayed and the message truncation code in
+        * the msgq_status routine working.
+        *
+        * And, finally, if we updated any status lines, make sure the cursor
+        * gets back to where it belongs.
+        */
+       for (need_refresh = 0, tsp = sp->wp->scrq.cqh_first;
+           tsp != (void *)&sp->wp->scrq; tsp = tsp->q.cqe_next)
+               if (F_ISSET(tsp, SC_STATUS)) {
+                       need_refresh = 1;
+                       vs_resolve(tsp, sp, 0);
+               }
+       if (need_refresh)
+               (void)gp->scr_refresh(sp, 0);
+
+       /*
+        * A side-effect of refreshing the screen is that it's now ready
+        * for everything else, i.e. messages.
+        */
+       F_SET(sp, SC_SCR_VI);
+       return (0);
+}
+
+/*
+ * vs_paint --
+ *     This is the guts of the vi curses screen code.  The idea is that
+ *     the SCR structure passed in contains the new coordinates of the
+ *     screen.  What makes this hard is that we don't know how big
+ *     characters are, doing input can put the cursor in illegal places,
+ *     and we're frantically trying to avoid repainting unless it's
+ *     absolutely necessary.  If you change this code, you'd better know
+ *     what you're doing.  It's subtle and quick to anger.
+ */
+static int
+vs_paint(SCR *sp, u_int flags)
+{
+       GS *gp;
+       SMAP *smp, tmp;
+       VI_PRIVATE *vip;
+       db_recno_t lastline, lcnt;
+       size_t cwtotal, cnt, len, notused, off, y;
+       int ch = 0, didpaint, isempty, leftright_warp;
+       CHAR_T *p;
+
+#define         LNO    sp->lno                 /* Current file line. */
+#define        OLNO    vip->olno               /* Remembered file line. */
+#define         CNO    sp->cno                 /* Current file column. */
+#define        OCNO    vip->ocno               /* Remembered file column. */
+#define        SCNO    vip->sc_col             /* Current screen column. */
+
+       gp = sp->gp;
+       vip = VIP(sp);
+       didpaint = leftright_warp = 0;
+
+       /*
+        * 5: Reformat the lines.
+        *
+        * If the lines themselves have changed (:set list, for example),
+        * fill in the map from scratch.  Adjust the screen that's being
+        * displayed if the leftright flag is set.
+        */
+       if (F_ISSET(sp, SC_SCR_REFORMAT)) {
+               /* Invalidate the line size cache. */
+               VI_SCR_CFLUSH(vip);
+
+               /* Toss vs_line() cached information. */
+               if (F_ISSET(sp, SC_SCR_TOP)) {
+                       if (vs_sm_fill(sp, LNO, P_TOP))
+                               return (1);
+               }
+               else if (F_ISSET(sp, SC_SCR_CENTER)) {
+                       if (vs_sm_fill(sp, LNO, P_MIDDLE))
+                               return (1);
+               } else
+                       if (vs_sm_fill(sp, OOBLNO, P_TOP))
+                               return (1);
+               F_SET(sp, SC_SCR_REDRAW);
+       }
+
+       /*
+        * 6: Line movement.
+        *
+        * Line changes can cause the top line to change as well.  As
+        * before, if the movement is large, the screen is repainted.
+        *
+        * 6a: Small screens.
+        *
+        * Users can use the window, w300, w1200 and w9600 options to make
+        * the screen artificially small.  The behavior of these options
+        * in the historic vi wasn't all that consistent, and, in fact, it
+        * was never documented how various screen movements affected the
+        * screen size.  Generally, one of three things would happen:
+        *      1: The screen would expand in size, showing the line
+        *      2: The screen would scroll, showing the line
+        *      3: The screen would compress to its smallest size and
+        *              repaint.
+        * In general, scrolling didn't cause compression (200^D was handled
+        * the same as ^D), movement to a specific line would (:N where N
+        * was 1 line below the screen caused a screen compress), and cursor
+        * movement would scroll if it was 11 lines or less, and compress if
+        * it was more than 11 lines.  (And, no, I have no idea where the 11
+        * comes from.)
+        *
+        * What we do is try and figure out if the line is less than half of
+        * a full screen away.  If it is, we expand the screen if there's
+        * room, and then scroll as necessary.  The alternative is to compress
+        * and repaint.
+        *
+        * !!!
+        * This code is a special case from beginning to end.  Unfortunately,
+        * home modems are still slow enough that it's worth having.
+        *
+        * XXX
+        * If the line a really long one, i.e. part of the line is on the
+        * screen but the column offset is not, we'll end up in the adjust
+        * code, when we should probably have compressed the screen.
+        */
+       if (IS_SMALL(sp)) {
+               if (LNO < HMAP->lno) {
+                       lcnt = vs_sm_nlines(sp, HMAP, LNO, sp->t_maxrows);
+                       if (lcnt <= HALFSCREEN(sp))
+                               for (; lcnt && sp->t_rows != sp->t_maxrows;
+                                    --lcnt, ++sp->t_rows) {
+                                       ++TMAP;
+                                       if (vs_sm_1down(sp))
+                                               return (1);
+                               }
+                       else
+                               goto small_fill;
+               } else if (LNO > TMAP->lno) {
+                       lcnt = vs_sm_nlines(sp, TMAP, LNO, sp->t_maxrows);
+                       if (lcnt <= HALFSCREEN(sp))
+                               for (; lcnt && sp->t_rows != sp->t_maxrows;
+                                    --lcnt, ++sp->t_rows) {
+                                       if (vs_sm_next(sp, TMAP, TMAP + 1))
+                                               return (1);
+                                       ++TMAP;
+                                       if (vs_line(sp, TMAP, NULL, NULL))
+                                               return (1);
+                               }
+                       else {
+small_fill:                    (void)gp->scr_move(sp, LASTLINE(sp), 0);
+                               (void)gp->scr_clrtoeol(sp);
+                               for (; sp->t_rows > sp->t_minrows;
+                                   --sp->t_rows, --TMAP) {
+                                       (void)gp->scr_move(sp, TMAP - HMAP, 0);
+                                       (void)gp->scr_clrtoeol(sp);
+                               }
+                               if (vs_sm_fill(sp, LNO, P_FILL))
+                                       return (1);
+                               F_SET(sp, SC_SCR_REDRAW);
+                               goto adjust;
+                       }
+               }
+       }
+
+       /*
+        * 6b: Line down, or current screen.
+        */
+       if (LNO >= HMAP->lno) {
+               /* Current screen. */
+               if (LNO <= TMAP->lno)
+                       goto adjust;
+               if (F_ISSET(sp, SC_SCR_TOP))
+                       goto top;
+               if (F_ISSET(sp, SC_SCR_CENTER))
+                       goto middle;
+
+               /*
+                * If less than half a screen above the line, scroll down
+                * until the line is on the screen.
+                */
+               lcnt = vs_sm_nlines(sp, TMAP, LNO, HALFTEXT(sp));
+               if (lcnt < HALFTEXT(sp)) {
+                       while (lcnt--)
+                               if (vs_sm_1up(sp))
+                                       return (1);
+                       goto adjust;
+               }
+               goto bottom;
+       }
+
+       /*
+        * 6c: If not on the current screen, may request center or top.
+        */
+       if (F_ISSET(sp, SC_SCR_TOP))
+               goto top;
+       if (F_ISSET(sp, SC_SCR_CENTER))
+               goto middle;
+
+       /*
+        * 6d: Line up.
+        */
+       lcnt = vs_sm_nlines(sp, HMAP, LNO, HALFTEXT(sp));
+       if (lcnt < HALFTEXT(sp)) {
+               /*
+                * If less than half a screen below the line, scroll up until
+                * the line is the first line on the screen.  Special check so
+                * that if the screen has been emptied, we refill it.
+                */
+               if (db_exist(sp, HMAP->lno)) {
+                       while (lcnt--)
+                               if (vs_sm_1down(sp))
+                                       return (1);
+                       goto adjust;
+               }
+
+               /*
+                * If less than a half screen from the bottom of the file,
+                * put the last line of the file on the bottom of the screen.
+                */
+bottom:                if (db_last(sp, &lastline))
+                       return (1);
+               tmp.lno = LNO;
+               tmp.coff = HMAP->coff;
+               tmp.soff = 1;
+               lcnt = vs_sm_nlines(sp, &tmp, lastline+1, sp->t_rows);
+               if (lcnt < HALFTEXT(sp)) {
+                       if (vs_sm_fill(sp, lastline, P_BOTTOM))
+                               return (1);
+                       F_SET(sp, SC_SCR_REDRAW);
+                       goto adjust;
+               }
+               /* It's not close, just put the line in the middle. */
+               goto middle;
+       }
+
+       /*
+        * If less than half a screen from the top of the file, put the first
+        * line of the file at the top of the screen.  Otherwise, put the line
+        * in the middle of the screen.
+        */
+       tmp.lno = 1;
+       tmp.coff = HMAP->coff;
+       tmp.soff = 1;
+       lcnt = vs_sm_nlines(sp, &tmp, LNO, HALFTEXT(sp));
+       if (lcnt < HALFTEXT(sp)) {
+               if (vs_sm_fill(sp, 1, P_TOP))
+                       return (1);
+       } else
+middle:                if (vs_sm_fill(sp, LNO, P_MIDDLE))
+                       return (1);
+       if (0) {
+top:           if (vs_sm_fill(sp, LNO, P_TOP))
+                       return (1);
+       }
+       F_SET(sp, SC_SCR_REDRAW);
+
+       /*
+        * At this point we know part of the line is on the screen.  Since
+        * scrolling is done using logical lines, not physical, all of the
+        * line may not be on the screen.  While that's not necessarily bad,
+        * if the part the cursor is on isn't there, we're going to lose.
+        * This can be tricky; if the line covers the entire screen, lno
+        * may be the same as both ends of the map, that's why we test BOTH
+        * the top and the bottom of the map.  This isn't a problem for
+        * left-right scrolling, the cursor movement code handles the problem.
+        *
+        * There's a performance issue here if editing *really* long lines.
+        * This gets to the right spot by scrolling, and, in a binary, by
+        * scrolling hundreds of lines.  If the adjustment looks like it's
+        * going to be a serious problem, refill the screen and repaint.
+        */
+adjust:        if (!O_ISSET(sp, O_LEFTRIGHT) &&
+           (LNO == HMAP->lno || LNO == TMAP->lno)) {
+               cnt = vs_screens(sp, LNO, &CNO);
+               if (LNO == HMAP->lno && cnt < HMAP->soff) {
+                       if ((HMAP->soff - cnt) > HALFTEXT(sp)) {
+                               HMAP->soff = cnt;
+                               vs_sm_fill(sp, OOBLNO, P_TOP);
+                               F_SET(sp, SC_SCR_REDRAW);
+                       } else
+                               while (cnt < HMAP->soff)
+                                       if (vs_sm_1down(sp))
+                                               return (1);
+               }
+               if (LNO == TMAP->lno && cnt > TMAP->soff) {
+                       if ((cnt - TMAP->soff) > HALFTEXT(sp)) {
+                               TMAP->soff = cnt;
+                               vs_sm_fill(sp, OOBLNO, P_BOTTOM);
+                               F_SET(sp, SC_SCR_REDRAW);
+                       } else
+                               while (cnt > TMAP->soff)
+                                       if (vs_sm_1up(sp))
+                                               return (1);
+               }
+       }
+
+       /*
+        * If the screen needs to be repainted, skip cursor optimization.
+        * However, in the code above we skipped leftright scrolling on
+        * the grounds that the cursor code would handle it.  Make sure
+        * the right screen is up.
+        */
+       if (F_ISSET(sp, SC_SCR_REDRAW)) {
+               if (O_ISSET(sp, O_LEFTRIGHT))
+                       goto slow;
+               goto paint;
+       }
+
+       /*
+        * 7: Cursor movements (current screen only).
+        */
+       if (!LF_ISSET(UPDATE_CURSOR))
+               goto number;
+
+       /*
+        * Decide cursor position.  If the line has changed, the cursor has
+        * moved over a tab, or don't know where the cursor was, reparse the
+        * line.  Otherwise, we've just moved over fixed-width characters,
+        * and can calculate the left/right scrolling and cursor movement
+        * without reparsing the line.  Note that we don't know which (if any)
+        * of the characters between the old and new cursor positions changed.
+        *
+        * XXX
+        * With some work, it should be possible to handle tabs quickly, at
+        * least in obvious situations, like moving right and encountering
+        * a tab, without reparsing the whole line.
+        *
+        * If the line we're working with has changed, reread it..
+        */
+       if (F_ISSET(vip, VIP_CUR_INVALID) || LNO != OLNO)
+               goto slow;
+
+       /* Otherwise, if nothing's changed, ignore the cursor. */
+       if (CNO == OCNO)
+               goto fast;
+
+       /*
+        * Get the current line.  If this fails, we either have an empty
+        * file and can just repaint, or there's a real problem.  This
+        * isn't a performance issue because there aren't any ways to get
+        * here repeatedly.
+        */
+       if (db_eget(sp, LNO, &p, &len, &isempty)) {
+               if (isempty)
+                       goto slow;
+               return (1);
+       }
+
+#ifdef DEBUG
+       /* Sanity checking. */
+       if (CNO >= len && len != 0) {
+               msgq(sp, M_ERR, "Error: %s/%d: cno (%u) >= len (%u)",
+                    tail(__FILE__), __LINE__, CNO, len);
+               return (1);
+       }
+#endif
+       /*
+        * The basic scheme here is to look at the characters in between
+        * the old and new positions and decide how big they are on the
+        * screen, and therefore, how many screen positions to move.
+        */
+       if (CNO < OCNO) {
+               /*
+                * 7a: Cursor moved left.
+                *
+                * Point to the old character.  The old cursor position can
+                * be past EOL if, for example, we just deleted the rest of
+                * the line.  In this case, since we don't know the width of
+                * the characters we traversed, we have to do it slowly.
+                */
+               p += OCNO;
+               cnt = (OCNO - CNO) + 1;
+               if (OCNO >= len)
+                       goto slow;
+
+               /*
+                * Quick sanity check -- it's hard to figure out exactly when
+                * we cross a screen boundary as we do in the cursor right
+                * movement.  If cnt is so large that we're going to cross the
+                * boundary no matter what, stop now.
+                */
+               if (SCNO + 1 + MAX_CHARACTER_COLUMNS < cnt)
+                       goto slow;
+
+               /*
+                * Count up the widths of the characters.  If it's a tab
+                * character, go do it the the slow way.
+                */
+               for (cwtotal = 0; cnt--; cwtotal += KEY_COL(sp, ch))
+                       if ((ch = *(UCHAR_T *)p--) == '\t')
+                               goto slow;
+
+               /*
+                * Decrement the screen cursor by the total width of the
+                * characters minus 1.
+                */
+               cwtotal -= 1;
+
+               /*
+                * If we're moving left, and there's a wide character in the
+                * current position, go to the end of the character.
+                */
+               if (KEY_COL(sp, ch) > 1)
+                       cwtotal -= KEY_COL(sp, ch) - 1;
+
+               /*
+                * If the new column moved us off of the current logical line,
+                * calculate a new one.  If doing leftright scrolling, we've
+                * moved off of the current screen, as well.
+                */
+               if (SCNO < cwtotal)
+                       goto slow;
+               SCNO -= cwtotal;
+       } else {
+               /*
+                * 7b: Cursor moved right.
+                *
+                * Point to the first character to the right.
+                */
+               p += OCNO + 1;
+               cnt = CNO - OCNO;
+
+               /*
+                * Count up the widths of the characters.  If it's a tab
+                * character, go do it the the slow way.  If we cross a
+                * screen boundary, we can quit.
+                */
+               for (cwtotal = SCNO; cnt--;) {
+                       if ((ch = *(UCHAR_T *)p++) == '\t')
+                               goto slow;
+                       if ((cwtotal += KEY_COL(sp, ch)) >= SCREEN_COLS(sp))
+                               break;
+               }
+
+               /*
+                * Increment the screen cursor by the total width of the
+                * characters.
+                */
+               SCNO = cwtotal;
+
+               /* See screen change comment in section 6a. */
+               if (SCNO >= SCREEN_COLS(sp))
+                       goto slow;
+       }
+
+       /*
+        * 7c: Fast cursor update.
+        *
+        * We have the current column, retrieve the current row.
+        */
+fast:  (void)gp->scr_cursor(sp, &y, &notused);
+       goto done_cursor;
+
+       /*
+        * 7d: Slow cursor update.
+        *
+        * Walk through the map and find the current line.
+        */
+slow:  for (smp = HMAP; smp->lno != LNO; ++smp);
+
+       /*
+        * 7e: Leftright scrolling adjustment.
+        *
+        * If doing left-right scrolling and the cursor movement has changed
+        * the displayed screen, scroll the screen left or right, unless we're
+        * updating the info line in which case we just scroll that one line.
+        * We adjust the offset up or down until we have a window that covers
+        * the current column, making sure that we adjust differently for the
+        * first screen as compared to subsequent ones.
+        */
+       if (O_ISSET(sp, O_LEFTRIGHT)) {
+               /*
+                * Get the screen column for this character, and correct
+                * for the number option offset.
+                */
+               cnt = vs_columns(sp, NULL, LNO, &CNO, NULL);
+               if (O_ISSET(sp, O_NUMBER))
+                       cnt -= O_NUMBER_LENGTH;
+
+               /* Adjust the window towards the beginning of the line. */
+               off = smp->coff;
+               if (off >= cnt) {
+                       do {
+                               if (off >= O_VAL(sp, O_SIDESCROLL))
+                                       off -= O_VAL(sp, O_SIDESCROLL);
+                               else {
+                                       off = 0;
+                                       break;
+                               }
+                       } while (off >= cnt);
+                       goto shifted;
+               }
+
+               /* Adjust the window towards the end of the line. */
+               if ((off == 0 && off + SCREEN_COLS(sp) < cnt) ||
+                   (off != 0 && off + sp->cols < cnt)) {
+                       do {
+                               off += O_VAL(sp, O_SIDESCROLL);
+                       } while (off + sp->cols < cnt);
+
+shifted:               /* Fill in screen map with the new offset. */
+                       if (F_ISSET(sp, SC_TINPUT_INFO))
+                               smp->coff = off;
+                       else {
+                               for (smp = HMAP; smp <= TMAP; ++smp)
+                                       smp->coff = off;
+                               leftright_warp = 1;
+                       }
+                       goto paint;
+               }
+
+               /*
+                * We may have jumped here to adjust a leftright screen because
+                * redraw was set.  If so, we have to paint the entire screen.
+                */
+               if (F_ISSET(sp, SC_SCR_REDRAW))
+                       goto paint;
+       }
+
+       /*
+        * Update the screen lines for this particular file line until we
+        * have a new screen cursor position.
+        */
+       for (y = -1,
+           vip->sc_smap = NULL; smp <= TMAP && smp->lno == LNO; ++smp) {
+               if (vs_line(sp, smp, &y, &SCNO))
+                       return (1);
+               if (y != (size_t)-1) {
+                       vip->sc_smap = smp;
+                       break;
+               }
+       }
+       goto done_cursor;
+
+       /*
+        * 8: Repaint the entire screen.
+        *
+        * Lost big, do what you have to do.  We flush the cache, since
+        * SC_SCR_REDRAW gets set when the screen isn't worth fixing, and
+        * it's simpler to repaint.  So, don't trust anything that we
+        * think we know about it.
+        */
+paint: for (smp = HMAP; smp <= TMAP; ++smp)
+               SMAP_FLUSH(smp);
+       for (y = -1, vip->sc_smap = NULL, smp = HMAP; smp <= TMAP; ++smp) {
+               if (vs_line(sp, smp, &y, &SCNO))
+                       return (1);
+               if (y != (size_t)-1 && vip->sc_smap == NULL)
+                       vip->sc_smap = smp;
+       }
+       /*
+        * If it's a small screen and we're redrawing, clear the unused lines,
+        * ex may have overwritten them.
+        */
+       if (F_ISSET(sp, SC_SCR_REDRAW) && IS_SMALL(sp))
+               for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
+                       (void)gp->scr_move(sp, cnt, 0);
+                       (void)gp->scr_clrtoeol(sp);
+               }
+
+       didpaint = 1;
+
+done_cursor:
+       /*
+        * Sanity checking.  When the repainting code messes up, the usual
+        * result is we don't repaint the cursor and so sc_smap will be
+        * NULL.  If we're debugging, die, otherwise restart from scratch.
+        */
+#ifdef DEBUG
+       if (vip->sc_smap == NULL) {
+               fprintf(stderr, "smap error\n");
+               sleep(100);
+               abort();
+       }
+#else
+       if (vip->sc_smap == NULL) {
+               F_SET(sp, SC_SCR_REFORMAT);
+               return (vs_paint(sp, flags));
+       }
+#endif
+
+       /*
+        * 9: Set the remembered cursor values.
+        */
+       OCNO = CNO;
+       OLNO = LNO;
+
+       /*
+        * 10: Repaint the line numbers.
+        *
+        * If O_NUMBER is set and the VIP_N_RENUMBER bit is set, and we
+        * didn't repaint the screen, repaint all of the line numbers,
+        * they've changed.
+        */
+number:        if (O_ISSET(sp, O_NUMBER) &&
+           F_ISSET(vip, VIP_N_RENUMBER) && !didpaint && vs_number(sp))
+               return (1);
+
+       /*
+        * 11: Update the mode line, position the cursor, and flush changes.
+        *
+        * If we warped the screen, we have to refresh everything.
+        */
+       if (leftright_warp)
+               LF_SET(UPDATE_CURSOR | UPDATE_SCREEN);
+
+       if (LF_ISSET(UPDATE_SCREEN) && !IS_ONELINE(sp) &&
+           !F_ISSET(vip, VIP_S_MODELINE) && !F_ISSET(sp, SC_TINPUT_INFO))
+               vs_modeline(sp);
+
+       if (LF_ISSET(UPDATE_CURSOR)) {
+               (void)gp->scr_move(sp, y, SCNO);
+
+               /*
+                * XXX
+                * If the screen shifted, we recalculate the "most favorite"
+                * cursor position.  Vi won't know that we've warped the
+                * screen, so it's going to have a wrong idea about where the
+                * cursor should be.  This is vi's problem, and fixing it here
+                * is a gross layering violation.
+                */
+               if (leftright_warp)
+                       (void)vs_column(sp, &sp->rcm);
+       }
+
+       if (LF_ISSET(UPDATE_SCREEN))
+               (void)gp->scr_refresh(sp, F_ISSET(vip, VIP_N_EX_PAINT));
+
+       /* 12: Clear the flags that are handled by this routine. */
+       F_CLR(sp, SC_SCR_CENTER | SC_SCR_REDRAW | SC_SCR_REFORMAT | SC_SCR_TOP);
+       F_CLR(vip, VIP_CUR_INVALID |
+           VIP_N_EX_PAINT | VIP_N_REFRESH | VIP_N_RENUMBER | VIP_S_MODELINE);
+
+       return (0);
+
+#undef  LNO
+#undef OLNO
+#undef  CNO
+#undef OCNO
+#undef SCNO
+}
+
+/*
+ * vs_modeline --
+ *     Update the mode line.
+ */
+static void
+vs_modeline(SCR *sp)
+{
+       static const char * const modes[] = {
+               "215|Append",                   /* SM_APPEND */
+               "216|Change",                   /* SM_CHANGE */
+               "217|Command",                  /* SM_COMMAND */
+               "218|Insert",                   /* SM_INSERT */
+               "219|Replace",                  /* SM_REPLACE */
+       };
+       GS *gp;
+       size_t cols, curcol, curlen, endpoint, len, midpoint;
+       const char *t = NULL;
+       int ellipsis;
+       char *p, buf[20];
+
+       gp = sp->gp;
+
+       /*
+        * We put down the file name, the ruler, the mode and the dirty flag.
+        * If there's not enough room, there's not enough room, we don't play
+        * any special games.  We try to put the ruler in the middle and the
+        * mode and dirty flag at the end.
+        *
+        * !!!
+        * Leave the last character blank, in case it's a really dumb terminal
+        * with hardware scroll.  Second, don't paint the last character in the
+        * screen, SunOS 4.1.1 and Ultrix 4.2 curses won't let you.
+        *
+        * Move to the last line on the screen.
+        */
+       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+
+       /* If more than one screen in the display, show the file name. */
+       curlen = 0;
+       if (IS_SPLIT(sp)) {
+               for (p = sp->frp->name; *p != '\0'; ++p);
+               for (ellipsis = 0, cols = sp->cols / 2; --p > sp->frp->name;) {
+                       if (*p == '/') {
+                               ++p;
+                               break;
+                       }
+                       if ((curlen += KEY_LEN(sp, *p)) > cols) {
+                               ellipsis = 3;
+                               curlen +=
+                                   KEY_LEN(sp, '.') * 3 + KEY_LEN(sp, ' ');
+                               while (curlen > cols) {
+                                       ++p;
+                                       curlen -= KEY_LEN(sp, *p);
+                               }
+                               break;
+                       }
+               }
+               if (ellipsis) {
+                       while (ellipsis--)
+                               (void)gp->scr_addstr(sp,
+                                   (const char *)KEY_NAME(sp, '.'),
+                                   KEY_LEN(sp, '.'));
+                       (void)gp->scr_addstr(sp,
+                           (const char *)KEY_NAME(sp, ' '), KEY_LEN(sp, ' '));
+               }
+               for (; *p != '\0'; ++p)
+                       (void)gp->scr_addstr(sp,
+                           (const char *)KEY_NAME(sp, *p), KEY_LEN(sp, *p));
+       }
+
+       /* Clear the rest of the line. */
+       (void)gp->scr_clrtoeol(sp);
+
+       /*
+        * Display the ruler.  If we're not at the midpoint yet, move there.
+        * Otherwise, add in two extra spaces.
+        *
+        * Adjust the current column for the fact that the editor uses it as
+        * a zero-based number.
+        *
+        * XXX
+        * Assume that numbers, commas, and spaces only take up a single
+        * column on the screen.
+        */
+       cols = sp->cols - 1;
+       if (O_ISSET(sp, O_RULER)) {
+               vs_column(sp, &curcol);
+               len =
+                   snprintf(buf, sizeof(buf), "%lu,%lu",
+                       (unsigned long)sp->lno, (unsigned long)curcol + 1);
+
+               midpoint = (cols - ((len + 1) / 2)) / 2;
+               if (curlen < midpoint) {
+                       (void)gp->scr_move(sp, LASTLINE(sp), midpoint);
+                       curlen += len;
+               } else if (curlen + 2 + len < cols) {
+                       (void)gp->scr_addstr(sp, "  ", 2);
+                       curlen += 2 + len;
+               }
+               (void)gp->scr_addstr(sp, buf, len);
+       }
+
+       /*
+        * Display the mode and the modified flag, as close to the end of the
+        * line as possible, but guaranteeing at least two spaces between the
+        * ruler and the modified flag.
+        */
+#define        MODESIZE        9
+       endpoint = cols;
+       if (O_ISSET(sp, O_SHOWMODE)) {
+               if (F_ISSET(sp->ep, F_MODIFIED))
+                       --endpoint;
+               t = msg_cat(sp, modes[sp->showmode], &len);
+               endpoint -= len;
+       }
+
+       if (endpoint > curlen + 2) {
+               (void)gp->scr_move(sp, LASTLINE(sp), endpoint);
+               if (O_ISSET(sp, O_SHOWMODE)) {
+                       if (F_ISSET(sp->ep, F_MODIFIED))
+                               (void)gp->scr_addstr(sp,
+                                   (const char *)KEY_NAME(sp, '*'),
+                                   KEY_LEN(sp, '*'));
+                       (void)gp->scr_addstr(sp, t, len);
+               }
+       }
+}
diff --git a/dist/nvi/vi/vs_relative.c b/dist/nvi/vi/vs_relative.c
new file mode 100644 (file)
index 0000000..f015cfd
--- /dev/null
@@ -0,0 +1,297 @@
+/*     $NetBSD: vs_relative.c,v 1.2 2008/12/05 22:51:43 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vs_relative.c,v 10.18 2001/07/08 13:02:48 skimo Exp (Berkeley) Date: 2001/07/08 13:02:48";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * vs_column --
+ *     Return the logical column of the cursor in the line.
+ *
+ * PUBLIC: int vs_column __P((SCR *, size_t *));
+ */
+int
+vs_column(SCR *sp, size_t *colp)
+{
+       VI_PRIVATE *vip;
+
+       vip = VIP(sp);
+
+       *colp = (O_ISSET(sp, O_LEFTRIGHT) ?
+           vip->sc_smap->coff : (vip->sc_smap->soff - 1) * sp->cols) +
+           vip->sc_col - (O_ISSET(sp, O_NUMBER) ? O_NUMBER_LENGTH : 0);
+       return (0);
+}
+
+/*
+ * vs_screens --
+ *     Return the screens necessary to display the line, or if specified,
+ *     the physical character column within the line, including space
+ *     required for the O_NUMBER and O_LIST options.
+ *
+ * PUBLIC: size_t vs_screens __P((SCR *, db_recno_t, size_t *));
+ */
+size_t
+vs_screens(SCR *sp, db_recno_t lno, size_t *cnop)
+{
+       size_t cols, screens;
+
+       /* Left-right screens are simple, it's always 1. */
+       if (O_ISSET(sp, O_LEFTRIGHT))
+               return (1);
+
+       /*
+        * Check for a cached value.  We maintain a cache because, if the
+        * line is large, this routine gets called repeatedly.  One other
+        * hack, lots of time the cursor is on column one, which is an easy
+        * one.
+        */
+       if (cnop == NULL) {
+               if (VIP(sp)->ss_lno == lno)
+                       return (VIP(sp)->ss_screens);
+       } else if (*cnop == 0)
+               return (1);
+
+       /* Figure out how many columns the line/column needs. */
+       cols = vs_columns(sp, NULL, lno, cnop, NULL);
+
+       screens = (cols / sp->cols + (cols % sp->cols ? 1 : 0));
+       if (screens == 0)
+               screens = 1;
+
+       /* Cache the value. */
+       if (cnop == NULL) {
+               VIP(sp)->ss_lno = lno;
+               VIP(sp)->ss_screens = screens;
+       }
+       return (screens);
+}
+
+/*
+ * vs_columns --
+ *     Return the screen columns necessary to display the line, or,
+ *     if specified, the physical character column within the line.
+ *
+ * PUBLIC: size_t vs_columns __P((SCR *, CHAR_T *, db_recno_t, size_t *, size_t *));
+ */
+size_t
+vs_columns(SCR *sp, CHAR_T *lp, db_recno_t lno, size_t *cnop, size_t *diffp)
+{
+       size_t chlen, cno, curoff, last = 0, len, scno;
+       int ch, leftright, listset;
+       CHAR_T *p;
+
+       /*
+        * Initialize the screen offset.
+        */
+       scno = 0;
+
+       /* Leading number if O_NUMBER option set. */
+       if (O_ISSET(sp, O_NUMBER))
+               scno += O_NUMBER_LENGTH;
+
+       /* Need the line to go any further. */
+       if (lp == NULL) {
+               (void)db_get(sp, lno, 0, &lp, &len);
+               if (len == 0)
+                       goto done;
+       }
+
+       /* Missing or empty lines are easy. */
+       if (lp == NULL) {
+done:          if (diffp != NULL)              /* XXX */
+                       *diffp = 0;
+               return scno;
+       }
+
+       /* Store away the values of the list and leftright edit options. */
+       listset = O_ISSET(sp, O_LIST);
+       leftright = O_ISSET(sp, O_LEFTRIGHT);
+
+       /*
+        * Initialize the pointer into the buffer and current offset.
+        */
+       p = lp;
+       curoff = 0;
+
+       /* Macro to return the display length of any signal character. */
+#define        CHLEN(val) (ch = *(UCHAR_T *)p++) == '\t' &&                    \
+           !listset ? TAB_OFF(val) : KEY_COL(sp, ch);
+
+       /*
+        * If folding screens (the historic vi screen format), past the end
+        * of the current screen, and the character was a tab, reset the
+        * current screen column to 0, and the total screen columns to the
+        * last column of the screen.  Otherwise, display the rest of the
+        * character in the next screen.
+        */
+#define        TAB_RESET {                                                     \
+       curoff += chlen;                                                \
+       if (!leftright && curoff >= sp->cols) {                         \
+               if (ch == '\t') {                                       \
+                       curoff = 0;                                     \
+                       scno -= scno % sp->cols;                        \
+               } else                                                  \
+                       curoff -= sp->cols;                             \
+       }                                                               \
+}
+       if (cnop == NULL)
+               while (len--) {
+                       chlen = CHLEN(curoff);
+                       last = scno;
+                       scno += chlen;
+                       TAB_RESET;
+               }
+       else
+               for (cno = *cnop;; --cno) {
+                       chlen = CHLEN(curoff);
+                       last = scno;
+                       scno += chlen;
+                       TAB_RESET;
+                       if (cno == 0)
+                               break;
+               }
+
+       /* Add the trailing '$' if the O_LIST option set. */
+       if (listset && cnop == NULL)
+               scno += KEY_LEN(sp, '$');
+
+       /*
+        * The text input screen code needs to know how much additional
+        * room the last two characters required, so that it can handle
+        * tab character displays correctly.
+        */
+       if (diffp != NULL)
+               *diffp = scno - last;
+       return (scno);
+}
+
+/*
+ * vs_rcm --
+ *     Return the physical column from the line that will display a
+ *     character closest to the currently most attractive character
+ *     position (which is stored as a screen column).
+ *
+ * PUBLIC: size_t vs_rcm __P((SCR *, db_recno_t, int));
+ */
+size_t
+vs_rcm(SCR *sp, db_recno_t lno, int islast)
+{
+       size_t len;
+
+       /* Last character is easy, and common. */
+       if (islast) {
+               if (db_get(sp, lno, 0, NULL, &len) || len == 0)
+                       return (0);
+               return (len - 1);
+       }
+
+       /* First character is easy, and common. */
+       if (sp->rcm == 0)
+               return (0);
+
+       return (vs_colpos(sp, lno, sp->rcm));
+}
+
+/*
+ * vs_colpos --
+ *     Return the physical column from the line that will display a
+ *     character closest to the specified screen column.
+ *
+ * PUBLIC: size_t vs_colpos __P((SCR *, db_recno_t, size_t));
+ */
+size_t
+vs_colpos(SCR *sp, db_recno_t lno, size_t cno)
+{
+       size_t chlen, curoff, len, llen, off, scno;
+       int ch = 0, leftright, listset;
+       CHAR_T *lp, *p;
+
+       /* Need the line to go any further. */
+       (void)db_get(sp, lno, 0, &lp, &llen);
+
+       /* Missing or empty lines are easy. */
+       if (lp == NULL || llen == 0)
+               return (0);
+
+       /* Store away the values of the list and leftright edit options. */
+       listset = O_ISSET(sp, O_LIST);
+       leftright = O_ISSET(sp, O_LEFTRIGHT);
+
+       /* Discard screen (logical) lines. */
+       off = cno / sp->cols;
+       cno %= sp->cols;
+       for (scno = 0, p = lp, len = llen; off--;) {
+               for (; len && scno < sp->cols; --len)
+                       scno += CHLEN(scno);
+
+               /*
+                * If reached the end of the physical line, return the last
+                * physical character in the line.
+                */
+               if (len == 0)
+                       return (llen - 1);
+
+               /*
+                * If folding screens (the historic vi screen format), past
+                * the end of the current screen, and the character was a tab,
+                * reset the current screen column to 0.  Otherwise, the rest
+                * of the character is displayed in the next screen.
+                */
+               if (leftright && ch == '\t')
+                       scno = 0;
+               else
+                       scno -= sp->cols;
+       }
+
+       /* Step through the line until reach the right character or EOL. */
+       for (curoff = scno; len--;) {
+               chlen = CHLEN(curoff);
+
+               /*
+                * If we've reached the specific character, there are three
+                * cases.
+                *
+                * 1: scno == cno, i.e. the current character ends at the
+                *    screen character we care about.
+                *      a: off < llen - 1, i.e. not the last character in
+                *         the line, return the offset of the next character.
+                *      b: else return the offset of the last character.
+                * 2: scno != cno, i.e. this character overruns the character
+                *    we care about, return the offset of this character.
+                */
+               if ((scno += chlen) >= cno) {
+                       off = p - lp;
+                       return (scno == cno ?
+                           (off < llen - 1 ? off : llen - 1) : off - 1);
+               }
+
+               TAB_RESET;
+       }
+
+       /* No such character; return the start of the last character. */
+       return (llen - 1);
+}
diff --git a/dist/nvi/vi/vs_smap.c b/dist/nvi/vi/vs_smap.c
new file mode 100644 (file)
index 0000000..1e21d82
--- /dev/null
@@ -0,0 +1,1234 @@
+/*     $NetBSD: vs_smap.c,v 1.2 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vs_smap.c,v 10.30 2002/01/19 21:59:07 skimo Exp (Berkeley) Date: 2002/01/19 21:59:07";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int     vs_deleteln __P((SCR *, int));
+static int     vs_insertln __P((SCR *, int));
+static int     vs_sm_delete __P((SCR *, db_recno_t));
+static int     vs_sm_down __P((SCR *, MARK *, db_recno_t, scroll_t, SMAP *));
+static int     vs_sm_erase __P((SCR *));
+static int     vs_sm_insert __P((SCR *, db_recno_t));
+static int     vs_sm_reset __P((SCR *, db_recno_t));
+static int     vs_sm_up __P((SCR *, MARK *, db_recno_t, scroll_t, SMAP *));
+
+/*
+ * vs_change --
+ *     Make a change to the screen.
+ *
+ * PUBLIC: int vs_change __P((SCR *, db_recno_t, lnop_t));
+ */
+int
+vs_change(SCR *sp, db_recno_t lno, lnop_t op)
+{
+       VI_PRIVATE *vip;
+       SMAP *p;
+       size_t cnt, oldy, oldx;
+
+       vip = VIP(sp);
+
+       /*
+        * XXX
+        * Very nasty special case.  The historic vi code displays a single
+        * space (or a '$' if the list option is set) for the first line in
+        * an "empty" file.  If we "insert" a line, that line gets scrolled
+        * down, not repainted, so it's incorrect when we refresh the screen.
+        * The vi text input functions detect it explicitly and don't insert
+        * a new line.
+        *
+        * Check for line #2 before going to the end of the file.
+        */
+       if (((op == LINE_APPEND && lno == 0) || 
+           (op == LINE_INSERT && lno == 1)) &&
+           !db_exist(sp, 2)) {
+               lno = 1;
+               op = LINE_RESET;
+       }
+
+       /* Appending is the same as inserting, if the line is incremented. */
+       if (op == LINE_APPEND) {
+               ++lno;
+               op = LINE_INSERT;
+       }
+
+       /* Ignore the change if the line is after the map. */
+       if (lno > TMAP->lno)
+               return (0);
+
+       /*
+        * If the line is before the map, and it's a decrement, decrement
+        * the map.  If it's an increment, increment the map.  Otherwise,
+        * ignore it.
+        */
+       if (lno < HMAP->lno) {
+               switch (op) {
+               case LINE_APPEND:
+                       abort();
+                       /* NOTREACHED */
+               case LINE_DELETE:
+                       for (p = HMAP, cnt = sp->t_rows; cnt--; ++p)
+                               --p->lno;
+                       if (sp->lno >= lno)
+                               --sp->lno;
+                       F_SET(vip, VIP_N_RENUMBER);
+                       break;
+               case LINE_INSERT:
+                       for (p = HMAP, cnt = sp->t_rows; cnt--; ++p)
+                               ++p->lno;
+                       if (sp->lno >= lno)
+                               ++sp->lno;
+                       F_SET(vip, VIP_N_RENUMBER);
+                       break;
+               case LINE_RESET:
+                       break;
+               }
+               return (0);
+       }
+
+       F_SET(vip, VIP_N_REFRESH);
+
+       /*
+        * Invalidate the line size cache, and invalidate the cursor if it's
+        * on this line,
+        */
+       VI_SCR_CFLUSH(vip);
+       if (sp->lno == lno)
+               F_SET(vip, VIP_CUR_INVALID);
+
+       /*
+        * If ex modifies the screen after ex output is already on the screen
+        * or if we've switched into ex canonical mode, don't touch it -- we'll
+        * get scrolling wrong, at best.
+        */
+       if (!F_ISSET(sp, SC_TINPUT_INFO) &&
+           (F_ISSET(sp, SC_SCR_EXWROTE) || VIP(sp)->totalcount > 1)) {
+               F_SET(vip, VIP_N_EX_REDRAW);
+               return (0);
+       }
+
+       /* Save and restore the cursor for these routines. */
+       (void)sp->gp->scr_cursor(sp, &oldy, &oldx);
+
+       switch (op) {
+       case LINE_DELETE:
+               if (vs_sm_delete(sp, lno))
+                       return (1);
+               if (sp->lno > lno)
+                       --sp->lno;
+               F_SET(vip, VIP_N_RENUMBER);
+               break;
+       case LINE_INSERT:
+               if (vs_sm_insert(sp, lno))
+                       return (1);
+               if (sp->lno > lno)
+                       ++sp->lno;
+               F_SET(vip, VIP_N_RENUMBER);
+               break;
+       case LINE_RESET:
+               if (vs_sm_reset(sp, lno))
+                       return (1);
+               break;
+       default:
+               abort();
+       }
+
+       (void)sp->gp->scr_move(sp, oldy, oldx);
+       return (0);
+}
+
+/*
+ * vs_sm_fill --
+ *     Fill in the screen map, placing the specified line at the
+ *     right position.  There isn't any way to tell if an SMAP
+ *     entry has been filled in, so this routine had better be
+ *     called with P_FILL set before anything else is done.
+ *
+ * !!!
+ * Unexported interface: if lno is OOBLNO, P_TOP means that the HMAP
+ * slot is already filled in, P_BOTTOM means that the TMAP slot is
+ * already filled in, and we just finish up the job.
+ *
+ * PUBLIC: int vs_sm_fill __P((SCR *, db_recno_t, pos_t));
+ */
+int
+vs_sm_fill(SCR *sp, db_recno_t lno, pos_t pos)
+{
+       SMAP *p, tmp;
+       size_t cnt;
+
+       /* Flush all cached information from the SMAP. */
+       for (p = HMAP, cnt = sp->t_rows; cnt--; ++p)
+               SMAP_FLUSH(p);
+
+       /*
+        * If the map is filled, the screen must be redrawn.
+        *
+        * XXX
+        * This is a bug.  We should try and figure out if the desired line
+        * is already in the map or close by -- scrolling the screen would
+        * be a lot better than redrawing.
+        */
+       F_SET(sp, SC_SCR_REDRAW);
+
+       switch (pos) {
+       case P_FILL:
+               tmp.lno = 1;
+               tmp.coff = 0;
+               tmp.soff = 1;
+
+               /* See if less than half a screen from the top. */
+               if (vs_sm_nlines(sp,
+                   &tmp, lno, HALFTEXT(sp)) <= HALFTEXT(sp)) {
+                       lno = 1;
+                       goto top;
+               }
+
+               /* See if less than half a screen from the bottom. */
+               if (db_last(sp, &tmp.lno))
+                       return (1);
+               tmp.coff = 0;
+               tmp.soff = vs_screens(sp, tmp.lno, NULL);
+               if (vs_sm_nlines(sp,
+                   &tmp, lno, HALFTEXT(sp)) <= HALFTEXT(sp)) {
+                       TMAP->lno = tmp.lno;
+                       TMAP->coff = tmp.coff;
+                       TMAP->soff = tmp.soff;
+                       goto bottom;
+               }
+               goto middle;
+       case P_TOP:
+               if (lno != OOBLNO) {
+top:                   HMAP->lno = lno;
+                       HMAP->coff = 0;
+                       HMAP->soff = 1;
+               }
+               /* If we fail, just punt. */
+               for (p = HMAP, cnt = sp->t_rows; --cnt; ++p)
+                       if (vs_sm_next(sp, p, p + 1))
+                               goto err;
+               break;
+       case P_MIDDLE:
+               /* If we fail, guess that the file is too small. */
+middle:                p = HMAP + sp->t_rows / 2;
+               p->lno = lno;
+               p->coff = 0;
+               p->soff = 1;
+               for (; p > HMAP; --p)
+                       if (vs_sm_prev(sp, p, p - 1)) {
+                               lno = 1;
+                               goto top;
+                       }
+
+               /* If we fail, just punt. */
+               p = HMAP + sp->t_rows / 2;
+               for (; p < TMAP; ++p)
+                       if (vs_sm_next(sp, p, p + 1))
+                               goto err;
+               break;
+       case P_BOTTOM:
+               if (lno != OOBLNO) {
+                       TMAP->lno = lno;
+                       TMAP->coff = 0;
+                       TMAP->soff = vs_screens(sp, lno, NULL);
+               }
+               /* If we fail, guess that the file is too small. */
+bottom:                for (p = TMAP; p > HMAP; --p)
+                       if (vs_sm_prev(sp, p, p - 1)) {
+                               lno = 1;
+                               goto top;
+                       }
+               break;
+       default:
+               abort();
+       }
+       return (0);
+
+       /*
+        * Try and put *something* on the screen.  If this fails, we have a
+        * serious hard error.
+        */
+err:   HMAP->lno = 1;
+       HMAP->coff = 0;
+       HMAP->soff = 1;
+       for (p = HMAP; p < TMAP; ++p)
+               if (vs_sm_next(sp, p, p + 1))
+                       return (1);
+       return (0);
+}
+
+/*
+ * For the routines vs_sm_reset, vs_sm_delete and vs_sm_insert: if the
+ * screen contains only a single line (whether because the screen is small
+ * or the line large), it gets fairly exciting.  Skip the fun, set a flag
+ * so the screen map is refilled and the screen redrawn, and return.  This
+ * is amazingly slow, but it's not clear that anyone will care.
+ */
+#define        HANDLE_WEIRDNESS(cnt) {                                         \
+       if (cnt >= sp->t_rows) {                                        \
+               F_SET(sp, SC_SCR_REFORMAT);                             \
+               return (0);                                             \
+       }                                                               \
+}
+
+/*
+ * vs_sm_delete --
+ *     Delete a line out of the SMAP.
+ */
+static int
+vs_sm_delete(SCR *sp, db_recno_t lno)
+{
+       SMAP *p, *t;
+       size_t cnt_orig;
+
+       /*
+        * Find the line in the map, and count the number of screen lines
+        * which display any part of the deleted line.
+        */
+       for (p = HMAP; p->lno != lno; ++p);
+       if (O_ISSET(sp, O_LEFTRIGHT))
+               cnt_orig = 1;
+       else
+               for (cnt_orig = 1, t = p + 1;
+                   t <= TMAP && t->lno == lno; ++cnt_orig, ++t);
+
+       HANDLE_WEIRDNESS(cnt_orig);
+
+       /* Delete that many lines from the screen. */
+       (void)sp->gp->scr_move(sp, p - HMAP, 0);
+       if (vs_deleteln(sp, cnt_orig))
+               return (1);
+
+       /* Shift the screen map up. */
+       memmove(p, p + cnt_orig, (((TMAP - p) - cnt_orig) + 1) * sizeof(SMAP));
+
+       /* Decrement the line numbers for the rest of the map. */
+       for (t = TMAP - cnt_orig; p <= t; ++p)
+               --p->lno;
+
+       /* Display the new lines. */
+       for (p = TMAP - cnt_orig;;) {
+               if (p < TMAP && vs_sm_next(sp, p, p + 1))
+                       return (1);
+               /* vs_sm_next() flushed the cache. */
+               if (vs_line(sp, ++p, NULL, NULL))
+                       return (1);
+               if (p == TMAP)
+                       break;
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_insert --
+ *     Insert a line into the SMAP.
+ */
+static int
+vs_sm_insert(SCR *sp, db_recno_t lno)
+{
+       SMAP *p, *t;
+       size_t cnt_orig, cnt, coff;
+
+       /* Save the offset. */
+       coff = HMAP->coff;
+
+       /*
+        * Find the line in the map, find out how many screen lines
+        * needed to display the line.
+        */
+       for (p = HMAP; p->lno != lno; ++p);
+
+       cnt_orig = vs_screens(sp, lno, NULL);
+       HANDLE_WEIRDNESS(cnt_orig);
+
+       /*
+        * The lines left in the screen override the number of screen
+        * lines in the inserted line.
+        */
+       cnt = (TMAP - p) + 1;
+       if (cnt_orig > cnt)
+               cnt_orig = cnt;
+
+       /* Push down that many lines. */
+       (void)sp->gp->scr_move(sp, p - HMAP, 0);
+       if (vs_insertln(sp, cnt_orig))
+               return (1);
+
+       /* Shift the screen map down. */
+       memmove(p + cnt_orig, p, (((TMAP - p) - cnt_orig) + 1) * sizeof(SMAP));
+
+       /* Increment the line numbers for the rest of the map. */
+       for (t = p + cnt_orig; t <= TMAP; ++t)
+               ++t->lno;
+
+       /* Fill in the SMAP for the new lines, and display. */
+       for (cnt = 1, t = p; cnt <= cnt_orig; ++t, ++cnt) {
+               t->lno = lno;
+               t->coff = coff;
+               t->soff = cnt;
+               SMAP_FLUSH(t);
+               if (vs_line(sp, t, NULL, NULL))
+                       return (1);
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_reset --
+ *     Reset a line in the SMAP.
+ */
+static int
+vs_sm_reset(SCR *sp, db_recno_t lno)
+{
+       SMAP *p, *t;
+       size_t cnt_orig, cnt_new, cnt, diff;
+
+       /*
+        * See if the number of on-screen rows taken up by the old display
+        * for the line is the same as the number needed for the new one.
+        * If so, repaint, otherwise do it the hard way.
+        */
+       for (p = HMAP; p->lno != lno; ++p);
+       if (O_ISSET(sp, O_LEFTRIGHT)) {
+               t = p;
+               cnt_orig = cnt_new = 1;
+       } else {
+               for (cnt_orig = 0,
+                   t = p; t <= TMAP && t->lno == lno; ++cnt_orig, ++t);
+               cnt_new = vs_screens(sp, lno, NULL);
+       }
+
+       HANDLE_WEIRDNESS(cnt_orig);
+
+       if (cnt_orig == cnt_new) {
+               do {
+                       SMAP_FLUSH(p);
+                       if (vs_line(sp, p, NULL, NULL))
+                               return (1);
+               } while (++p < t);
+               return (0);
+       }
+
+       if (cnt_orig < cnt_new) {
+               /* Get the difference. */
+               diff = cnt_new - cnt_orig;
+
+               /*
+                * The lines left in the screen override the number of screen
+                * lines in the inserted line.
+                */
+               cnt = (TMAP - p) + 1;
+               if (diff > cnt)
+                       diff = cnt;
+
+               /* If there are any following lines, push them down. */
+               if (cnt > 1) {
+                       (void)sp->gp->scr_move(sp, p - HMAP, 0);
+                       if (vs_insertln(sp, diff))
+                               return (1);
+
+                       /* Shift the screen map down. */
+                       memmove(p + diff, p,
+                           (((TMAP - p) - diff) + 1) * sizeof(SMAP));
+               }
+
+               /* Fill in the SMAP for the replaced line, and display. */
+               for (cnt = 1, t = p; cnt_new-- && t <= TMAP; ++t, ++cnt) {
+                       t->lno = lno;
+                       t->soff = cnt;
+                       SMAP_FLUSH(t);
+                       if (vs_line(sp, t, NULL, NULL))
+                               return (1);
+               }
+       } else {
+               /* Get the difference. */
+               diff = cnt_orig - cnt_new;
+
+               /* Delete that many lines from the screen. */
+               (void)sp->gp->scr_move(sp, p - HMAP, 0);
+               if (vs_deleteln(sp, diff))
+                       return (1);
+
+               /* Shift the screen map up. */
+               memmove(p, p + diff, (((TMAP - p) - diff) + 1) * sizeof(SMAP));
+
+               /* Fill in the SMAP for the replaced line, and display. */
+               for (cnt = 1, t = p; cnt_new--; ++t, ++cnt) {
+                       t->lno = lno;
+                       t->soff = cnt;
+                       SMAP_FLUSH(t);
+                       if (vs_line(sp, t, NULL, NULL))
+                               return (1);
+               }
+
+               /* Display the new lines at the bottom of the screen. */
+               for (t = TMAP - diff;;) {
+                       if (t < TMAP && vs_sm_next(sp, t, t + 1))
+                               return (1);
+                       /* vs_sm_next() flushed the cache. */
+                       if (vs_line(sp, ++t, NULL, NULL))
+                               return (1);
+                       if (t == TMAP)
+                               break;
+               }
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_scroll
+ *     Scroll the SMAP up/down count logical lines.  Different
+ *     semantics based on the vi command, *sigh*.
+ *
+ * PUBLIC: int vs_sm_scroll __P((SCR *, MARK *, db_recno_t, scroll_t));
+ */
+int
+vs_sm_scroll(SCR *sp, MARK *rp, db_recno_t count, scroll_t scmd)
+{
+       SMAP *smp;
+
+       /*
+        * Invalidate the cursor.  The line is probably going to change,
+        * (although for ^E and ^Y it may not).  In any case, the scroll
+        * routines move the cursor to draw things.
+        */
+       F_SET(VIP(sp), VIP_CUR_INVALID);
+
+       /* Find the cursor in the screen. */
+       if (vs_sm_cursor(sp, &smp))
+               return (1);
+
+       switch (scmd) {
+       case CNTRL_B:
+       case CNTRL_U:
+       case CNTRL_Y:
+       case Z_CARAT:
+               if (vs_sm_down(sp, rp, count, scmd, smp))
+                       return (1);
+               break;
+       case CNTRL_D:
+       case CNTRL_E:
+       case CNTRL_F:
+       case Z_PLUS:
+               if (vs_sm_up(sp, rp, count, scmd, smp))
+                       return (1);
+               break;
+       default:
+               abort();
+       }
+
+       /*
+        * !!!
+        * If we're at the start of a line, go for the first non-blank.
+        * This makes it look like the old vi, even though we're moving
+        * around by logical lines, not physical ones.
+        *
+        * XXX
+        * In the presence of a long line, which has more than a screen
+        * width of leading spaces, this code can cause a cursor warp.
+        * Live with it.
+        */
+       if (scmd != CNTRL_E && scmd != CNTRL_Y &&
+           rp->cno == 0 && nonblank(sp, rp->lno, &rp->cno))
+               return (1);
+
+       return (0);
+}
+
+/*
+ * vs_sm_up --
+ *     Scroll the SMAP up count logical lines.
+ */
+static int
+vs_sm_up(SCR *sp, MARK *rp, db_recno_t count, scroll_t scmd, SMAP *smp)
+{
+       int cursor_set, echanged, zset;
+       SMAP *ssmp, s1, s2;
+
+       /*
+        * Check to see if movement is possible.
+        *
+        * Get the line after the map.  If that line is a new one (and if
+        * O_LEFTRIGHT option is set, this has to be true), and the next
+        * line doesn't exist, and the cursor doesn't move, or the cursor
+        * isn't even on the screen, or the cursor is already at the last
+        * line in the map, it's an error.  If that test succeeded because
+        * the cursor wasn't at the end of the map, test to see if the map
+        * is mostly empty.
+        */
+       if (vs_sm_next(sp, TMAP, &s1))
+               return (1);
+       if (s1.lno > TMAP->lno && !db_exist(sp, s1.lno)) {
+               if (scmd == CNTRL_E || scmd == Z_PLUS || smp == TMAP) {
+                       v_eof(sp, NULL);
+                       return (1);
+               }
+               if (vs_sm_next(sp, smp, &s1))
+                       return (1);
+               if (s1.lno > smp->lno && !db_exist(sp, s1.lno)) {
+                       v_eof(sp, NULL);
+                       return (1);
+               }
+       }
+
+       /*
+        * Small screens: see vs_refresh.c section 6a.
+        *
+        * If it's a small screen, and the movement isn't larger than a
+        * screen, i.e some context will remain, open up the screen and
+        * display by scrolling.  In this case, the cursor moves down one
+        * line for each line displayed.  Otherwise, erase/compress and
+        * repaint, and move the cursor to the first line in the screen.
+        * Note, the ^F command is always in the latter case, for historical
+        * reasons.
+        */
+       cursor_set = 0;
+       if (IS_SMALL(sp)) {
+               if (count >= sp->t_maxrows || scmd == CNTRL_F) {
+                       s1 = TMAP[0];
+                       if (vs_sm_erase(sp))
+                               return (1);
+                       for (; count--; s1 = s2) {
+                               if (vs_sm_next(sp, &s1, &s2))
+                                       return (1);
+                               if (s2.lno != s1.lno && !db_exist(sp, s2.lno))
+                                       break;
+                       }
+                       TMAP[0] = s2;
+                       if (vs_sm_fill(sp, OOBLNO, P_BOTTOM))
+                               return (1);
+                       return (vs_sm_position(sp, rp, 0, P_TOP));
+               }
+               cursor_set = scmd == CNTRL_E || vs_sm_cursor(sp, &ssmp);
+               for (; count &&
+                   sp->t_rows != sp->t_maxrows; --count, ++sp->t_rows) {
+                       if (vs_sm_next(sp, TMAP, &s1))
+                               return (1);
+                       if (TMAP->lno != s1.lno && !db_exist(sp, s1.lno))
+                               break;
+                       *++TMAP = s1;
+                       /* vs_sm_next() flushed the cache. */
+                       if (vs_line(sp, TMAP, NULL, NULL))
+                               return (1);
+
+                       if (!cursor_set)
+                               ++ssmp;
+               }
+               if (!cursor_set) {
+                       rp->lno = ssmp->lno;
+                       rp->cno = ssmp->c_sboff;
+               }
+               if (count == 0)
+                       return (0);
+       }
+
+       for (echanged = zset = 0; count; --count) {
+               /* Decide what would show up on the screen. */
+               if (vs_sm_next(sp, TMAP, &s1))
+                       return (1);
+
+               /* If the line doesn't exist, we're done. */
+               if (TMAP->lno != s1.lno && !db_exist(sp, s1.lno))
+                       break;
+
+               /* Scroll the screen cursor up one logical line. */
+               if (vs_sm_1up(sp))
+                       return (1);
+               switch (scmd) {
+               case CNTRL_E:
+                       if (smp > HMAP)
+                               --smp;
+                       else
+                               echanged = 1;
+                       break;
+               case Z_PLUS:
+                       if (zset) {
+                               if (smp > HMAP)
+                                       --smp;
+                       } else {
+                               smp = TMAP;
+                               zset = 1;
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       break;
+               }
+       }
+
+       if (cursor_set)
+               return(0);
+
+       switch (scmd) {
+       case CNTRL_E:
+               /*
+                * On a ^E that was forced to change lines, try and keep the
+                * cursor as close as possible to the last position, but also
+                * set it up so that the next "real" movement will return the
+                * cursor to the closest position to the last real movement.
+                */
+               if (echanged) {
+                       rp->lno = smp->lno;
+                       rp->cno = vs_colpos(sp, smp->lno,
+                           (O_ISSET(sp, O_LEFTRIGHT) ? 
+                           smp->coff : (smp->soff - 1) * sp->cols) +
+                           sp->rcm % sp->cols);
+               }
+               return (0);
+       case CNTRL_F:
+               /*
+                * If there are more lines, the ^F command is positioned at
+                * the first line of the screen.
+                */
+               if (!count) {
+                       smp = HMAP;
+                       break;
+               }
+               /* FALLTHROUGH */
+       case CNTRL_D:
+               /*
+                * The ^D and ^F commands move the cursor towards EOF
+                * if there are more lines to move.  Check to be sure
+                * the lines actually exist.  (They may not if the
+                * file is smaller than the screen.)
+                */
+               for (; count; --count, ++smp)
+                       if (smp == TMAP || !db_exist(sp, smp[1].lno))
+                               break;
+               break;
+       case Z_PLUS:
+                /* The z+ command moves the cursor to the first new line. */
+               break;
+       default:
+               abort();
+       }
+
+       if (!SMAP_CACHE(smp) && vs_line(sp, smp, NULL, NULL))
+               return (1);
+       rp->lno = smp->lno;
+       rp->cno = smp->c_scoff == 255 ? 0 : smp->c_sboff;
+       return (0);
+}
+
+/*
+ * vs_sm_1up --
+ *     Scroll the SMAP up one.
+ *
+ * PUBLIC: int vs_sm_1up __P((SCR *));
+ */
+int
+vs_sm_1up(SCR *sp)
+{
+       /*
+        * Delete the top line of the screen.  Shift the screen map
+        * up and display a new line at the bottom of the screen.
+        */
+       (void)sp->gp->scr_move(sp, 0, 0);
+       if (vs_deleteln(sp, 1))
+               return (1);
+
+       /* One-line screens can fail. */
+       if (IS_ONELINE(sp)) {
+               if (vs_sm_next(sp, TMAP, TMAP))
+                       return (1);
+       } else {
+               memmove(HMAP, HMAP + 1, (sp->rows - 1) * sizeof(SMAP));
+               if (vs_sm_next(sp, TMAP - 1, TMAP))
+                       return (1);
+       }
+       /* vs_sm_next() flushed the cache. */
+       return (vs_line(sp, TMAP, NULL, NULL));
+}
+
+/*
+ * vs_deleteln --
+ *     Delete a line a la curses, make sure to put the information
+ *     line and other screens back.
+ */
+static int
+vs_deleteln(SCR *sp, int cnt)
+{
+       GS *gp;
+       size_t oldy, oldx;
+
+       gp = sp->gp;
+
+       /* If the screen is vertically split, we can't scroll it. */
+       if (IS_VSPLIT(sp)) {
+               F_SET(sp, SC_SCR_REDRAW);
+               return (0);
+       }
+               
+       if (IS_ONELINE(sp))
+               (void)gp->scr_clrtoeol(sp);
+       else {
+               (void)gp->scr_cursor(sp, &oldy, &oldx);
+               while (cnt--) {
+                       (void)gp->scr_deleteln(sp);
+                       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+                       (void)gp->scr_insertln(sp);
+                       (void)gp->scr_move(sp, oldy, oldx);
+               }
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_down --
+ *     Scroll the SMAP down count logical lines.
+ */
+static int
+vs_sm_down(SCR *sp, MARK *rp, db_recno_t count, scroll_t scmd, SMAP *smp)
+{
+       SMAP *ssmp, s1, s2;
+       int cursor_set, ychanged, zset;
+
+       /* Check to see if movement is possible. */
+       if (HMAP->lno == 1 &&
+           (O_ISSET(sp, O_LEFTRIGHT) || HMAP->soff == 1) &&
+           (scmd == CNTRL_Y || scmd == Z_CARAT || smp == HMAP)) {
+               v_sof(sp, NULL);
+               return (1);
+       }
+
+       /*
+        * Small screens: see vs_refresh.c section 6a.
+        *
+        * If it's a small screen, and the movement isn't larger than a
+        * screen, i.e some context will remain, open up the screen and
+        * display by scrolling.  In this case, the cursor moves up one
+        * line for each line displayed.  Otherwise, erase/compress and
+        * repaint, and move the cursor to the first line in the screen.
+        * Note, the ^B command is always in the latter case, for historical
+        * reasons.
+        */
+       cursor_set = scmd == CNTRL_Y;
+       if (IS_SMALL(sp)) {
+               if (count >= sp->t_maxrows || scmd == CNTRL_B) {
+                       s1 = HMAP[0];
+                       if (vs_sm_erase(sp))
+                               return (1);
+                       for (; count--; s1 = s2) {
+                               if (vs_sm_prev(sp, &s1, &s2))
+                                       return (1);
+                               if (s2.lno == 1 &&
+                                   (O_ISSET(sp, O_LEFTRIGHT) || s2.soff == 1))
+                                       break;
+                       }
+                       HMAP[0] = s2;
+                       if (vs_sm_fill(sp, OOBLNO, P_TOP))
+                               return (1);
+                       return (vs_sm_position(sp, rp, 0, P_BOTTOM));
+               }
+               cursor_set = scmd == CNTRL_Y || vs_sm_cursor(sp, &ssmp);
+               for (; count &&
+                   sp->t_rows != sp->t_maxrows; --count, ++sp->t_rows) {
+                       if (HMAP->lno == 1 &&
+                           (O_ISSET(sp, O_LEFTRIGHT) || HMAP->soff == 1))
+                               break;
+                       ++TMAP;
+                       if (vs_sm_1down(sp))
+                               return (1);
+               }
+               if (!cursor_set) {
+                       rp->lno = ssmp->lno;
+                       rp->cno = ssmp->c_sboff;
+               }
+               if (count == 0)
+                       return (0);
+       }
+
+       for (ychanged = zset = 0; count; --count) {
+               /* If the line doesn't exist, we're done. */
+               if (HMAP->lno == 1 &&
+                   (O_ISSET(sp, O_LEFTRIGHT) || HMAP->soff == 1))
+                       break;
+
+               /* Scroll the screen and cursor down one logical line. */
+               if (vs_sm_1down(sp))
+                       return (1);
+               switch (scmd) {
+               case CNTRL_Y:
+                       if (smp < TMAP)
+                               ++smp;
+                       else
+                               ychanged = 1;
+                       break;
+               case Z_CARAT:
+                       if (zset) {
+                               if (smp < TMAP)
+                                       ++smp;
+                       } else {
+                               smp = HMAP;
+                               zset = 1;
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       break;
+               }
+       }
+
+       if (scmd != CNTRL_Y && cursor_set)
+               return(0);
+
+       switch (scmd) {
+       case CNTRL_B:
+               /*
+                * If there are more lines, the ^B command is positioned at
+                * the last line of the screen.  However, the line may not
+                * exist.
+                */
+               if (!count) {
+                       for (smp = TMAP; smp > HMAP; --smp)
+                               if (db_exist(sp, smp->lno))
+                                       break;
+                       break;
+               }
+               /* FALLTHROUGH */
+       case CNTRL_U:
+               /*
+                * The ^B and ^U commands move the cursor towards SOF
+                * if there are more lines to move.
+                */
+               if (count < (db_recno_t)(smp - HMAP))
+                       smp -= count;
+               else
+                       smp = HMAP;
+               break;
+       case CNTRL_Y:
+               /*
+                * On a ^Y that was forced to change lines, try and keep the
+                * cursor as close as possible to the last position, but also
+                * set it up so that the next "real" movement will return the
+                * cursor to the closest position to the last real movement.
+                */
+               if (ychanged) {
+                       rp->lno = smp->lno;
+                       rp->cno = vs_colpos(sp, smp->lno,
+                           (O_ISSET(sp, O_LEFTRIGHT) ? 
+                           smp->coff : (smp->soff - 1) * sp->cols) +
+                           sp->rcm % sp->cols);
+               }
+               return (0);
+       case Z_CARAT:
+                /* The z^ command moves the cursor to the first new line. */
+               break;
+       default:
+               abort();
+       }
+
+       if (!SMAP_CACHE(smp) && vs_line(sp, smp, NULL, NULL))
+               return (1);
+       rp->lno = smp->lno;
+       rp->cno = smp->c_scoff == 255 ? 0 : smp->c_sboff;
+       return (0);
+}
+
+/*
+ * vs_sm_erase --
+ *     Erase the small screen area for the scrolling functions.
+ */
+static int
+vs_sm_erase(SCR *sp)
+{
+       GS *gp;
+
+       gp = sp->gp;
+       (void)gp->scr_move(sp, LASTLINE(sp), 0);
+       (void)gp->scr_clrtoeol(sp);
+       for (; sp->t_rows > sp->t_minrows; --sp->t_rows, --TMAP) {
+               (void)gp->scr_move(sp, TMAP - HMAP, 0);
+               (void)gp->scr_clrtoeol(sp);
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_1down --
+ *     Scroll the SMAP down one.
+ *
+ * PUBLIC: int vs_sm_1down __P((SCR *));
+ */
+int
+vs_sm_1down(SCR *sp)
+{
+       /*
+        * Insert a line at the top of the screen.  Shift the screen map
+        * down and display a new line at the top of the screen.
+        */
+       (void)sp->gp->scr_move(sp, 0, 0);
+       if (vs_insertln(sp, 1))
+               return (1);
+
+       /* One-line screens can fail. */
+       if (IS_ONELINE(sp)) {
+               if (vs_sm_prev(sp, HMAP, HMAP))
+                       return (1);
+       } else {
+               memmove(HMAP + 1, HMAP, (sp->rows - 1) * sizeof(SMAP));
+               if (vs_sm_prev(sp, HMAP + 1, HMAP))
+                       return (1);
+       }
+       /* vs_sm_prev() flushed the cache. */
+       return (vs_line(sp, HMAP, NULL, NULL));
+}
+
+/*
+ * vs_insertln --
+ *     Insert a line a la curses, make sure to put the information
+ *     line and other screens back.
+ */
+static int
+vs_insertln(SCR *sp, int cnt)
+{
+       GS *gp;
+       size_t oldy, oldx;
+
+       gp = sp->gp;
+
+       /* If the screen is vertically split, we can't scroll it. */
+       if (IS_VSPLIT(sp)) {
+               F_SET(sp, SC_SCR_REDRAW);
+               return (0);
+       }
+               
+       if (IS_ONELINE(sp)) {
+               (void)gp->scr_move(sp, LASTLINE(sp), 0);
+               (void)gp->scr_clrtoeol(sp);
+       } else {
+               (void)gp->scr_cursor(sp, &oldy, &oldx);
+               while (cnt--) {
+                       (void)gp->scr_move(sp, LASTLINE(sp) - 1, 0);
+                       (void)gp->scr_deleteln(sp);
+                       (void)gp->scr_move(sp, oldy, oldx);
+                       (void)gp->scr_insertln(sp);
+               }
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_next --
+ *     Fill in the next entry in the SMAP.
+ *
+ * PUBLIC: int vs_sm_next __P((SCR *, SMAP *, SMAP *));
+ */
+int
+vs_sm_next(SCR *sp, SMAP *p, SMAP *t)
+{
+       size_t lcnt;
+
+       SMAP_FLUSH(t);
+       if (O_ISSET(sp, O_LEFTRIGHT)) {
+               t->lno = p->lno + 1;
+               t->coff = p->coff;
+       } else {
+               lcnt = vs_screens(sp, p->lno, NULL);
+               if (lcnt == p->soff) {
+                       t->lno = p->lno + 1;
+                       t->soff = 1;
+               } else {
+                       t->lno = p->lno;
+                       t->soff = p->soff + 1;
+               }
+       }
+       return (0);
+}
+
+/*
+ * vs_sm_prev --
+ *     Fill in the previous entry in the SMAP.
+ *
+ * PUBLIC: int vs_sm_prev __P((SCR *, SMAP *, SMAP *));
+ */
+int
+vs_sm_prev(SCR *sp, SMAP *p, SMAP *t)
+{
+       SMAP_FLUSH(t);
+       if (O_ISSET(sp, O_LEFTRIGHT)) {
+               t->lno = p->lno - 1;
+               t->coff = p->coff;
+       } else {
+               if (p->soff != 1) {
+                       t->lno = p->lno;
+                       t->soff = p->soff - 1;
+               } else {
+                       t->lno = p->lno - 1;
+                       t->soff = vs_screens(sp, t->lno, NULL);
+               }
+       }
+       return (t->lno == 0);
+}
+
+/*
+ * vs_sm_cursor --
+ *     Return the SMAP entry referenced by the cursor.
+ *
+ * PUBLIC: int vs_sm_cursor __P((SCR *, SMAP **));
+ */
+int
+vs_sm_cursor(SCR *sp, SMAP **smpp)
+{
+       SMAP *p;
+
+       /* See if the cursor is not in the map. */
+       if (sp->lno < HMAP->lno || sp->lno > TMAP->lno)
+               return (1);
+
+       /* Find the first occurence of the line. */
+       for (p = HMAP; p->lno != sp->lno; ++p);
+
+       /* Fill in the map information until we find the right line. */
+       for (; p <= TMAP; ++p) {
+               /* Short lines are common and easy to detect. */
+               if (p != TMAP && (p + 1)->lno != p->lno) {
+                       *smpp = p;
+                       return (0);
+               }
+               if (!SMAP_CACHE(p) && vs_line(sp, p, NULL, NULL))
+                       return (1);
+               if (p->c_eboff >= sp->cno) {
+                       *smpp = p;
+                       return (0);
+               }
+       }
+
+       /* It was past the end of the map after all. */
+       return (1);
+}
+
+/*
+ * vs_sm_position --
+ *     Return the line/column of the top, middle or last line on the screen.
+ *     (The vi H, M and L commands.)  Here because only the screen routines
+ *     know what's really out there.
+ *
+ * PUBLIC: int vs_sm_position __P((SCR *, MARK *, u_long, pos_t));
+ */
+int
+vs_sm_position(SCR *sp, MARK *rp, u_long cnt, pos_t pos)
+{
+       SMAP *smp;
+       db_recno_t last;
+
+       switch (pos) {
+       case P_TOP:
+               /*
+                * !!!
+                * Historically, an invalid count to the H command failed.
+                * We do nothing special here, just making sure that H in
+                * an empty screen works.
+                */
+               if (cnt > (u_long)(TMAP - HMAP))
+                       goto sof;
+               smp = HMAP + cnt;
+               if (cnt && !db_exist(sp, smp->lno)) {
+sof:                   msgq(sp, M_BERR, "220|Movement past the end-of-screen");
+                       return (1);
+               }
+               break;
+       case P_MIDDLE:
+               /*
+                * !!!
+                * Historically, a count to the M command was ignored.
+                * If the screen isn't filled, find the middle of what's
+                * real and move there.
+                */
+               if (!db_exist(sp, TMAP->lno)) {
+                       if (db_last(sp, &last))
+                               return (1);
+                       for (smp = TMAP; smp->lno > last && smp > HMAP; --smp);
+                       if (smp > HMAP)
+                               smp -= (smp - HMAP) / 2;
+               } else
+                       smp = (HMAP + (TMAP - HMAP) / 2) + cnt;
+               break;
+       case P_BOTTOM:
+               /*
+                * !!!
+                * Historically, an invalid count to the L command failed.
+                * If the screen isn't filled, find the bottom of what's
+                * real and try to offset from there.
+                */
+               if (cnt > (u_long)(TMAP - HMAP))
+                       goto eof;
+               smp = TMAP - cnt;
+               if (!db_exist(sp, smp->lno)) {
+                       if (db_last(sp, &last))
+                               return (1);
+                       for (; smp->lno > last && smp > HMAP; --smp);
+                       if (cnt > (u_long)(smp - HMAP)) {
+eof:                           msgq(sp, M_BERR,
+                           "221|Movement past the beginning-of-screen");
+                               return (1);
+                       }
+                       smp -= cnt;
+               }
+               break;
+       default:
+               abort();
+       }
+
+       /* Make sure that the cached information is valid. */
+       if (!SMAP_CACHE(smp) && vs_line(sp, smp, NULL, NULL))
+               return (1);
+       rp->lno = smp->lno;
+       rp->cno = smp->c_sboff;
+
+       return (0);
+}
+
+/*
+ * vs_sm_nlines --
+ *     Return the number of screen lines from an SMAP entry to the
+ *     start of some file line, less than a maximum value.
+ *
+ * PUBLIC: db_recno_t vs_sm_nlines __P((SCR *, SMAP *, db_recno_t, size_t));
+ */
+db_recno_t
+vs_sm_nlines(SCR *sp, SMAP *from_sp, db_recno_t to_lno, size_t max)
+{
+       db_recno_t lno, lcnt;
+
+       if (O_ISSET(sp, O_LEFTRIGHT))
+               return (from_sp->lno > to_lno ?
+                   from_sp->lno - to_lno : to_lno - from_sp->lno);
+
+       if (from_sp->lno == to_lno)
+               return (from_sp->soff - 1);
+
+       if (from_sp->lno > to_lno) {
+               lcnt = from_sp->soff - 1;       /* Correct for off-by-one. */
+               for (lno = from_sp->lno; --lno >= to_lno && lcnt <= max;)
+                       lcnt += vs_screens(sp, lno, NULL);
+       } else {
+               lno = from_sp->lno;
+               lcnt = (vs_screens(sp, lno, NULL) - from_sp->soff) + 1;
+               for (; ++lno < to_lno && lcnt <= max;)
+                       lcnt += vs_screens(sp, lno, NULL);
+       }
+       return (lcnt);
+}
diff --git a/dist/nvi/vi/vs_split.c b/dist/nvi/vi/vs_split.c
new file mode 100644 (file)
index 0000000..51f1665
--- /dev/null
@@ -0,0 +1,970 @@
+/*     $NetBSD: vs_split.c,v 1.3 2009/01/18 03:45:50 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "Id: vs_split.c,v 10.42 2001/06/25 15:19:38 skimo Exp (Berkeley) Date: 2001/06/25 15:19:38";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+typedef enum { HORIZ_FOLLOW, HORIZ_PRECEDE, VERT_FOLLOW, VERT_PRECEDE } jdir_t;
+
+static SCR     *vs_getbg __P((SCR *, const char *));
+static void      vs_insert __P((SCR *sp, WIN *wp));
+static int      vs_join __P((SCR *, SCR **, jdir_t *));
+
+/*
+ * vs_split --
+ *     Create a new screen, horizontally.
+ *
+ * PUBLIC: int vs_split __P((SCR *, SCR *, int));
+ */
+int
+vs_split(SCR *sp, SCR *new, int ccl)
+                     
+                               /* Colon-command line split. */
+{
+       GS *gp;
+       SMAP *smp;
+       size_t half;
+       int issmallscreen, splitup;
+
+       gp = sp->gp;
+
+       /* Check to see if it's possible. */
+       /* XXX: The IS_ONELINE fix will change this, too. */
+       if (sp->rows < 4) {
+               msgq(sp, M_ERR,
+                   "222|Screen must be larger than %d lines to split", 4 - 1);
+               return (1);
+       }
+
+       /* Wait for any messages in the screen. */
+       vs_resolve(sp, NULL, 1);
+
+       /* Get a new screen map. */
+       CALLOC(sp, _HMAP(new), SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
+       if (_HMAP(new) == NULL)
+               return (1);
+       _HMAP(new)->lno = sp->lno;
+       _HMAP(new)->coff = 0;
+       _HMAP(new)->soff = 1;
+
+       /* Split the screen in half. */
+       half = sp->rows / 2;
+       if (ccl && half > 6)
+               half = 6;
+
+       /*
+        * Small screens: see vs_refresh.c section 6a.  Set a flag so
+        * we know to fix the screen up later.
+        */
+       issmallscreen = IS_SMALL(sp);
+
+       /* The columns in the screen don't change. */
+       new->coff = sp->coff;
+       new->cols = sp->cols;
+
+       /*
+        * Split the screen, and link the screens together.  If creating a
+        * screen to edit the colon command line or the cursor is in the top
+        * half of the current screen, the new screen goes under the current
+        * screen.  Else, it goes above the current screen.
+        *
+        * Recalculate current cursor position based on sp->lno, we're called
+        * with the cursor on the colon command line.  Then split the screen
+        * in half and update the shared information.
+        */
+       splitup =
+           !ccl && (vs_sm_cursor(sp, &smp) ? 0 : (size_t)(smp - HMAP) + 1) >= half;
+       if (splitup) {                          /* Old is bottom half. */
+               new->rows = sp->rows - half;    /* New. */
+               new->roff = sp->roff;
+               sp->rows = half;                /* Old. */
+               sp->roff += new->rows;
+
+               /*
+                * If the parent is the bottom half of the screen, shift
+                * the map down to match on-screen text.
+                */
+               memcpy(_HMAP(sp), _HMAP(sp) + new->rows,
+                   (sp->t_maxrows - new->rows) * sizeof(SMAP));
+       } else {                                /* Old is top half. */
+               new->rows = half;               /* New. */
+               sp->rows -= half;               /* Old. */
+               new->roff = sp->roff + sp->rows;
+       }
+
+       /* Adjust maximum text count. */
+       sp->t_maxrows = IS_ONELINE(sp) ? 1 : sp->rows - 1;
+       new->t_maxrows = IS_ONELINE(new) ? 1 : new->rows - 1;
+
+       /*
+        * Small screens: see vs_refresh.c, section 6a.
+        *
+        * The child may have different screen options sizes than the parent,
+        * so use them.  Guarantee that text counts aren't larger than the
+        * new screen sizes.
+        */
+       if (issmallscreen) {
+               /* Fix the text line count for the parent. */
+               if (splitup)
+                       sp->t_rows -= new->rows;
+
+               /* Fix the parent screen. */
+               if (sp->t_rows > sp->t_maxrows)
+                       sp->t_rows = sp->t_maxrows;
+               if (sp->t_minrows > sp->t_maxrows)
+                       sp->t_minrows = sp->t_maxrows;
+
+               /* Fix the child screen. */
+               new->t_minrows = new->t_rows = O_VAL(sp, O_WINDOW);
+               if (new->t_rows > new->t_maxrows)
+                       new->t_rows = new->t_maxrows;
+               if (new->t_minrows > new->t_maxrows)
+                       new->t_minrows = new->t_maxrows;
+       } else {
+               sp->t_minrows = sp->t_rows = IS_ONELINE(sp) ? 1 : sp->rows - 1;
+
+               /*
+                * The new screen may be a small screen, even if the parent
+                * was not.  Don't complain if O_WINDOW is too large, we're
+                * splitting the screen so the screen is much smaller than
+                * normal.
+                */
+               new->t_minrows = new->t_rows = O_VAL(sp, O_WINDOW);
+               if (new->t_rows > new->rows - 1)
+                       new->t_minrows = new->t_rows =
+                           IS_ONELINE(new) ? 1 : new->rows - 1;
+       }
+
+       /* Adjust the ends of the new and old maps. */
+       _TMAP(sp) = IS_ONELINE(sp) ?
+           _HMAP(sp) : _HMAP(sp) + (sp->t_rows - 1);
+       _TMAP(new) = IS_ONELINE(new) ?
+           _HMAP(new) : _HMAP(new) + (new->t_rows - 1);
+
+       /* Reset the length of the default scroll. */
+       if ((sp->defscroll = sp->t_maxrows / 2) == 0)
+               sp->defscroll = 1;
+       if ((new->defscroll = new->t_maxrows / 2) == 0)
+               new->defscroll = 1;
+
+       /* Fit the screen into the logical chain. */
+       vs_insert(new, sp->wp);
+
+       /* Tell the display that we're splitting. */
+       (void)gp->scr_split(sp, new);
+
+       /*
+        * Initialize the screen flags:
+        *
+        * If we're in vi mode in one screen, we don't have to reinitialize.
+        * This isn't just a cosmetic fix.  The path goes like this:
+        *
+        *      return into vi(), SC_SSWITCH set
+        *      call vs_refresh() with SC_STATUS set
+        *      call vs_resolve to display the status message
+        *      call vs_refresh() because the SC_SCR_VI bit isn't set
+        *
+        * Things go downhill at this point.
+        *
+        * Draw the new screen from scratch, and add a status line.
+        */
+       F_SET(new,
+           SC_SCR_REFORMAT | SC_STATUS |
+           F_ISSET(sp, SC_EX | SC_VI | SC_SCR_VI | SC_SCR_EX));
+       return (0);
+}
+
+/*
+ * vs_vsplit --
+ *     Create a new screen, vertically.
+ *
+ * PUBLIC: int vs_vsplit __P((SCR *, SCR *));
+ */
+int
+vs_vsplit(SCR *sp, SCR *new)
+{
+       GS *gp;
+       size_t cols;
+
+       gp = sp->gp;
+
+       /* Check to see if it's possible. */
+       if (sp->cols / 2 <= MINIMUM_SCREEN_COLS) {
+               msgq(sp, M_ERR,
+                   "288|Screen must be larger than %d columns to split",
+                   MINIMUM_SCREEN_COLS * 2);
+               return (1);
+       }
+
+       /* Wait for any messages in the screen. */
+       vs_resolve(sp, NULL, 1);
+
+       /* Get a new screen map. */
+       CALLOC(sp, _HMAP(new), SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
+       if (_HMAP(new) == NULL)
+               return (1);
+       _HMAP(new)->lno = sp->lno;
+       _HMAP(new)->coff = 0;
+       _HMAP(new)->soff = 1;
+
+       /*
+        * Split the screen in half; we have to sacrifice a column to delimit
+        * the screens.
+        *
+        * XXX
+        * We always split to the right... that makes more sense to me, and
+        * I don't want to play the stupid games that I play when splitting
+        * horizontally.
+        *
+        * XXX
+        * We reserve a column for the screen, "knowing" that curses needs
+        * one.  This should be worked out with the display interface.
+        */
+       cols = sp->cols / 2;
+       new->cols = sp->cols - cols - 1;
+       sp->cols = cols;
+       new->coff = sp->coff + cols + 1;
+       sp->cno = 0;
+
+       /* Nothing else changes. */
+       new->rows = sp->rows;
+       new->t_rows = sp->t_rows;
+       new->t_maxrows = sp->t_maxrows;
+       new->t_minrows = sp->t_minrows;
+       new->roff = sp->roff;
+       new->defscroll = sp->defscroll;
+       _TMAP(new) = _HMAP(new) + (new->t_rows - 1);
+
+       /* Fit the screen into the logical chain. */
+       vs_insert(new, sp->wp);
+
+       /* Tell the display that we're splitting. */
+       (void)gp->scr_split(sp, new);
+
+       /* Redraw the old screen from scratch. */
+       F_SET(sp, SC_SCR_REFORMAT | SC_STATUS);
+
+       /*
+        * Initialize the screen flags:
+        *
+        * If we're in vi mode in one screen, we don't have to reinitialize.
+        * This isn't just a cosmetic fix.  The path goes like this:
+        *
+        *      return into vi(), SC_SSWITCH set
+        *      call vs_refresh() with SC_STATUS set
+        *      call vs_resolve to display the status message
+        *      call vs_refresh() because the SC_SCR_VI bit isn't set
+        *
+        * Things go downhill at this point.
+        *
+        * Draw the new screen from scratch, and add a status line.
+        */
+       F_SET(new,
+           SC_SCR_REFORMAT | SC_STATUS |
+           F_ISSET(sp, SC_EX | SC_VI | SC_SCR_VI | SC_SCR_EX));
+       return (0);
+}
+
+/*
+ * vs_insert --
+ *     Insert the new screen into the correct place in the logical
+ *     chain.
+ */
+static void
+vs_insert(SCR *sp, WIN *wp)
+{
+       GS *gp;
+       SCR *tsp;
+
+       gp = sp->gp;
+
+       sp->wp = wp;
+
+       /* Move past all screens with lower row numbers. */
+       for (tsp = wp->scrq.cqh_first;
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
+               if (tsp->roff >= sp->roff)
+                       break;
+       /*
+        * Move past all screens with the same row number and lower
+        * column numbers.
+        */
+       for (; tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next)
+               if (tsp->roff != sp->roff || tsp->coff > sp->coff)
+                       break;
+
+       /*
+        * If we reached the end, this screen goes there.  Otherwise,
+        * put it before or after the screen where we stopped.
+        */
+       if (tsp == (void *)&wp->scrq) {
+               CIRCLEQ_INSERT_TAIL(&wp->scrq, sp, q);
+       } else if (tsp->roff < sp->roff ||
+           (tsp->roff == sp->roff && tsp->coff < sp->coff)) {
+               CIRCLEQ_INSERT_AFTER(&wp->scrq, tsp, sp, q);
+       } else
+               CIRCLEQ_INSERT_BEFORE(&wp->scrq, tsp, sp, q);
+}
+
+/*
+ * vs_discard --
+ *     Discard the screen, folding the real-estate into a related screen,
+ *     if one exists, and return that screen.
+ *
+ * PUBLIC: int vs_discard __P((SCR *, SCR **));
+ */
+int
+vs_discard(SCR *sp, SCR **spp)
+{
+       GS *gp;
+       SCR *tsp, **lp, *list[100];
+       jdir_t jdir;
+
+       gp = sp->gp;
+
+       /*
+        * Save the old screen's cursor information.
+        *
+        * XXX
+        * If called after file_end(), and the underlying file was a tmp
+        * file, it may have gone away.
+        */
+       if (sp->frp != NULL) {
+               sp->frp->lno = sp->lno;
+               sp->frp->cno = sp->cno;
+               F_SET(sp->frp, FR_CURSORSET);
+       }
+
+       /* If no other screens to join, we're done. */
+       if (!IS_SPLIT(sp)) {
+               (void)gp->scr_discard(sp, NULL);
+
+               if (spp != NULL)
+                       *spp = NULL;
+               return (0);
+       }
+
+       /*
+        * Find a set of screens that cover one of the screen's borders.
+        * Check the vertical axis first, for no particular reason.
+        *
+        * XXX
+        * It's possible (I think?), to create a screen that shares no full
+        * border with any other set of screens, so we can't discard it.  We
+        * just complain at the user until they clean it up.
+        */
+       if (vs_join(sp, list, &jdir))
+               return (1);
+
+       /*
+        * Modify the affected screens.  Redraw the modified screen(s) from
+        * scratch, setting a status line.  If this is ever a performance
+        * problem we could play games with the map, but I wrote that code
+        * before and it was never clean or easy.
+        *
+        * Don't clean up the discarded screen's information.  If the screen
+        * isn't exiting, we'll do the work when the user redisplays it.
+        */
+       switch (jdir) {
+       case HORIZ_FOLLOW:
+       case HORIZ_PRECEDE:
+               for (lp = &list[0]; (tsp = *lp) != NULL; ++lp) {
+                       /*
+                        * Small screens: see vs_refresh.c section 6a.  Adjust
+                        * text line info, unless it's a small screen.
+                        *
+                        * Reset the length of the default scroll.
+                        *
+                        * Reset the map references.
+                        */
+                       tsp->rows += sp->rows;
+                       if (!IS_SMALL(tsp))
+                               tsp->t_rows = tsp->t_minrows = tsp->rows - 1;
+                       tsp->t_maxrows = tsp->rows - 1;
+
+                       tsp->defscroll = tsp->t_maxrows / 2;
+
+                       *(_HMAP(tsp) + (tsp->t_rows - 1)) = *_TMAP(tsp);
+                       _TMAP(tsp) = _HMAP(tsp) + (tsp->t_rows - 1);
+
+                       switch (jdir) {
+                       case HORIZ_FOLLOW:
+                               tsp->roff = sp->roff;
+                               vs_sm_fill(tsp, OOBLNO, P_TOP);
+                               break;
+                       case HORIZ_PRECEDE:
+                               vs_sm_fill(tsp, OOBLNO, P_BOTTOM);
+                               break;
+                       default:
+                               abort();
+                       }
+                       F_SET(tsp, SC_STATUS);
+               }
+               break;
+       case VERT_FOLLOW:
+       case VERT_PRECEDE:
+               for (lp = &list[0]; (tsp = *lp) != NULL; ++lp) {
+                       if (jdir == VERT_FOLLOW)
+                               tsp->coff = sp->coff;
+                       tsp->cols += sp->cols + 1;      /* XXX: DIVIDER */
+                       vs_sm_fill(tsp, OOBLNO, P_TOP);
+                       F_SET(tsp, SC_STATUS);
+               }
+               break;
+       default:
+               abort();
+       }
+
+       /* Find the closest screen that changed and move to it. */
+       tsp = list[0];
+       if (spp != NULL)
+               *spp = tsp;
+
+       /* Tell the display that we're discarding a screen. */
+       (void)gp->scr_discard(sp, list);
+
+       return (0);
+}
+
+/*
+ * vs_join --
+ *     Find a set of screens that covers a screen's border.
+ */
+static int
+vs_join(SCR *sp, SCR **listp, jdir_t *jdirp)
+{
+       GS *gp;
+       WIN *wp;
+       SCR **lp, *tsp;
+       int first;
+       size_t tlen;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       /* Check preceding vertical. */
+       for (lp = listp, tlen = sp->rows,
+           tsp = wp->scrq.cqh_first;
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next) {
+               if (sp == tsp)
+                       continue;
+               /* Test if precedes the screen vertically. */
+               if (tsp->coff + tsp->cols + 1 != sp->coff)
+                       continue;
+               /*
+                * Test if a subset on the vertical axis.  If overlaps the
+                * beginning or end, we can't join on this axis at all.
+                */
+               if (tsp->roff > sp->roff + sp->rows)
+                       continue;
+               if (tsp->roff < sp->roff) {
+                       if (tsp->roff + tsp->rows >= sp->roff)
+                               break;
+                       continue;
+               }
+               if (tsp->roff + tsp->rows > sp->roff + sp->rows)
+                       break;
+#ifdef DEBUG
+               if (tlen < tsp->rows)
+                       abort();
+#endif
+               tlen -= tsp->rows;
+               *lp++ = tsp;
+       }
+       if (tlen == 0) {
+               *lp = NULL;
+               *jdirp = VERT_PRECEDE;
+               return (0);
+       }
+
+       /* Check following vertical. */
+       for (lp = listp, tlen = sp->rows,
+           tsp = wp->scrq.cqh_first;
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next) {
+               if (sp == tsp)
+                       continue;
+               /* Test if follows the screen vertically. */
+               if (tsp->coff != sp->coff + sp->cols + 1)
+                       continue;
+               /*
+                * Test if a subset on the vertical axis.  If overlaps the
+                * beginning or end, we can't join on this axis at all.
+                */
+               if (tsp->roff > sp->roff + sp->rows)
+                       continue;
+               if (tsp->roff < sp->roff) {
+                       if (tsp->roff + tsp->rows >= sp->roff)
+                               break;
+                       continue;
+               }
+               if (tsp->roff + tsp->rows > sp->roff + sp->rows)
+                       break;
+#ifdef DEBUG
+               if (tlen < tsp->rows)
+                       abort();
+#endif
+               tlen -= tsp->rows;
+               *lp++ = tsp;
+       }
+       if (tlen == 0) {
+               *lp = NULL;
+               *jdirp = VERT_FOLLOW;
+               return (0);
+       }
+
+       /* Check preceding horizontal. */
+       for (first = 0, lp = listp, tlen = sp->cols,
+           tsp = wp->scrq.cqh_first;
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next) {
+               if (sp == tsp)
+                       continue;
+               /* Test if precedes the screen horizontally. */
+               if (tsp->roff + tsp->rows != sp->roff)
+                       continue;
+               /*
+                * Test if a subset on the horizontal axis.  If overlaps the
+                * beginning or end, we can't join on this axis at all.
+                */
+               if (tsp->coff > sp->coff + sp->cols)
+                       continue;
+               if (tsp->coff < sp->coff) {
+                       if (tsp->coff + tsp->cols >= sp->coff)
+                               break;
+                       continue;
+               }
+               if (tsp->coff + tsp->cols > sp->coff + sp->cols)
+                       break;
+#ifdef DEBUG
+               if (tlen < tsp->cols)
+                       abort();
+#endif
+               tlen -= tsp->cols + first;
+               first = 1;
+               *lp++ = tsp;
+       }
+       if (tlen == 0) {
+               *lp = NULL;
+               *jdirp = HORIZ_PRECEDE;
+               return (0);
+       }
+
+       /* Check following horizontal. */
+       for (first = 0, lp = listp, tlen = sp->cols,
+           tsp = wp->scrq.cqh_first;
+           tsp != (void *)&wp->scrq; tsp = tsp->q.cqe_next) {
+               if (sp == tsp)
+                       continue;
+               /* Test if precedes the screen horizontally. */
+               if (tsp->roff != sp->roff + sp->rows)
+                       continue;
+               /*
+                * Test if a subset on the horizontal axis.  If overlaps the
+                * beginning or end, we can't join on this axis at all.
+                */
+               if (tsp->coff > sp->coff + sp->cols)
+                       continue;
+               if (tsp->coff < sp->coff) {
+                       if (tsp->coff + tsp->cols >= sp->coff)
+                               break;
+                       continue;
+               }
+               if (tsp->coff + tsp->cols > sp->coff + sp->cols)
+                       break;
+#ifdef DEBUG
+               if (tlen < tsp->cols)
+                       abort();
+#endif
+               tlen -= tsp->cols + first;
+               first = 1;
+               *lp++ = tsp;
+       }
+       if (tlen == 0) {
+               *lp = NULL;
+               *jdirp = HORIZ_FOLLOW;
+               return (0);
+       }
+       return (1);
+}
+
+/*
+ * vs_fg --
+ *     Background the current screen, and foreground a new one.
+ *
+ * PUBLIC: int vs_fg __P((SCR *, SCR **, CHAR_T *, int));
+ */
+int
+vs_fg(SCR *sp, SCR **nspp, CHAR_T *name, int newscreen)
+{
+       GS *gp;
+       WIN *wp;
+       SCR *nsp;
+       const char *np;
+       size_t nlen;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       if (name)
+           INT2CHAR(sp, name, STRLEN(name) + 1, np, nlen);
+       else
+           np = NULL;
+       if (newscreen)
+               /* Get the specified background screen. */
+               nsp = vs_getbg(sp, np);
+       else
+               /* Swap screens. */
+               if (vs_swap(sp, &nsp, np))
+                       return (1);
+
+       if ((*nspp = nsp) == NULL) {
+               msgq_wstr(sp, M_ERR, name,
+                   name == NULL ?
+                   "223|There are no background screens" :
+                   "224|There's no background screen editing a file named %s");
+               return (1);
+       }
+
+       if (newscreen) {
+               /* Remove the new screen from the background queue. */
+               CIRCLEQ_REMOVE(&gp->hq, nsp, q);
+
+               /* Split the screen; if we fail, hook the screen back in. */
+               if (vs_split(sp, nsp, 0)) {
+                       CIRCLEQ_INSERT_TAIL(&gp->hq, nsp, q);
+                       return (1);
+               }
+       } else {
+               /* Move the old screen to the background queue. */
+               CIRCLEQ_REMOVE(&wp->scrq, sp, q);
+               CIRCLEQ_INSERT_TAIL(&gp->hq, sp, q);
+       }
+       return (0);
+}
+
+/*
+ * vs_bg --
+ *     Background the screen, and switch to the next one.
+ *
+ * PUBLIC: int vs_bg __P((SCR *));
+ */
+int
+vs_bg(SCR *sp)
+{
+       GS *gp;
+       WIN *wp;
+       SCR *nsp;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       /* Try and join with another screen. */
+       if (vs_discard(sp, &nsp))
+               return (1);
+       if (nsp == NULL) {
+               msgq(sp, M_ERR,
+                   "225|You may not background your only displayed screen");
+               return (1);
+       }
+
+       /* Move the old screen to the background queue. */
+       CIRCLEQ_REMOVE(&wp->scrq, sp, q);
+       CIRCLEQ_INSERT_TAIL(&gp->hq, sp, q);
+
+       /* Toss the screen map. */
+       free(_HMAP(sp));
+       _HMAP(sp) = NULL;
+
+       /* Switch screens. */
+       sp->nextdisp = nsp;
+       F_SET(sp, SC_SSWITCH);
+
+       return (0);
+}
+
+/*
+ * vs_swap --
+ *     Swap the current screen with a backgrounded one.
+ *
+ * PUBLIC: int vs_swap __P((SCR *, SCR **, const char *));
+ */
+int
+vs_swap(SCR *sp, SCR **nspp, const char *name)
+{
+       GS *gp;
+       WIN *wp;
+       SCR *nsp, *list[2];
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       /* Get the specified background screen. */
+       if ((*nspp = nsp = vs_getbg(sp, name)) == NULL)
+               return (0);
+
+       /*
+        * Save the old screen's cursor information.
+        *
+        * XXX
+        * If called after file_end(), and the underlying file was a tmp
+        * file, it may have gone away.
+        */
+       if (sp->frp != NULL) {
+               sp->frp->lno = sp->lno;
+               sp->frp->cno = sp->cno;
+               F_SET(sp->frp, FR_CURSORSET);
+       }
+
+       /* Switch screens. */
+       sp->nextdisp = nsp;
+       F_SET(sp, SC_SSWITCH);
+
+       /* Initialize terminal information. */
+       VIP(nsp)->srows = VIP(sp)->srows;
+
+       /* Initialize screen information. */
+       nsp->cols = sp->cols;
+       nsp->rows = sp->rows;   /* XXX: Only place in vi that sets rows. */
+       nsp->roff = sp->roff;
+
+       /*
+        * Small screens: see vs_refresh.c, section 6a.
+        *
+        * The new screens may have different screen options sizes than the
+        * old one, so use them.  Make sure that text counts aren't larger
+        * than the new screen sizes.
+        */
+       if (IS_SMALL(nsp)) {
+               nsp->t_minrows = nsp->t_rows = O_VAL(nsp, O_WINDOW);
+               if (nsp->t_rows > sp->t_maxrows)
+                       nsp->t_rows = nsp->t_maxrows;
+               if (nsp->t_minrows > sp->t_maxrows)
+                       nsp->t_minrows = nsp->t_maxrows;
+       } else
+               nsp->t_rows = nsp->t_maxrows = nsp->t_minrows = nsp->rows - 1;
+
+       /* Reset the length of the default scroll. */
+       nsp->defscroll = nsp->t_maxrows / 2;
+
+       /* Allocate a new screen map. */
+       CALLOC_RET(nsp, _HMAP(nsp), SMAP *, SIZE_HMAP(nsp), sizeof(SMAP));
+       _TMAP(nsp) = _HMAP(nsp) + (nsp->t_rows - 1);
+
+       /* Fill the map. */
+       nsp->wp = sp->wp;
+       if (vs_sm_fill(nsp, nsp->lno, P_FILL))
+               return (1);
+
+       /*
+        * The new screen replaces the old screen in the parent/child list.
+        * We insert the new screen after the old one.  If we're exiting,
+        * the exit will delete the old one, if we're foregrounding, the fg
+        * code will move the old one to the background queue.
+        */
+       CIRCLEQ_REMOVE(&gp->hq, nsp, q);
+       CIRCLEQ_INSERT_AFTER(&wp->scrq, sp, nsp, q);
+
+       /*
+        * Don't change the screen's cursor information other than to
+        * note that the cursor is wrong.
+        */
+       F_SET(VIP(nsp), VIP_CUR_INVALID);
+
+       /* Draw the new screen from scratch, and add a status line. */
+       F_SET(nsp, SC_SCR_REDRAW | SC_STATUS);
+
+       list[0] = nsp; list[1] = NULL;
+       (void)gp->scr_discard(sp, list);
+
+       return (0);
+}
+
+/*
+ * vs_resize --
+ *     Change the absolute size of the current screen.
+ *
+ * PUBLIC: int vs_resize __P((SCR *, long, adj_t));
+ */
+int
+vs_resize(SCR *sp, long int count, adj_t adj)
+{
+       GS *gp;
+       WIN *wp;
+       SCR *g, *s, *prev, *next, *list[3] = {NULL, NULL, NULL};
+       size_t g_off, s_off;
+
+       gp = sp->gp;
+       wp = sp->wp;
+
+       /*
+        * Figure out which screens will grow, which will shrink, and
+        * make sure it's possible.
+        */
+       if (count == 0)
+               return (0);
+       if (adj == A_SET) {
+               if (sp->t_maxrows == (size_t)count)
+                       return (0);
+               if (sp->t_maxrows > (size_t)count) {
+                       adj = A_DECREASE;
+                       count = sp->t_maxrows - count;
+               } else {
+                       adj = A_INCREASE;
+                       count = count - sp->t_maxrows;
+               }
+       }
+
+       /* Find first overlapping screen */
+       for (next = sp->q.cqe_next; 
+            next != (void *)&wp->scrq && 
+            (next->coff >= sp->coff + sp->cols || 
+             next->coff + next->cols <= sp->coff); 
+            next = next->q.cqe_next);
+       /* See if we can use it */
+       if (next != (void *)&wp->scrq && 
+           (sp->coff != next->coff || sp->cols != next->cols))
+               next = (void *)&wp->scrq;
+       for (prev = sp->q.cqe_prev; 
+            prev != (void *)&wp->scrq && 
+            (prev->coff >= sp->coff + sp->cols || 
+             prev->coff + prev->cols <= sp->coff); 
+            prev = prev->q.cqe_prev);
+       if (prev != (void *)&wp->scrq && 
+           (sp->coff != prev->coff || sp->cols != prev->cols))
+               prev = (void *)&wp->scrq;
+
+       g_off = s_off = 0;
+       if (adj == A_DECREASE) {
+               if (count < 0)
+                       count = -count;
+               s = sp;
+               if (s->t_maxrows < MINIMUM_SCREEN_ROWS + (size_t)count)
+                       goto toosmall;
+               if ((g = prev) == (void *)&wp->scrq) {
+                       if ((g = next) == (void *)&wp->scrq)
+                               goto toobig;
+                       g_off = -count;
+               } else
+                       s_off = count;
+       } else {
+               g = sp;
+               if ((s = next) != (void *)&wp->scrq &&
+                   s->t_maxrows >= MINIMUM_SCREEN_ROWS + (size_t)count)
+                               s_off = count;
+               else
+                       s = NULL;
+               if (s == NULL) {
+                       if ((s = prev) == (void *)&wp->scrq) {
+toobig:                                msgq(sp, M_BERR, adj == A_DECREASE ?
+                                   "227|The screen cannot shrink" :
+                                   "228|The screen cannot grow");
+                               return (1);
+                       }
+                       if (s->t_maxrows < MINIMUM_SCREEN_ROWS + (size_t)count) {
+toosmall:                      msgq(sp, M_BERR,
+                                   "226|The screen can only shrink to %d rows",
+                                   MINIMUM_SCREEN_ROWS);
+                               return (1);
+                       }
+                       g_off = -count;
+               }
+       }
+
+       /*
+        * Fix up the screens; we could optimize the reformatting of the
+        * screen, but this isn't likely to be a common enough operation
+        * to make it worthwhile.
+        */
+       s->rows += -count;
+       s->roff += s_off;
+       g->rows += count;
+       g->roff += g_off;
+
+       g->t_rows += count;
+       if (g->t_minrows == g->t_maxrows)
+               g->t_minrows += count;
+       g->t_maxrows += count;
+       _TMAP(g) += count;
+       F_SET(g, SC_SCR_REFORMAT | SC_STATUS);
+
+       s->t_rows -= count;
+       s->t_maxrows -= count;
+       if (s->t_minrows > s->t_maxrows)
+               s->t_minrows = s->t_maxrows;
+       _TMAP(s) -= count;
+       F_SET(s, SC_SCR_REFORMAT | SC_STATUS);
+
+       /* XXXX */
+       list[0] = g; list[1] = s;
+       gp->scr_discard(0, list);
+
+       return (0);
+}
+
+/*
+ * vs_getbg --
+ *     Get the specified background screen, or, if name is NULL, the first
+ *     background screen.
+ */
+static SCR *
+vs_getbg(SCR *sp, const char *name)
+{
+       GS *gp;
+       SCR *nsp;
+       char *p;
+
+       gp = sp->gp;
+
+       /* If name is NULL, return the first background screen on the list. */
+       if (name == NULL) {
+               nsp = gp->hq.cqh_first;
+               return (nsp == (void *)&gp->hq ? NULL : nsp);
+       }
+
+       /* Search for a full match. */
+       for (nsp = gp->hq.cqh_first;
+           nsp != (void *)&gp->hq; nsp = nsp->q.cqe_next)
+               if (!strcmp(nsp->frp->name, name))
+                       break;
+       if (nsp != (void *)&gp->hq)
+               return (nsp);
+
+       /* Search for a last-component match. */
+       for (nsp = gp->hq.cqh_first;
+           nsp != (void *)&gp->hq; nsp = nsp->q.cqe_next) {
+               if ((p = strrchr(nsp->frp->name, '/')) == NULL)
+                       p = nsp->frp->name;
+               else
+                       ++p;
+               if (!strcmp(p, name))
+                       break;
+       }
+       if (nsp != (void *)&gp->hq)
+               return (nsp);
+
+       return (NULL);
+}
index a5111e38aebb3fc3de5edb0242fe84dc74629d0c..5f3100e2388067b3db3ba733e6dd888885067762 100644 (file)
 ./usr/bin/dumpcore                     minix-sys
 ./usr/bin/egrep                                minix-sys
 ./usr/bin/eject                                minix-sys
-./usr/bin/elvis                                minix-sys
-./usr/bin/elvprsv                      minix-sys
-./usr/bin/elvrec                       minix-sys
+./usr/bin/elvis                                minix-sys       obsolete
+./usr/bin/elvprsv                      minix-sys       obsolete
+./usr/bin/elvrec                       minix-sys       obsolete
 ./usr/bin/env                          minix-sys
 ./usr/bin/ex                           minix-sys
 ./usr/bin/expand                       minix-sys
 ./usr/bin/fix                          minix-sys
 ./usr/bin/flex++                       minix-sys
 ./usr/bin/flex                         minix-sys
-./usr/bin/fmt                          minix-sys
+./usr/bin/fmt                          minix-sys       obsolete
 ./usr/bin/fold                         minix-sys
 ./usr/bin/format                       minix-sys
 ./usr/bin/fortune                      minix-sys
 ./usr/bin/readall                      minix-sys       obsolete
 ./usr/bin/readlink                     minix-sys
 ./usr/bin/reboot                       minix-sys
-./usr/bin/ref                          minix-sys
+./usr/bin/ref                          minix-sys       obsolete
 ./usr/bin/remsync                      minix-sys
 ./usr/bin/restore                      minix-sys
 ./usr/bin/rev                          minix-sys
 ./usr/bin/uue                          minix-sys
 ./usr/bin/uuencode                     minix-sys
 ./usr/bin/version                      minix-sys
+./usr/bin/view                         minix-sys
 ./usr/bin/vi                           minix-sys
 ./usr/bin/vol                          minix-sys
 ./usr/bin/wc                           minix-sys
 ./usr/include/g++                      minix-sys
 ./usr/include/grp.h                    minix-sys
 ./usr/include/hesiod.h                 minix-sys
+./usr/include/histedit.h               minix-sys
 ./usr/include/iconv.h                  minix-sys
 ./usr/include/ieeefp.h                 minix-sys
 ./usr/include/ifaddrs.h                        minix-sys
 ./usr/include/pwd.h                    minix-sys
 ./usr/include/randomid.h               minix-sys
 ./usr/include/ranlib.h                 minix-sys
+./usr/include/readline/history.h       minix-sys
+./usr/include/readline                 minix-sys
+./usr/include/readline/readline.h      minix-sys
 ./usr/include/re_comp.h                        minix-sys
 ./usr/include/regex.h                  minix-sys
 ./usr/include/regexp.h                 minix-sys
 ./usr/lib/libdevman_pic.a              minix-sys
 ./usr/lib/libedit.a                    minix-sys
 ./usr/lib/libedit_pic.a                        minix-sys
+./usr/lib/libedit.so.3.0               minix-sys
+./usr/lib/libedit.so.3                 minix-sys
+./usr/lib/libedit.so                   minix-sys
 ./usr/lib/libelf.a                     minix-sys
 ./usr/lib/libelf_pic.a                 minix-sys
 ./usr/lib/libelf.so.0                  minix-sys
 ./usr/man/man1/ed.1                    minix-sys
 ./usr/man/man1/egrep.1                 minix-sys
 ./usr/man/man1/eject.1                 minix-sys
-./usr/man/man1/elvis.1                 minix-sys
-./usr/man/man1/elvrec.1                        minix-sys
+./usr/man/man1/elvis.1                 minix-sys       obsolete
+./usr/man/man1/elvrec.1                        minix-sys       obsolete
 ./usr/man/man1/env.1                   minix-sys
 ./usr/man/man1/eval.1                  minix-sys
 ./usr/man/man1/ex.1                    minix-sys
 ./usr/man/man1/finger.1                        minix-sys
 ./usr/man/man1/flex.1                  minix-sys
 ./usr/man/man1/flexdoc.1               minix-sys
-./usr/man/man1/fmt.1                   minix-sys
+./usr/man/man1/fmt.1                   minix-sys       obsolete
 ./usr/man/man1/fold.1                  minix-sys
 ./usr/man/man1/for.1                   minix-sys
 ./usr/man/man1/format.1                        minix-sys
 ./usr/man/man1/readlink.1              minix-sys
 ./usr/man/man1/readonly.1              minix-sys
 ./usr/man/man1/recwave.1               minix-sys
-./usr/man/man1/ref.1                   minix-sys
+./usr/man/man1/ref.1                   minix-sys       obsolete
 ./usr/man/man1/remsync.1               minix-sys
 ./usr/man/man1/return.1                        minix-sys
 ./usr/man/man1/rget.1                  minix-sys
 ./usr/man/man1/unset.1                 minix-sys
 ./usr/man/man1/uud.1                   minix-sys
 ./usr/man/man1/uue.1                   minix-sys
+./usr/man/man1/vi.1                    minix-sys
+./usr/man/man1/view.1                  minix-sys
 ./usr/man/man1/vol.1                   minix-sys
 ./usr/man/man1/wait.1                  minix-sys
 ./usr/man/man1/wc.1                    minix-sys
 ./usr/man/man1/write.1                 minix-sys
 ./usr/man/man1/xargs.1                 minix-sys
 ./usr/man/man1x/awk.1x                 minix-sys
-./usr/man/man1x/elvis.1x               minix-sys
+./usr/man/man1x/elvis.1x               minix-sys       obsolete
 ./usr/man/man1x/kermit.1x              minix-sys
 ./usr/man/man1x/macros.1x              minix-sys
 ./usr/man/man1x/mined.1x               minix-sys
 ./usr/man/man3/ecalloc.3                                       minix-sys
 ./usr/man/man3/echo.3                                  minix-sys
 ./usr/man/man3/echochar.3                                      minix-sys
+./usr/man/man3/editline.3              minix-sys
 ./usr/man/man3/efopen.3                                        minix-sys
 ./usr/man/man3/efun.3                                  minix-sys
+./usr/man/man3/el_deletestr.3          minix-sys
+./usr/man/man3/el_end.3                        minix-sys
 ./usr/man/man3/elf32_checksum.3                                        minix-sys
 ./usr/man/man3/elf32_fsize.3                                   minix-sys
 ./usr/man/man3/elf32_getehdr.3                                 minix-sys
 ./usr/man/man3/elf_strptr.3                                    minix-sys
 ./usr/man/man3/elf_update.3                                    minix-sys
 ./usr/man/man3/elf_version.3                                   minix-sys
+./usr/man/man3/el_get.3                        minix-sys
+./usr/man/man3/el_getc.3               minix-sys
+./usr/man/man3/el_gets.3               minix-sys
+./usr/man/man3/el_init.3               minix-sys
+./usr/man/man3/el_insertstr.3          minix-sys
+./usr/man/man3/el_line.3               minix-sys
+./usr/man/man3/el_parse.3              minix-sys
+./usr/man/man3/el_push.3               minix-sys
+./usr/man/man3/el_reset.3              minix-sys
+./usr/man/man3/el_resize.3             minix-sys
+./usr/man/man3/el_set.3                        minix-sys
+./usr/man/man3/el_source.3             minix-sys
 ./usr/man/man3/emalloc.3                                       minix-sys
 ./usr/man/man3/encrypt.3                                       minix-sys
 ./usr/man/man3/endfsent.3                                      minix-sys
 ./usr/man/man3/hesiod_init.3                           minix-sys       obsolete
 ./usr/man/man3/hesiod_resolve.3                                minix-sys       obsolete
 ./usr/man/man3/hesiod_to_bind.3                                minix-sys       obsolete
+./usr/man/man3/history.3               minix-sys
+./usr/man/man3/history_end.3           minix-sys
+./usr/man/man3/history_init.3          minix-sys
 ./usr/man/man3/hline.3                                 minix-sys
 ./usr/man/man3/hostalias.3                                     minix-sys
 ./usr/man/man3/hsearch.3                                       minix-sys
 ./usr/man/man3/tmpfile.3                                       minix-sys
 ./usr/man/man3/tmpnam.3                                        minix-sys
 ./usr/man/man3/toascii.3                                       minix-sys
+./usr/man/man3/tok_end.3               minix-sys
+./usr/man/man3/tok_init.3              minix-sys
+./usr/man/man3/tok_line.3              minix-sys
+./usr/man/man3/tok_reset.3             minix-sys
+./usr/man/man3/tok_str.3               minix-sys
 ./usr/man/man3/tolower.3                                       minix-sys
 ./usr/man/man3/touchline.3                                     minix-sys
 ./usr/man/man3/touchoverlap.3                                  minix-sys
 ./usr/man/man5/crontab.5                                       minix-sys
 ./usr/man/man5/dhcp.conf.5                                     minix-sys
 ./usr/man/man5/dir.5                                   minix-sys
+./usr/man/man5/editrc.5                        minix-sys
 ./usr/man/man5/ethers.5                                        minix-sys
 ./usr/man/man5/fstab.5                                 minix-sys
 ./usr/man/man5/group.5                                 minix-sys
 ./usr/man/man8/cron.8                          minix-sys
 ./usr/man/man8/dhcpd.8                         minix-sys
 ./usr/man/man8/diskctl.8                       minix-sys
-./usr/man/man8/elvprsv.8                       minix-sys
+./usr/man/man8/elvprsv.8                       minix-sys       obsolete
 ./usr/man/man8/fbdctl.8                                minix-sys
 ./usr/man/man8/fdisk.8                         minix-sys
 ./usr/man/man8/fingerd.8                       minix-sys
index c27b477e7e7c4f96ac4b96a7ec9e81d2e630bc68..f251f34aecb458603af339d3da4e7aec75ccf9b1 100644 (file)
@@ -50,6 +50,7 @@
 ./usr/include/net/gen
 ./usr/include/prop
 ./usr/include/protocols
+./usr/include/readline
 ./usr/include/rpcsvc
 ./usr/include/ssp
 ./usr/include/sys
index d354e13e25fbf7b7ec759f9c7fcecb3a865d60cb..da4349856a1f59d3b4c385e1295ad76791f46c89 100644 (file)
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.188 2012/08/17 16:22:27 joerg Exp $
+#      $NetBSD: Makefile,v 1.189 2012/09/16 13:47:41 rmind Exp $
 #      from: @(#)Makefile      5.25.1.1 (Berkeley) 5/7/91
 
 .include <bsd.own.mk>
@@ -38,7 +38,7 @@ SUBDIR+=      .WAIT
 #SUBDIR+=      i18n_module
 
 SUBDIR+= libcompat_minix libblockdriver libchardriver     \
-       libnetdriver libedit libm libtimers libutil \
+       libnetdriver libm libtimers libutil \
        libz libfetch libvtreefs libaudiodriver libmthread   \
        libexec libdevman libusb libasyn librmt \
        libddekit libminixfs libbdev libelf libminc libcrypt libterminfo \
@@ -107,7 +107,7 @@ SUBDIR+=    .WAIT
 
 SUBDIR+=       libcurses       # depends on libterminfo
 #SUBDIR+=      libdm           # depends on libprop
-#SUBDIR+=      libedit         # depends on libterminfo
+SUBDIR+=       libedit         # depends on libterminfo
 #SUBDIR+=      libexecinfo     # depends on libelf
 #SUBDIR+=      libppath        # depends on libprop
 #SUBDIR+=      libperfuse      # depends on libpuffs
@@ -120,6 +120,7 @@ SUBDIR+=    librumphijack   # depends on librumpclient and libpthread
 
 .if (${MKNPF} != "no")
 SUBDIR+=       libnpf          # depends on libprop
+#SUBDIR+=      npf
 .endif
 
 .if (${MKCRYPTO} != "no")
index b3bef76cf89fa2e3bfdffaab5b7716b8a4d8dc09..0880363d11ec7d63f1d1e935a6065586059dd43a 100644 (file)
-##  $Revision$
-##
-##  Unix makefile for editline library.
-##
-
-LIB=           edit
-
-##  Set your options:
-##     -DANSI_ARROWS           ANSI arrows keys work like emacs.
-##     -DHAVE_STDLIB           Have <stdlib.h>.
-##     -DHAVE_TCGETATTR        Have , .
-##     -DHAVE_TERMIO           Have "struct termio" and <termio.h>
-##     (If neither of above two, we use <sgttyb.h> and BSD ioctl's)
-##     -DHIDE                  Make static functions static (non debug).
-##     -DHIST_SIZE=n           History size.
-##     -DNEED_STRDUP           Don't have .
-##     -DUNIQUE_HISTORY        Don't save command if same as last one.
-##     -DUSE_DIRENT            Use <dirent.h>, not <sys/dir.h>?
-##     -DUSE_TERMCAP           Use the termcap library for terminal size
-##                             see LDFLAGS, below, if you set this.
-##     -DNEED_PERROR           Don't have  (used in testit)
-CPPFLAGS+=-DANSI_ARROWS -DHAVE_STDLIB -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT \
-       -DHIST_SIZE=100 -DUSE_TERMCAP -DSYS_UNIX
-
-SRCS=  editline.c complete.c sysunix.c
+#      $NetBSD: Makefile,v 1.51 2012/08/10 12:20:10 joerg Exp $
+#      @(#)Makefile    8.1 (Berkeley) 6/4/93
+
+USE_SHLIBDIR=  yes
+
+WIDECHAR ?= yes
+WARNS?=        5
+LIB=   edit
+
+LIBDPLIBS+=     terminfo ${.CURDIR}/../libterminfo
+
+.include "bsd.own.mk"
+
+COPTS+=        -Wunused-parameter
+CWARNFLAGS.gcc+=       -Wconversion
+
+OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c \
+       hist.c keymacro.c map.c chartype.c \
+       parse.c prompt.c read.c refresh.c search.c sig.c terminal.c tty.c vi.c
+
+MAN=   editline.3 editrc.5
+
+MLINKS=        editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \
+       editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \
+       editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_get.3 \
+       editline.3 el_source.3 editline.3 el_resize.3 editline.3 el_line.3 \
+       editline.3 el_insertstr.3 editline.3 el_deletestr.3 \
+       editline.3 history_init.3 editline.3 history_end.3 \
+       editline.3 history.3 \
+       editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \
+       editline.3 tok_line.3 editline.3 tok_str.3
+
+# For speed and debugging
+#SRCS=   ${OSRCS} readline.c tokenizer.c history.c
+# For protection
+SRCS=  editline.c readline.c tokenizer.c history.c
+
+.if ${WIDECHAR} == "yes"
+OSRCS += eln.c
+SRCS += tokenizern.c historyn.c
+CLEANFILES+=tokenizern.c.tmp tokenizern.c historyn.c.tmp historyn.c
+CPPFLAGS+=-DWIDECHAR
+.endif
+
+LIBEDITDIR?=${.CURDIR}
+
+INCS= histedit.h
+INCSDIR=/usr/include
+
+CLEANFILES+=editline.c
+CLEANFILES+=common.h.tmp editline.c.tmp emacs.h.tmp fcns.c.tmp fcns.h.tmp
+CLEANFILES+=help.c.tmp help.h.tmp vi.h.tmp tc1.o tc1
+CLEANFILES+=tokenizern.c.tmp tokenizern.c tokenizerw.c.tmp tokenizerw.c
+CPPFLAGS+=-I. -I${LIBEDITDIR} 
+CPPFLAGS+=-I. -I${.CURDIR}
+CPPFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
+CPPFLAGS+=#-DDEBUG_PASTE -DDEBUG_EDIT
+
+AHDR=vi.h emacs.h common.h 
+ASRC=${LIBEDITDIR}/vi.c ${LIBEDITDIR}/emacs.c ${LIBEDITDIR}/common.c
+
+DPSRCS+=       ${AHDR} fcns.h help.h fcns.c help.c
+CLEANFILES+=   ${AHDR} fcns.h help.h fcns.c help.c
+
+SUBDIR=        readline
+
+vi.h: vi.c makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/vi.c \
+           > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+emacs.h: emacs.c makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/emacs.c \
+           > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+common.h: common.c makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/common.c \
+           > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+fcns.h: ${AHDR} makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -fh ${AHDR} > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+fcns.c: ${AHDR} fcns.h help.h makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -fc ${AHDR} > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+help.c: ${ASRC} makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -bc ${ASRC} > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+help.h: ${ASRC} makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -bh ${ASRC} > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+editline.c: ${OSRCS} makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -e ${OSRCS:T} > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+tokenizern.c: makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -n tokenizer.c > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+historyn.c: makelist Makefile
+       ${_MKTARGET_CREATE}
+       ${HOST_SH} ${LIBEDITDIR}/makelist -n history.c > ${.TARGET}.tmp && \
+           mv ${.TARGET}.tmp ${.TARGET}
+
+tc1.o: ${LIBEDITDIR}/TEST/tc1.c
+
+tc1:   libedit.a tc1.o 
+       ${_MKTARGET_LINK}
+       ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermlib
 
 .include <bsd.lib.mk>
+.include <bsd.subdir.mk>
+
+# XXX
+.if defined(HAVE_GCC) && ${HAVE_GCC} >= 45
+COPTS.editline.c+=     -Wno-cast-qual
+COPTS.tokenizer.c+=    -Wno-cast-qual
+COPTS.tokenizern.c+=   -Wno-cast-qual
+.endif
diff --git a/lib/libedit/README b/lib/libedit/README
deleted file mode 100644 (file)
index d3abb2f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-
-This is a line-editing library.  It can be linked into almost any
-program to provide command-line editing and recall.
-
-It is call-compatible with the FSF readline library, but it is a
-fraction of the size (and offers fewer features).  It does not use
-standard I/O.  It is distributed under a "C News-like" copyright.
-
-Configuration is done in the Makefile.  Type "make testit" to get
-a small slow shell for testing.
-
-An earlier version was distributed with Byron's rc.  Principal
-changes over that version include:
-       Faster.
-       Is eight-bit clean (thanks to brendan@cs.widener.edu)
-       Written in K&R C, but ANSI compliant (gcc all warnings)
-       Propagates EOF properly; rc trip test now passes
-       Doesn't need or use or provide memmove.
-       More robust
-       Calling sequence changed to be compatible with readline.
-       Test program, new manpage, better configuration
-       More system-independant; includes Unix and OS-9 support.
-
-This contains some changes since the posting to comp.sources.misc:
-       Bugfix for completion on absolute pathnames.
-       Better handling of M-n versus showing raw 8bit chars.
-       Better signal handling.
-       Now supports termios/termio/sgttyb ioctl's.
-       Add M-m command to toggle how 8bit data is displayed.
-
-There is one known bug:
-       History-searching redraws the line wrong if the text
-       retrieved is shorter then the prompt.
-
-Enjoy,
-       Rich $alz
-       <rsalz@osf.org>
-
- Copyright 1992,1993 Simmule Turner and Rich Salz.  All rights reserved.
-
- This software is not subject to any license of the American Telephone
- and Telegraph Company or of the Regents of the University of California.
-
- Permission is granted to anyone to use this software for any purpose on
- any computer system, and to alter it and redistribute it freely, subject
- to the following restrictions:
- 1. The authors are not responsible for the consequences of use of this
-    software, no matter how awful, even if they arise from flaws in it.
- 2. The origin of this software must not be misrepresented, either by
-    explicit claim or by omission.  Since few users ever read sources,
-    credits must appear in the documentation.
- 3. Altered versions must be plainly marked as such, and must not be
-    misrepresented as being the original software.  Since few users
-    ever read sources, credits must appear in the documentation.
- 4. This notice may not be removed or altered.
-
---
-$PchId: README,v 1.3 1996/02/22 21:18:51 philip Exp $
diff --git a/lib/libedit/TEST/Makefile b/lib/libedit/TEST/Makefile
new file mode 100644 (file)
index 0000000..e06fceb
--- /dev/null
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile,v 1.5 2010/02/03 15:34:43 roy Exp $
+
+NOMAN=1
+PROG=wtc1
+CPPFLAGS=-I${.CURDIR}/..
+LDADD+=-ledit -ltermlib
+DPADD+=${LIBEDIT} ${LIBTERMLIB}
+
+.ifdef DEBUG
+CPPFLAGS+=-DDEBUG
+.endif
+
+.include <bsd.prog.mk>
diff --git a/lib/libedit/TEST/rl1.c b/lib/libedit/TEST/rl1.c
new file mode 100644 (file)
index 0000000..78ff518
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: rl1.c,v 1.1 2010/09/16 20:08:51 christos Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: rl1.c,v 1.1 2010/09/16 20:08:51 christos Exp $");
+#endif /* not lint  */
+
+/*
+ * test.c: A little test program
+ */
+#include <stdio.h>
+#include <readline/readline.h>
+
+int
+main(int argc, char *argv[])
+{
+       char *p;
+       while ((p = readline("hi$")) != NULL) {
+               add_history(p);
+               printf("%d %s\n", history_length, p);
+       }
+       return 0;
+}
diff --git a/lib/libedit/TEST/tc1.c b/lib/libedit/TEST/tc1.c
new file mode 100644 (file)
index 0000000..77f8a51
--- /dev/null
@@ -0,0 +1,304 @@
+/*     $NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n");
+#endif /* not lint */
+
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)test.c     8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: tc1.c,v 1.5 2010/04/18 21:17:47 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * test.c: A little test program
+ */
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <locale.h>
+
+#include "histedit.h"
+
+static int continuation = 0;
+volatile sig_atomic_t gotsig = 0;
+
+static unsigned char   complete(EditLine *, int);
+       int     main(int, char **);
+static char   *prompt(EditLine *);
+static void    sig(int);
+
+static char *
+prompt(EditLine *el)
+{
+       static char a[] = "\1\033[7m\1Edit$\1\033[0m\1 ";
+       static char b[] = "Edit> ";
+
+       return (continuation ? b : a);
+}
+
+static void
+sig(int i)
+{
+       gotsig = i;
+}
+
+static unsigned char
+complete(EditLine *el, int ch)
+{
+       DIR *dd = opendir(".");
+       struct dirent *dp;
+       const char* ptr;
+       const LineInfo *lf = el_line(el);
+       int len;
+       int res = CC_ERROR;
+
+       /*
+        * Find the last word
+        */
+       for (ptr = lf->cursor - 1;
+           !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)
+               continue;
+       len = lf->cursor - ++ptr;
+
+       for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
+               if (len > strlen(dp->d_name))
+                       continue;
+               if (strncmp(dp->d_name, ptr, len) == 0) {
+                       if (el_insertstr(el, &dp->d_name[len]) == -1)
+                               res = CC_ERROR;
+                       else
+                               res = CC_REFRESH;
+                       break;
+               }
+       }
+
+       closedir(dd);
+       return res;
+}
+
+int
+main(int argc, char *argv[])
+{
+       EditLine *el = NULL;
+       int num;
+       const char *buf;
+       Tokenizer *tok;
+#if 0
+       int lastevent = 0;
+#endif
+       int ncontinuation;
+       History *hist;
+       HistEvent ev;
+
+       (void) setlocale(LC_CTYPE, "");
+       (void) signal(SIGINT, sig);
+       (void) signal(SIGQUIT, sig);
+       (void) signal(SIGHUP, sig);
+       (void) signal(SIGTERM, sig);
+
+       hist = history_init();          /* Init the builtin history     */
+                                       /* Remember 100 events          */
+       history(hist, &ev, H_SETSIZE, 100);
+
+       tok  = tok_init(NULL);          /* Initialize the tokenizer     */
+
+                                       /* Initialize editline          */
+       el = el_init(*argv, stdin, stdout, stderr);
+
+       el_set(el, EL_EDITOR, "vi");    /* Default editor is vi         */
+       el_set(el, EL_SIGNAL, 1);       /* Handle signals gracefully    */
+       el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */
+
+                       /* Tell editline to use this history interface  */
+       el_set(el, EL_HIST, history, hist);
+
+                                       /* Add a user-defined function  */
+       el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
+
+                                       /* Bind tab to it               */
+       el_set(el, EL_BIND, "^I", "ed-complete", NULL);
+
+       /*
+        * Bind j, k in vi command mode to previous and next line, instead
+        * of previous and next history.
+        */
+       el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
+       el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
+
+       /*
+        * Source the user's defaults file.
+        */
+       el_source(el, NULL);
+
+       while ((buf = el_gets(el, &num)) != NULL && num != 0)  {
+               int ac, cc, co;
+#ifdef DEBUG
+               int i;
+#endif
+               const char **av;
+               const LineInfo *li;
+               li = el_line(el);
+#ifdef DEBUG
+               (void) fprintf(stderr, "==> got %d %s", num, buf);
+               (void) fprintf(stderr, "  > li `%.*s_%.*s'\n",
+                   (li->cursor - li->buffer), li->buffer,
+                   (li->lastchar - 1 - li->cursor),
+                   (li->cursor >= li->lastchar) ? "" : li->cursor);
+
+#endif
+               if (gotsig) {
+                       (void) fprintf(stderr, "Got signal %d.\n", gotsig);
+                       gotsig = 0;
+                       el_reset(el);
+               }
+
+               if (!continuation && num == 1)
+                       continue;
+
+               ac = cc = co = 0;
+               ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co);
+               if (ncontinuation < 0) {
+                       (void) fprintf(stderr, "Internal error\n");
+                       continuation = 0;
+                       continue;
+               }
+#ifdef DEBUG
+               (void) fprintf(stderr, "  > nc %d ac %d cc %d co %d\n",
+                   ncontinuation, ac, cc, co);
+#endif
+#if 0
+               if (continuation) {
+                       /*
+                        * Append to the right event in case the user
+                        * moved around in history.
+                        */
+                       if (history(hist, &ev, H_SET, lastevent) == -1)
+                               err(1, "%d: %s", lastevent, ev.str);
+                       history(hist, &ev, H_ADD , buf);
+               } else {
+                       history(hist, &ev, H_ENTER, buf);
+                       lastevent = ev.num;
+               }
+#else
+                               /* Simpler */
+               history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf);
+#endif
+
+               continuation = ncontinuation;
+               ncontinuation = 0;
+               if (continuation)
+                       continue;
+#ifdef DEBUG
+               for (i = 0; i < ac; i++) {
+                       (void) fprintf(stderr, "  > arg# %2d ", i);
+                       if (i != cc)
+                               (void) fprintf(stderr, "`%s'\n", av[i]);
+                       else
+                               (void) fprintf(stderr, "`%.*s_%s'\n",
+                                   co, av[i], av[i] + co);
+               }
+#endif
+
+               if (strcmp(av[0], "history") == 0) {
+                       int rv;
+
+                       switch (ac) {
+                       case 1:
+                               for (rv = history(hist, &ev, H_LAST); rv != -1;
+                                   rv = history(hist, &ev, H_PREV))
+                                       (void) fprintf(stdout, "%4d %s",
+                                           ev.num, ev.str);
+                               break;
+
+                       case 2:
+                               if (strcmp(av[1], "clear") == 0)
+                                        history(hist, &ev, H_CLEAR);
+                               else
+                                        goto badhist;
+                               break;
+
+                       case 3:
+                               if (strcmp(av[1], "load") == 0)
+                                        history(hist, &ev, H_LOAD, av[2]);
+                               else if (strcmp(av[1], "save") == 0)
+                                        history(hist, &ev, H_SAVE, av[2]);
+                               break;
+
+                       badhist:
+                       default:
+                               (void) fprintf(stderr,
+                                   "Bad history arguments\n");
+                               break;
+                       }
+               } else if (el_parse(el, ac, av) == -1) {
+                       switch (fork()) {
+                       case 0:
+                               execvp(av[0], (char *const *)__UNCONST(av));
+                               perror(av[0]);
+                               _exit(1);
+                               /*NOTREACHED*/
+                               break;
+
+                       case -1:
+                               perror("fork");
+                               break;
+
+                       default:
+                               if (wait(&num) == -1)
+                                       perror("wait");
+                               (void) fprintf(stderr, "Exit %x\n", num);
+                               break;
+                       }
+               }
+
+               tok_reset(tok);
+       }
+
+       el_end(el);
+       tok_end(tok);
+       history_end(hist);
+
+       return (0);
+}
diff --git a/lib/libedit/TEST/wtc1.c b/lib/libedit/TEST/wtc1.c
new file mode 100644 (file)
index 0000000..365bd2e
--- /dev/null
@@ -0,0 +1,278 @@
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
+#include <locale.h>
+
+#include "../histedit.h"
+
+
+static int continuation;
+volatile sig_atomic_t gotsig;
+static const char hfile[] = ".whistory";
+
+static wchar_t *
+prompt(EditLine *el)
+{
+       static wchar_t a[] = L"\1\033[7m\1Edit$\1\033[0m\1 ";
+       static wchar_t b[] = L"Edit> ";
+
+       return continuation ? b : a;
+}
+
+
+static void
+sig(int i)
+{
+       gotsig = i;
+}
+
+const char *
+my_wcstombs(const wchar_t *wstr)
+{
+       static struct {
+               char *str;
+               int len;
+       } buf;
+
+       int needed = wcstombs(0, wstr, 0) + 1;
+       if (needed > buf.len) {
+               buf.str = malloc(needed);
+               buf.len = needed;
+       }
+       wcstombs(buf.str, wstr, needed);
+       buf.str[needed - 1] = 0;
+
+       return buf.str;
+}
+
+
+static unsigned char
+complete(EditLine *el, int ch)
+{
+       DIR *dd = opendir(".");
+       struct dirent *dp;
+       const wchar_t *ptr;
+       char *buf, *bptr;
+       const LineInfoW *lf = el_wline(el);
+       int len, mblen, i;
+       unsigned char res = 0;
+       wchar_t dir[1024];
+
+       /* Find the last word */
+       for (ptr = lf->cursor -1; !iswspace(*ptr) && ptr > lf->buffer; --ptr)
+               continue;
+       len = lf->cursor - ++ptr;
+
+       /* Convert last word to multibyte encoding, so we can compare to it */
+       wctomb(NULL, 0); /* Reset shift state */
+       mblen = MB_LEN_MAX * len + 1;
+       buf = bptr = malloc(mblen);
+       if (buf == NULL)
+               err(1, "malloc");
+       for (i = 0; i < len; ++i) {
+               /* Note: really should test for -1 return from wctomb */
+               bptr += wctomb(bptr, ptr[i]);
+       }
+       *bptr = 0; /* Terminate multibyte string */
+       mblen = bptr - buf;
+
+       /* Scan directory for matching name */
+       for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
+               if (mblen > strlen(dp->d_name))
+                       continue;
+               if (strncmp(dp->d_name, buf, mblen) == 0) {
+                       mbstowcs(dir, &dp->d_name[mblen],
+                           sizeof(dir) / sizeof(*dir));
+                       if (el_winsertstr(el, dir) == -1)
+                               res = CC_ERROR;
+                       else
+                               res = CC_REFRESH;
+                       break;
+               }
+       }
+
+       closedir(dd);
+       free(buf);
+       return res;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+       EditLine *el = NULL;
+       int numc, ncontinuation;
+       const wchar_t *line;
+       TokenizerW *tok;
+       HistoryW *hist;
+       HistEventW ev;
+#ifdef DEBUG
+       int i;
+#endif
+
+       setlocale(LC_ALL, "");
+
+       (void)signal(SIGINT,  sig);
+       (void)signal(SIGQUIT, sig);
+       (void)signal(SIGHUP,  sig);
+       (void)signal(SIGTERM, sig);
+
+       hist = history_winit();         /* Init built-in history     */
+       history_w(hist, &ev, H_SETSIZE, 100);   /* Remember 100 events       */
+       history_w(hist, &ev, H_LOAD, hfile);
+
+       tok = tok_winit(NULL);                  /* Init the tokenizer        */
+
+       el = el_init(argv[0], stdin, stdout, stderr);
+
+       el_wset(el, EL_EDITOR, L"vi");          /* Default editor is vi      */
+       el_wset(el, EL_SIGNAL, 1);              /* Handle signals gracefully */
+       el_wset(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */
+
+       el_wset(el, EL_HIST, history_w, hist);  /* FIXME - history_w? */
+
+                                       /* Add a user-defined function  */
+       el_wset(el, EL_ADDFN, L"ed-complete", L"Complete argument", complete);
+
+                                       /* Bind <tab> to it */
+       el_wset(el, EL_BIND, L"^I", L"ed-complete", NULL);
+
+       /*
+       * Bind j, k in vi command mode to previous and next line, instead
+       * of previous and next history.
+       */
+       el_wset(el, EL_BIND, L"-a", L"k", L"ed-prev-line", NULL);
+       el_wset(el, EL_BIND, L"-a", L"j", L"ed-next-line", NULL);
+
+       /* Source the user's defaults file. */
+       el_source(el, NULL);
+
+       while((line = el_wgets(el, &numc)) != NULL && numc != 0) {
+               int ac, cc, co, rc;
+               const wchar_t **av;
+
+               const LineInfoW *li;
+               li = el_wline(el);
+
+#ifdef DEBUG
+               (void)fwprintf(stderr, L"==> got %d %ls", numc, line);
+               (void)fwprintf(stderr, L"  > li `%.*ls_%.*ls'\n",
+                   (li->cursor - li->buffer), li->buffer,
+                   (li->lastchar - 1 - li->cursor),
+                   (li->cursor >= li->lastchar) ? L"" : li->cursor);
+#endif
+
+               if (gotsig) {
+                       (void)fprintf(stderr, "Got signal %d.\n", gotsig);
+                       gotsig = 0;
+                       el_reset(el);
+               }
+
+               if(!continuation && numc == 1)
+                       continue;       /* Only got a linefeed */
+
+               ac = cc = co = 0;
+               ncontinuation = tok_wline(tok, li, &ac, &av, &cc, &co);
+               if (ncontinuation < 0) {
+                       (void) fprintf(stderr, "Internal error\n");
+                       continuation = 0;
+                       continue;
+               }
+
+#ifdef DEBUG
+               (void)fprintf(stderr, "  > nc %d ac %d cc %d co %d\n",
+                       ncontinuation, ac, cc, co);
+#endif
+               history_w(hist, &ev, continuation ? H_APPEND : H_ENTER, line);
+
+               continuation = ncontinuation;
+               ncontinuation = 0;
+               if(continuation)
+                       continue;
+
+#ifdef DEBUG
+               for (i = 0; i < ac; ++i) {
+                       (void)fwprintf(stderr, L"  > arg# %2d ", i);
+                       if (i != cc)
+                               (void)fwprintf(stderr, L"`%ls'\n", av[i]);
+                       else
+                               (void)fwprintf(stderr, L"`%.*ls_%ls'\n",
+                                   co, av[i], av[i] + co);
+               }
+#endif
+
+               if (wcscmp (av[0], L"history") == 0) {
+                       switch(ac) {
+                       case 1:
+                               for(rc = history_w(hist, &ev, H_LAST);
+                                    rc != -1;
+                                    rc = history_w(hist, &ev, H_PREV))
+                                       (void)fwprintf(stdout, L"%4d %ls",
+                                            ev.num, ev.str);
+                               break;
+                       case 2:
+                               if (wcscmp(av[1], L"clear") == 0)
+                                       history_w(hist, &ev, H_CLEAR);
+                               else
+                                       goto badhist;
+                               break;
+                       case 3:
+                               if (wcscmp(av[1], L"load") == 0)
+                                       history_w(hist, &ev, H_LOAD,
+                                           my_wcstombs(av[2]));
+                               else if (wcscmp(av[1], L"save") == 0)
+                                       history_w(hist, &ev, H_SAVE,
+                                           my_wcstombs(av[2]));
+                               else
+                                       goto badhist;
+                               break;
+                       badhist:
+                       default:
+                               (void)fprintf(stderr,
+                                   "Bad history arguments\n");
+                               break;
+                       }
+               } else if (el_wparse(el, ac, av) == -1) {
+                       switch (fork()) {
+                       case 0: {
+                               Tokenizer *ntok = tok_init(NULL);
+                               int nargc;
+                               const char **nav;
+                               tok_str(ntok, my_wcstombs(line), &nargc, &nav);
+                               execvp(nav[0],(char **)nav);
+                               perror(nav[0]);
+                               _exit(1);
+                               /* NOTREACHED */
+                               break;
+                       }
+                       case -1:
+                               perror("fork");
+                               break;
+                       default:
+                               if (wait(&rc) == -1)
+                                       perror("wait");
+                               (void)fprintf(stderr, "Exit %x\n", rc);
+                               break;
+                       }
+               }
+
+               tok_wreset(tok);
+       }
+
+       el_end(el);
+       tok_wend(tok);
+       history_w(hist, &ev, H_SAVE, hfile);
+       history_wend(hist);
+
+       fprintf(stdout, "\n");
+       return 0;
+}
+
+
diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c
new file mode 100644 (file)
index 0000000..fb75de8
--- /dev/null
@@ -0,0 +1,740 @@
+/*     $NetBSD: chared.c,v 1.37 2012/07/18 17:12:39 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)chared.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: chared.c,v 1.37 2012/07/18 17:12:39 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * chared.c: Character editor utilities
+ */
+#include <stdlib.h>
+#include "el.h"
+
+private void ch__clearmacro (EditLine *);
+
+/* value to leave unused in line buffer */
+#define        EL_LEAVE        2
+
+/* cv_undo():
+ *     Handle state for the vi undo command
+ */
+protected void
+cv_undo(EditLine *el)
+{
+       c_undo_t *vu = &el->el_chared.c_undo;
+       c_redo_t *r = &el->el_chared.c_redo;
+       size_t size;
+
+       /* Save entire line for undo */
+       size = (size_t)(el->el_line.lastchar - el->el_line.buffer);
+       vu->len = (ssize_t)size;
+       vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
+       (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
+
+       /* save command info for redo */
+       r->count = el->el_state.doingarg ? el->el_state.argument : 0;
+       r->action = el->el_chared.c_vcmd.action;
+       r->pos = r->buf;
+       r->cmd = el->el_state.thiscmd;
+       r->ch = el->el_state.thisch;
+}
+
+/* cv_yank():
+ *     Save yank/delete data for paste
+ */
+protected void
+cv_yank(EditLine *el, const Char *ptr, int size)
+{
+       c_kill_t *k = &el->el_chared.c_kill;
+
+       (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf));
+       k->last = k->buf + size;
+}
+
+
+/* c_insert():
+ *     Insert num characters
+ */
+protected void
+c_insert(EditLine *el, int num)
+{
+       Char *cp;
+
+       if (el->el_line.lastchar + num >= el->el_line.limit) {
+               if (!ch_enlargebufs(el, (size_t)num))
+                       return;         /* can't go past end of buffer */
+       }
+
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               /* if I must move chars */
+               for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
+                       cp[num] = *cp;
+       }
+       el->el_line.lastchar += num;
+}
+
+
+/* c_delafter():
+ *     Delete num characters after the cursor
+ */
+protected void
+c_delafter(EditLine *el, int num)
+{
+
+       if (el->el_line.cursor + num > el->el_line.lastchar)
+               num = (int)(el->el_line.lastchar - el->el_line.cursor);
+
+       if (el->el_map.current != el->el_map.emacs) {
+               cv_undo(el);
+               cv_yank(el, el->el_line.cursor, num);
+       }
+
+       if (num > 0) {
+               Char *cp;
+
+               for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+                       *cp = cp[num];
+
+               el->el_line.lastchar -= num;
+       }
+}
+
+
+/* c_delafter1():
+ *     Delete the character after the cursor, do not yank
+ */
+protected void
+c_delafter1(EditLine *el)
+{
+       Char *cp;
+
+       for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+               *cp = cp[1];
+
+       el->el_line.lastchar--;
+}
+
+
+/* c_delbefore():
+ *     Delete num characters before the cursor
+ */
+protected void
+c_delbefore(EditLine *el, int num)
+{
+
+       if (el->el_line.cursor - num < el->el_line.buffer)
+               num = (int)(el->el_line.cursor - el->el_line.buffer);
+
+       if (el->el_map.current != el->el_map.emacs) {
+               cv_undo(el);
+               cv_yank(el, el->el_line.cursor - num, num);
+       }
+
+       if (num > 0) {
+               Char *cp;
+
+               for (cp = el->el_line.cursor - num;
+                   cp <= el->el_line.lastchar;
+                   cp++)
+                       *cp = cp[num];
+
+               el->el_line.lastchar -= num;
+       }
+}
+
+
+/* c_delbefore1():
+ *     Delete the character before the cursor, do not yank
+ */
+protected void
+c_delbefore1(EditLine *el)
+{
+       Char *cp;
+
+       for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
+               *cp = cp[1];
+
+       el->el_line.lastchar--;
+}
+
+
+/* ce__isword():
+ *     Return if p is part of a word according to emacs
+ */
+protected int
+ce__isword(Int p)
+{
+       return Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL;
+}
+
+
+/* cv__isword():
+ *     Return if p is part of a word according to vi
+ */
+protected int
+cv__isword(Int p)
+{
+       if (Isalnum(p) || p == '_')
+               return 1;
+       if (Isgraph(p))
+               return 2;
+       return 0;
+}
+
+
+/* cv__isWord():
+ *     Return if p is part of a big word according to vi
+ */
+protected int
+cv__isWord(Int p)
+{
+       return !Isspace(p);
+}
+
+
+/* c__prev_word():
+ *     Find the previous word
+ */
+protected Char *
+c__prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
+{
+       p--;
+
+       while (n--) {
+               while ((p >= low) && !(*wtest)(*p))
+                       p--;
+               while ((p >= low) && (*wtest)(*p))
+                       p--;
+       }
+
+       /* cp now points to one character before the word */
+       p++;
+       if (p < low)
+               p = low;
+       /* cp now points where we want it */
+       return p;
+}
+
+
+/* c__next_word():
+ *     Find the next word
+ */
+protected Char *
+c__next_word(Char *p, Char *high, int n, int (*wtest)(Int))
+{
+       while (n--) {
+               while ((p < high) && !(*wtest)(*p))
+                       p++;
+               while ((p < high) && (*wtest)(*p))
+                       p++;
+       }
+       if (p > high)
+               p = high;
+       /* p now points where we want it */
+       return p;
+}
+
+/* cv_next_word():
+ *     Find the next word vi style
+ */
+protected Char *
+cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(Int))
+{
+       int test;
+
+       while (n--) {
+               test = (*wtest)(*p);
+               while ((p < high) && (*wtest)(*p) == test)
+                       p++;
+               /*
+                * vi historically deletes with cw only the word preserving the
+                * trailing whitespace! This is not what 'w' does..
+                */
+               if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
+                       while ((p < high) && Isspace(*p))
+                               p++;
+       }
+
+       /* p now points where we want it */
+       if (p > high)
+               return high;
+       else
+               return p;
+}
+
+
+/* cv_prev_word():
+ *     Find the previous word vi style
+ */
+protected Char *
+cv_prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
+{
+       int test;
+
+       p--;
+       while (n--) {
+               while ((p > low) && Isspace(*p))
+                       p--;
+               test = (*wtest)(*p);
+               while ((p >= low) && (*wtest)(*p) == test)
+                       p--;
+       }
+       p++;
+
+       /* p now points where we want it */
+       if (p < low)
+               return low;
+       else
+               return p;
+}
+
+
+/* cv_delfini():
+ *     Finish vi delete action
+ */
+protected void
+cv_delfini(EditLine *el)
+{
+       int size;
+       int action = el->el_chared.c_vcmd.action;
+
+       if (action & INSERT)
+               el->el_map.current = el->el_map.key;
+
+       if (el->el_chared.c_vcmd.pos == 0)
+               /* sanity */
+               return;
+
+       size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
+       if (size == 0)
+               size = 1;
+       el->el_line.cursor = el->el_chared.c_vcmd.pos;
+       if (action & YANK) {
+               if (size > 0)
+                       cv_yank(el, el->el_line.cursor, size);
+               else
+                       cv_yank(el, el->el_line.cursor + size, -size);
+       } else {
+               if (size > 0) {
+                       c_delafter(el, size);
+                       re_refresh_cursor(el);
+               } else  {
+                       c_delbefore(el, -size);
+                       el->el_line.cursor += size;
+               }
+       }
+       el->el_chared.c_vcmd.action = NOP;
+}
+
+
+/* cv__endword():
+ *     Go to the end of this word according to vi
+ */
+protected Char *
+cv__endword(Char *p, Char *high, int n, int (*wtest)(Int))
+{
+       int test;
+
+       p++;
+
+       while (n--) {
+               while ((p < high) && Isspace(*p))
+                       p++;
+
+               test = (*wtest)(*p);
+               while ((p < high) && (*wtest)(*p) == test)
+                       p++;
+       }
+       p--;
+       return p;
+}
+
+/* ch_init():
+ *     Initialize the character editor
+ */
+protected int
+ch_init(EditLine *el)
+{
+       c_macro_t *ma = &el->el_chared.c_macro;
+
+       el->el_line.buffer              = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_line.buffer));
+       if (el->el_line.buffer == NULL)
+               return -1;
+
+       (void) memset(el->el_line.buffer, 0, EL_BUFSIZ *
+           sizeof(*el->el_line.buffer));
+       el->el_line.cursor              = el->el_line.buffer;
+       el->el_line.lastchar            = el->el_line.buffer;
+       el->el_line.limit               = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
+
+       el->el_chared.c_undo.buf        = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_chared.c_undo.buf));
+       if (el->el_chared.c_undo.buf == NULL)
+               return -1;
+       (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ *
+           sizeof(*el->el_chared.c_undo.buf));
+       el->el_chared.c_undo.len        = -1;
+       el->el_chared.c_undo.cursor     = 0;
+       el->el_chared.c_redo.buf        = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_chared.c_redo.buf));
+       if (el->el_chared.c_redo.buf == NULL)
+               return -1;
+       el->el_chared.c_redo.pos        = el->el_chared.c_redo.buf;
+       el->el_chared.c_redo.lim        = el->el_chared.c_redo.buf + EL_BUFSIZ;
+       el->el_chared.c_redo.cmd        = ED_UNASSIGNED;
+
+       el->el_chared.c_vcmd.action     = NOP;
+       el->el_chared.c_vcmd.pos        = el->el_line.buffer;
+
+       el->el_chared.c_kill.buf        = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_chared.c_kill.buf));
+       if (el->el_chared.c_kill.buf == NULL)
+               return -1;
+       (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ *
+           sizeof(*el->el_chared.c_kill.buf));
+       el->el_chared.c_kill.mark       = el->el_line.buffer;
+       el->el_chared.c_kill.last       = el->el_chared.c_kill.buf;
+       el->el_chared.c_resizefun       = NULL;
+       el->el_chared.c_resizearg       = NULL;
+
+       el->el_map.current              = el->el_map.key;
+
+       el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
+       el->el_state.doingarg           = 0;
+       el->el_state.metanext           = 0;
+       el->el_state.argument           = 1;
+       el->el_state.lastcmd            = ED_UNASSIGNED;
+
+       ma->level       = -1;
+       ma->offset      = 0;
+       ma->macro       = el_malloc(EL_MAXMACRO * sizeof(*ma->macro));
+       if (ma->macro == NULL)
+               return -1;
+       return 0;
+}
+
+/* ch_reset():
+ *     Reset the character editor
+ */
+protected void
+ch_reset(EditLine *el, int mclear)
+{
+       el->el_line.cursor              = el->el_line.buffer;
+       el->el_line.lastchar            = el->el_line.buffer;
+
+       el->el_chared.c_undo.len        = -1;
+       el->el_chared.c_undo.cursor     = 0;
+
+       el->el_chared.c_vcmd.action     = NOP;
+       el->el_chared.c_vcmd.pos        = el->el_line.buffer;
+
+       el->el_chared.c_kill.mark       = el->el_line.buffer;
+
+       el->el_map.current              = el->el_map.key;
+
+       el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
+       el->el_state.doingarg           = 0;
+       el->el_state.metanext           = 0;
+       el->el_state.argument           = 1;
+       el->el_state.lastcmd            = ED_UNASSIGNED;
+
+       el->el_history.eventno          = 0;
+
+       if (mclear)
+               ch__clearmacro(el);
+}
+
+private void
+ch__clearmacro(EditLine *el)
+{
+       c_macro_t *ma = &el->el_chared.c_macro;
+       while (ma->level >= 0)
+               el_free(ma->macro[ma->level--]);
+}
+
+/* ch_enlargebufs():
+ *     Enlarge line buffer to be able to hold twice as much characters.
+ *     Returns 1 if successful, 0 if not.
+ */
+protected int
+ch_enlargebufs(EditLine *el, size_t addlen)
+{
+       size_t sz, newsz;
+       Char *newbuffer, *oldbuf, *oldkbuf;
+
+       sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
+       newsz = sz * 2;
+       /*
+        * If newly required length is longer than current buffer, we need
+        * to make the buffer big enough to hold both old and new stuff.
+        */
+       if (addlen > sz) {
+               while(newsz - sz < addlen)
+                       newsz *= 2;
+       }
+
+       /*
+        * Reallocate line buffer.
+        */
+       newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
+           
+       oldbuf = el->el_line.buffer;
+
+       el->el_line.buffer = newbuffer;
+       el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
+       el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
+       /* don't set new size until all buffers are enlarged */
+       el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
+
+       /*
+        * Reallocate kill buffer.
+        */
+       newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
+           sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
+
+       oldkbuf = el->el_chared.c_kill.buf;
+
+       el->el_chared.c_kill.buf = newbuffer;
+       el->el_chared.c_kill.last = newbuffer +
+                                       (el->el_chared.c_kill.last - oldkbuf);
+       el->el_chared.c_kill.mark = el->el_line.buffer +
+                                       (el->el_chared.c_kill.mark - oldbuf);
+
+       /*
+        * Reallocate undo buffer.
+        */
+       newbuffer = el_realloc(el->el_chared.c_undo.buf,
+           newsz * sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
+       el->el_chared.c_undo.buf = newbuffer;
+
+       newbuffer = el_realloc(el->el_chared.c_redo.buf,
+           newsz * sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+       el->el_chared.c_redo.pos = newbuffer +
+                       (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
+       el->el_chared.c_redo.lim = newbuffer +
+                       (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
+       el->el_chared.c_redo.buf = newbuffer;
+       
+       if (!hist_enlargebuf(el, sz, newsz))
+               return 0;
+
+       /* Safe to set enlarged buffer size */
+       el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
+       if (el->el_chared.c_resizefun)
+               (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
+       return 1;
+}
+
+/* ch_end():
+ *     Free the data structures used by the editor
+ */
+protected void
+ch_end(EditLine *el)
+{
+       el_free(el->el_line.buffer);
+       el->el_line.buffer = NULL;
+       el->el_line.limit = NULL;
+       el_free(el->el_chared.c_undo.buf);
+       el->el_chared.c_undo.buf = NULL;
+       el_free(el->el_chared.c_redo.buf);
+       el->el_chared.c_redo.buf = NULL;
+       el->el_chared.c_redo.pos = NULL;
+       el->el_chared.c_redo.lim = NULL;
+       el->el_chared.c_redo.cmd = ED_UNASSIGNED;
+       el_free(el->el_chared.c_kill.buf);
+       el->el_chared.c_kill.buf = NULL;
+       ch_reset(el, 1);
+       el_free(el->el_chared.c_macro.macro);
+       el->el_chared.c_macro.macro = NULL;
+}
+
+
+/* el_insertstr():
+ *     Insert string at cursorI
+ */
+public int
+FUN(el,insertstr)(EditLine *el, const Char *s)
+{
+       size_t len;
+
+       if (s == NULL || (len = Strlen(s)) == 0)
+               return -1;
+       if (el->el_line.lastchar + len >= el->el_line.limit) {
+               if (!ch_enlargebufs(el, len))
+                       return -1;
+       }
+
+       c_insert(el, (int)len);
+       while (*s)
+               *el->el_line.cursor++ = *s++;
+       return 0;
+}
+
+
+/* el_deletestr():
+ *     Delete num characters before the cursor
+ */
+public void
+el_deletestr(EditLine *el, int n)
+{
+       if (n <= 0)
+               return;
+
+       if (el->el_line.cursor < &el->el_line.buffer[n])
+               return;
+
+       c_delbefore(el, n);             /* delete before dot */
+       el->el_line.cursor -= n;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+}
+
+/* c_gets():
+ *     Get a string
+ */
+protected int
+c_gets(EditLine *el, Char *buf, const Char *prompt)
+{
+       Char ch;
+       ssize_t len;
+       Char *cp = el->el_line.buffer;
+
+       if (prompt) {
+               len = (ssize_t)Strlen(prompt);
+               (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
+               cp += len;
+       }
+       len = 0;
+
+       for (;;) {
+               el->el_line.cursor = cp;
+               *cp = ' ';
+               el->el_line.lastchar = cp + 1;
+               re_refresh(el);
+
+               if (FUN(el,getc)(el, &ch) != 1) {
+                       ed_end_of_file(el, 0);
+                       len = -1;
+                       break;
+               }
+
+               switch (ch) {
+
+               case 0010:      /* Delete and backspace */
+               case 0177:
+                       if (len == 0) {
+                               len = -1;
+                               break;
+                       }
+                       cp--;
+                       continue;
+
+               case 0033:      /* ESC */
+               case '\r':      /* Newline */
+               case '\n':
+                       buf[len] = ch;
+                       break;
+
+               default:
+                       if (len >= (ssize_t)(EL_BUFSIZ - 16))
+                               terminal_beep(el);
+                       else {
+                               buf[len++] = ch;
+                               *cp++ = ch;
+                       }
+                       continue;
+               }
+               break;
+       }
+
+       el->el_line.buffer[0] = '\0';
+       el->el_line.lastchar = el->el_line.buffer;
+       el->el_line.cursor = el->el_line.buffer;
+       return (int)len;
+}
+
+
+/* c_hpos():
+ *     Return the current horizontal position of the cursor
+ */
+protected int
+c_hpos(EditLine *el)
+{
+       Char *ptr;
+
+       /*
+        * Find how many characters till the beginning of this line.
+        */
+       if (el->el_line.cursor == el->el_line.buffer)
+               return 0;
+       else {
+               for (ptr = el->el_line.cursor - 1;
+                    ptr >= el->el_line.buffer && *ptr != '\n';
+                    ptr--)
+                       continue;
+               return (int)(el->el_line.cursor - ptr - 1);
+       }
+}
+
+protected int
+ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
+{
+       el->el_chared.c_resizefun = f;
+       el->el_chared.c_resizearg = a;
+       return 0;
+}
diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h
new file mode 100644 (file)
index 0000000..176475a
--- /dev/null
@@ -0,0 +1,171 @@
+/*     $NetBSD: chared.h,v 1.21 2010/08/28 15:44:59 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)chared.h    8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.chared.h: Character editor interface
+ */
+#ifndef _h_el_chared
+#define        _h_el_chared
+
+#include <ctype.h>
+#include <string.h>
+
+#include "histedit.h"
+
+#define        EL_MAXMACRO     10
+
+/*
+ * This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works
+ * like real vi: i.e. the transition from command<->insert modes moves
+ * the cursor.
+ *
+ * On the other hand we really don't want to move the cursor, because
+ * all the editing commands don't include the character under the cursor.
+ * Probably the best fix is to make all the editing commands aware of
+ * this fact.
+ */
+#define        VI_MOVE
+
+
+typedef struct c_macro_t {
+       int       level;
+       int       offset;
+       Char    **macro;
+} c_macro_t;
+
+/*
+ * Undo information for vi - no undo in emacs (yet)
+ */
+typedef struct c_undo_t {
+       ssize_t  len;                   /* length of saved line */
+       int      cursor;                /* position of saved cursor */
+       Char    *buf;                   /* full saved text */
+} c_undo_t;
+
+/* redo for vi */
+typedef struct c_redo_t {
+       Char    *buf;                   /* redo insert key sequence */
+       Char    *pos;
+       Char    *lim;
+       el_action_t     cmd;            /* command to redo */
+       Char    ch;                     /* char that invoked it */
+       int     count;
+       int     action;                 /* from cv_action() */
+} c_redo_t;
+
+/*
+ * Current action information for vi
+ */
+typedef struct c_vcmd_t {
+       int      action;
+       Char    *pos;
+} c_vcmd_t;
+
+/*
+ * Kill buffer for emacs
+ */
+typedef struct c_kill_t {
+       Char    *buf;
+       Char    *last;
+       Char    *mark;
+} c_kill_t;
+
+typedef void (*el_zfunc_t)(EditLine *, void *);
+
+/*
+ * Note that we use both data structures because the user can bind
+ * commands from both editors!
+ */
+typedef struct el_chared_t {
+       c_undo_t        c_undo;
+       c_kill_t        c_kill;
+       c_redo_t        c_redo;
+       c_vcmd_t        c_vcmd;
+       c_macro_t       c_macro;
+       el_zfunc_t      c_resizefun;
+       void *          c_resizearg;
+} el_chared_t;
+
+
+#define        STRQQ           "\"\""
+
+#define        isglob(a)       (strchr("*[]?", (a)) != NULL)
+
+#define        NOP             0x00
+#define        DELETE          0x01
+#define        INSERT          0x02
+#define        YANK            0x04
+
+#define        CHAR_FWD        (+1)
+#define        CHAR_BACK       (-1)
+
+#define        MODE_INSERT     0
+#define        MODE_REPLACE    1
+#define        MODE_REPLACE_1  2
+
+#include "common.h"
+#include "vi.h"
+#include "emacs.h"
+#include "search.h"
+#include "fcns.h"
+
+
+protected int   cv__isword(Int);
+protected int   cv__isWord(Int);
+protected void  cv_delfini(EditLine *);
+protected Char *cv__endword(Char *, Char *, int, int (*)(Int));
+protected int   ce__isword(Int);
+protected void  cv_undo(EditLine *);
+protected void  cv_yank(EditLine *, const Char *, int);
+protected Char *cv_next_word(EditLine*, Char *, Char *, int, int (*)(Int));
+protected Char *cv_prev_word(Char *, Char *, int, int (*)(Int));
+protected Char *c__next_word(Char *, Char *, int, int (*)(Int));
+protected Char *c__prev_word(Char *, Char *, int, int (*)(Int));
+protected void  c_insert(EditLine *, int);
+protected void  c_delbefore(EditLine *, int);
+protected void  c_delbefore1(EditLine *);
+protected void  c_delafter(EditLine *, int);
+protected void  c_delafter1(EditLine *);
+protected int   c_gets(EditLine *, Char *, const Char *);
+protected int   c_hpos(EditLine *);
+
+protected int   ch_init(EditLine *);
+protected void  ch_reset(EditLine *, int);
+protected int   ch_resizefun(EditLine *, el_zfunc_t, void *);
+protected int   ch_enlargebufs(EditLine *, size_t);
+protected void  ch_end(EditLine *);
+
+#endif /* _h_el_chared */
diff --git a/lib/libedit/chartype.c b/lib/libedit/chartype.c
new file mode 100644 (file)
index 0000000..8766aac
--- /dev/null
@@ -0,0 +1,356 @@
+/*     $NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $   */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * chartype.c: character classification and meta information
+ */
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+__RCSID("$NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $");
+#endif /* not lint && not SCCSID */
+#include "el.h"
+#include <stdlib.h>
+
+#define CT_BUFSIZ ((size_t)1024)
+
+#ifdef WIDECHAR
+protected void
+ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
+{
+       void *p;
+       if (mincsize > conv->csize) {
+               conv->csize = mincsize;
+               p = el_realloc(conv->cbuff, conv->csize * sizeof(*conv->cbuff));
+               if (p == NULL) {
+                       conv->csize = 0;
+                       el_free(conv->cbuff);
+                       conv->cbuff = NULL;
+               } else 
+                       conv->cbuff = p;
+       }
+
+       if (minwsize > conv->wsize) {
+               conv->wsize = minwsize;
+               p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff));
+               if (p == NULL) {
+                       conv->wsize = 0;
+                       el_free(conv->wbuff);
+                       conv->wbuff = NULL;
+               } else
+                       conv->wbuff = p;
+       }
+}
+
+
+public char *
+ct_encode_string(const Char *s, ct_buffer_t *conv)
+{
+       char *dst;
+       ssize_t used = 0;
+
+       if (!s)
+               return NULL;
+       if (!conv->cbuff)
+               ct_conv_buff_resize(conv, CT_BUFSIZ, (size_t)0);
+       if (!conv->cbuff)
+               return NULL;
+
+       dst = conv->cbuff;
+       while (*s) {
+               used = (ssize_t)(conv->csize - (size_t)(dst - conv->cbuff));
+               if (used < 5) {
+                       used = dst - conv->cbuff;
+                       ct_conv_buff_resize(conv, conv->csize + CT_BUFSIZ,
+                           (size_t)0);
+                       if (!conv->cbuff)
+                               return NULL;
+                       dst = conv->cbuff + used;
+               }
+               used = ct_encode_char(dst, (size_t)5, *s);
+               if (used == -1) /* failed to encode, need more buffer space */
+                       abort();
+               ++s;
+               dst += used;
+       }
+       *dst = '\0';
+       return conv->cbuff;
+}
+
+public Char *
+ct_decode_string(const char *s, ct_buffer_t *conv)
+{
+       size_t len = 0;
+
+       if (!s)
+               return NULL;
+       if (!conv->wbuff)
+               ct_conv_buff_resize(conv, (size_t)0, CT_BUFSIZ);
+       if (!conv->wbuff)
+               return NULL;
+
+       len = ct_mbstowcs(NULL, s, (size_t)0);
+       if (len == (size_t)-1)
+               return NULL;
+       if (len > conv->wsize)
+               ct_conv_buff_resize(conv, (size_t)0, len + 1);
+       if (!conv->wbuff)
+               return NULL;
+       ct_mbstowcs(conv->wbuff, s, conv->wsize);
+       return conv->wbuff;
+}
+
+
+protected Char **
+ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
+{
+       size_t bufspace;
+       int i;
+       Char *p;
+       Char **wargv;
+       ssize_t bytes;
+
+       /* Make sure we have enough space in the conversion buffer to store all
+        * the argv strings. */
+       for (i = 0, bufspace = 0; i < argc; ++i)
+               bufspace += argv[i] ? strlen(argv[i]) + 1 : 0;
+       ct_conv_buff_resize(conv, (size_t)0, bufspace);
+       if (!conv->wsize)
+               return NULL;
+
+       wargv = el_malloc((size_t)argc * sizeof(*wargv));
+
+       for (i = 0, p = conv->wbuff; i < argc; ++i) {
+               if (!argv[i]) {   /* don't pass null pointers to mbstowcs */
+                       wargv[i] = NULL;
+                       continue;
+               } else {
+                       wargv[i] = p;
+                       bytes = (ssize_t)mbstowcs(p, argv[i], bufspace);
+               }
+               if (bytes == -1) {
+                       el_free(wargv);
+                       return NULL;
+               } else
+                       bytes++;  /* include '\0' in the count */
+               bufspace -= (size_t)bytes;
+               p += bytes;
+       }
+
+       return wargv;
+}
+
+
+protected size_t
+ct_enc_width(Char c)
+{
+       /* UTF-8 encoding specific values */
+       if (c < 0x80)
+               return 1;
+       else if (c < 0x0800)
+               return 2;
+       else if (c < 0x10000)
+               return 3;
+       else if (c < 0x110000)
+               return 4;
+       else
+               return 0; /* not a valid codepoint */
+}
+
+protected ssize_t
+ct_encode_char(char *dst, size_t len, Char c)
+{
+       ssize_t l = 0;
+       if (len < ct_enc_width(c))
+               return -1;
+       l = ct_wctomb(dst, c);
+
+       if (l < 0) {
+               ct_wctomb_reset;
+               l = 0;
+       }
+       return l;
+}
+#endif
+
+protected const Char *
+ct_visual_string(const Char *s)
+{
+       static Char *buff = NULL;
+       static size_t buffsize = 0;
+       void *p;
+       Char *dst;
+       ssize_t used = 0;
+
+       if (!s)
+               return NULL;
+       if (!buff) {
+           buffsize = CT_BUFSIZ;
+           buff = el_malloc(buffsize * sizeof(*buff));
+       }
+       dst = buff;
+       while (*s) {
+               used = ct_visual_char(dst, buffsize - (size_t)(dst - buff), *s);
+               if (used == -1) { /* failed to encode, need more buffer space */
+                       used = dst - buff;
+                       buffsize += CT_BUFSIZ;
+                       p = el_realloc(buff, buffsize * sizeof(*buff));
+                       if (p == NULL)
+                               goto out;
+                       buff = p;
+                       dst = buff + used;
+                       /* don't increment s here - we want to retry it! */
+               }
+               else
+                   ++s;
+               dst += used;
+       }
+       if (dst >= (buff + buffsize)) { /* sigh */
+               buffsize += 1;
+               p = el_realloc(buff, buffsize * sizeof(*buff));
+               if (p == NULL)
+                       goto out;
+               buff = p;
+               dst = buff + buffsize - 1;
+       }
+       *dst = 0;
+       return buff;
+out:
+       el_free(buff);
+       buffsize = 0;
+       return NULL;
+}
+
+
+
+protected int
+ct_visual_width(Char c)
+{
+       int t = ct_chr_class(c);
+       switch (t) {
+       case CHTYPE_ASCIICTL:
+               return 2; /* ^@ ^? etc. */
+       case CHTYPE_TAB:
+               return 1; /* Hmm, this really need to be handled outside! */
+       case CHTYPE_NL:
+               return 0; /* Should this be 1 instead? */
+#ifdef WIDECHAR
+       case CHTYPE_PRINT:
+               return wcwidth(c);
+       case CHTYPE_NONPRINT:
+               if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
+                       return 8; /* \U+12345 */
+               else
+                       return 7; /* \U+1234 */
+#else
+       case CHTYPE_PRINT:
+               return 1;
+       case CHTYPE_NONPRINT:
+               return 4; /* \123 */
+#endif
+       default:
+               return 0; /* should not happen */
+       }
+}
+
+
+protected ssize_t
+ct_visual_char(Char *dst, size_t len, Char c)
+{
+       int t = ct_chr_class(c);
+       switch (t) {
+       case CHTYPE_TAB:
+       case CHTYPE_NL:
+       case CHTYPE_ASCIICTL:
+               if (len < 2)
+                       return -1;   /* insufficient space */
+               *dst++ = '^';
+               if (c == '\177')
+                       *dst = '?'; /* DEL -> ^? */
+               else
+                       *dst = c | 0100;    /* uncontrolify it */
+               return 2;
+       case CHTYPE_PRINT:
+               if (len < 1)
+                       return -1;  /* insufficient space */
+               *dst = c;
+               return 1;
+       case CHTYPE_NONPRINT:
+               /* we only use single-width glyphs for display,
+                * so this is right */
+               if ((ssize_t)len < ct_visual_width(c))
+                       return -1;   /* insufficient space */
+#ifdef WIDECHAR
+               *dst++ = '\\';
+               *dst++ = 'U';
+               *dst++ = '+';
+#define tohexdigit(v) "0123456789ABCDEF"[v]
+               if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
+                       *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf);
+               *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf);
+               *dst++ = tohexdigit(((unsigned int) c >>  8) & 0xf);
+               *dst++ = tohexdigit(((unsigned int) c >>  4) & 0xf);
+               *dst   = tohexdigit(((unsigned int) c      ) & 0xf);
+               return c > 0xffff ? 8 : 7;
+#else
+               *dst++ = '\\';
+#define tooctaldigit(v) ((v) + '0')
+               *dst++ = tooctaldigit(((unsigned int) c >> 6) & 0x7);
+               *dst++ = tooctaldigit(((unsigned int) c >> 3) & 0x7);
+               *dst++ = tooctaldigit(((unsigned int) c     ) & 0x7);
+#endif
+               /*FALLTHROUGH*/
+       /* these two should be handled outside this function */
+       default:            /* we should never hit the default */
+               return 0;
+       }
+}
+
+
+
+
+protected int
+ct_chr_class(Char c)
+{
+       if (c == '\t')
+               return CHTYPE_TAB;
+       else if (c == '\n')
+               return CHTYPE_NL;
+       else if (IsASCII(c) && Iscntrl(c))
+               return CHTYPE_ASCIICTL;
+       else if (Isprint(c))
+               return CHTYPE_PRINT;
+       else
+               return CHTYPE_NONPRINT;
+}
diff --git a/lib/libedit/chartype.h b/lib/libedit/chartype.h
new file mode 100644 (file)
index 0000000..b85a578
--- /dev/null
@@ -0,0 +1,250 @@
+/*     $NetBSD: chartype.h,v 1.10 2011/11/16 01:45:10 christos Exp $   */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _h_chartype_f
+#define _h_chartype_f
+
+
+
+#ifdef WIDECHAR
+
+/* Ideally we should also test the value of the define to see if it
+ * supports non-BMP code points without requiring UTF-16, but nothing
+ * seems to actually advertise this properly, despite Unicode 3.1 having
+ * been around since 2001... */
+#if !defined(__minix) && !defined(__NetBSD__) && !defined(__sun) && !(defined(__APPLE__) && defined(__MACH__))
+#ifndef __STDC_ISO_10646__
+/* In many places it is assumed that the first 127 code points are ASCII
+ * compatible, so ensure wchar_t indeed does ISO 10646 and not some other
+ * funky encoding that could break us in weird and wonderful ways. */
+       #error wchar_t must store ISO 10646 characters
+#endif
+#endif
+
+/* Oh for a <uchar.h> with char32_t and __STDC_UTF_32__ in it...
+ * ref: ISO/IEC DTR 19769
+ */
+#if WCHAR_MAX < INT32_MAX
+#warning Build environment does not support non-BMP characters
+#endif
+
+#define ct_mbtowc            mbtowc
+#define ct_mbtowc_reset      mbtowc(0,0,(size_t)0)
+#define ct_wctomb            wctomb
+#define ct_wctomb_reset      wctomb(0,0)
+#define ct_wcstombs          wcstombs
+#define ct_mbstowcs          mbstowcs
+
+#define Char                   wchar_t
+#define Int                    wint_t
+#define FUN(prefix,rest)       prefix ## _w ## rest
+#define FUNW(type)             type ## _w
+#define TYPE(type)             type ## W
+#define FSTR                   "%ls"
+#define STR(x)                         L ## x
+#define UC(c)                  c
+#define Isalpha(x)  iswalpha(x)
+#define Isalnum(x)  iswalnum(x)
+#define Isgraph(x)  iswgraph(x)
+#define Isspace(x)  iswspace(x)
+#define Isdigit(x)  iswdigit(x)
+#define Iscntrl(x)  iswcntrl(x)
+#define Isprint(x)  iswprint(x)
+
+#define Isupper(x)  iswupper(x)
+#define Islower(x)  iswlower(x)
+#define Toupper(x)  towupper(x)
+#define Tolower(x)  towlower(x)
+
+#define IsASCII(x)  (x < 0x100)
+
+#define Strlen(x)       wcslen(x)
+#define Strchr(s,c)     wcschr(s,c)
+#define Strrchr(s,c)    wcsrchr(s,c)
+#define Strstr(s,v)     wcsstr(s,v)
+#define Strdup(x)       wcsdup(x)
+#define Strcpy(d,s)     wcscpy(d,s)
+#define Strncpy(d,s,n)  wcsncpy(d,s,n)
+#define Strncat(d,s,n)  wcsncat(d,s,n)
+
+#define Strcmp(s,v)     wcscmp(s,v)
+#define Strncmp(s,v,n)  wcsncmp(s,v,n)
+#define Strcspn(s,r)    wcscspn(s,r)
+
+#define Strtol(p,e,b)   wcstol(p,e,b)
+
+static inline int
+Width(wchar_t c)
+{
+       int w = wcwidth(c);
+       return w < 0 ? 0 : w;
+}
+
+#else /* NARROW */
+
+#define ct_mbtowc            error
+#define ct_mbtowc_reset      
+#define ct_wctomb            error
+#define ct_wctomb_reset      
+#define ct_wcstombs(a, b, c)    (strncpy(a, b, c), strlen(a))
+#define ct_mbstowcs(a, b, c)    (strncpy(a, b, c), strlen(a))
+
+#define Char                   char
+#define Int                    int
+#define FUN(prefix,rest)       prefix ## _ ## rest
+#define FUNW(type)             type
+#define TYPE(type)             type
+#define FSTR                   "%s"
+#define STR(x)                         x
+#define UC(c)                  (unsigned char)(c)
+
+#define Isalpha(x)  isalpha((unsigned char)x)
+#define Isalnum(x)  isalnum((unsigned char)x)
+#define Isgraph(x)  isgraph((unsigned char)x)
+#define Isspace(x)  isspace((unsigned char)x)
+#define Isdigit(x)  isdigit((unsigned char)x)
+#define Iscntrl(x)  iscntrl((unsigned char)x)
+#define Isprint(x)  isprint((unsigned char)x)
+
+#define Isupper(x)  isupper((unsigned char)x)
+#define Islower(x)  islower((unsigned char)x)
+#define Toupper(x)  toupper((unsigned char)x)
+#define Tolower(x)  tolower((unsigned char)x)
+
+#define IsASCII(x)  isascii((unsigned char)x)
+
+#define Strlen(x)       strlen(x)
+#define Strchr(s,c)     strchr(s,c)
+#define Strrchr(s,c)    strrchr(s,c)
+#define Strstr(s,v)     strstr(s,v)
+#define Strdup(x)       strdup(x)
+#define Strcpy(d,s)     strcpy(d,s)
+#define Strncpy(d,s,n)  strncpy(d,s,n)
+#define Strncat(d,s,n)  strncat(d,s,n)
+
+#define Strcmp(s,v)     strcmp(s,v)
+#define Strncmp(s,v,n)  strncmp(s,v,n)
+#define Strcspn(s,r)    strcspn(s,r)
+
+#define Strtol(p,e,b)   strtol(p,e,b)
+
+#define Width(c)       1
+
+#endif
+
+
+#ifdef WIDECHAR
+/*
+ * Conversion buffer
+ */
+typedef struct ct_buffer_t {
+        char    *cbuff;
+        size_t  csize;
+        Char *wbuff;
+        size_t  wsize;
+} ct_buffer_t;
+
+#define ct_encode_string __ct_encode_string
+/* Encode a wide-character string and return the UTF-8 encoded result. */
+public char *ct_encode_string(const Char *, ct_buffer_t *);
+
+#define ct_decode_string __ct_decode_string
+/* Decode a (multi)?byte string and return the wide-character string result. */
+public Char *ct_decode_string(const char *, ct_buffer_t *);
+
+/* Decode a (multi)?byte argv string array.
+ * The pointer returned must be free()d when done. */
+protected Char **ct_decode_argv(int, const char *[],  ct_buffer_t *);
+
+/* Resizes the conversion buffer(s) if needed. */
+protected void ct_conv_buff_resize(ct_buffer_t *, size_t, size_t);
+protected ssize_t ct_encode_char(char *, size_t, Char);
+protected size_t ct_enc_width(Char);
+
+#define ct_free_argv(s)        el_free(s)
+
+#else
+#define        ct_encode_string(s, b)  (s)
+#define ct_decode_string(s, b) (s)
+#define ct_decode_argv(l, s, b)        (s)
+#define ct_conv_buff_resize(b, os, ns)
+#define ct_encode_char(d, l, s)        (*d = s, 1)
+#define ct_free_argv(s)
+#endif
+
+#ifndef NARROWCHAR
+/* Encode a characted into the destination buffer, provided there is sufficent
+ * buffer space available. Returns the number of bytes used up (zero if the
+ * character cannot be encoded, -1 if there was not enough space available). */
+
+/* The maximum buffer size to hold the most unwieldly visual representation,
+ * in this case \U+nnnnn. */
+#define VISUAL_WIDTH_MAX ((size_t)8)
+
+/* The terminal is thought of in terms of X columns by Y lines. In the cases
+ * where a wide character takes up more than one column, the adjacent 
+ * occupied column entries will contain this faux character. */
+#define MB_FILL_CHAR ((Char)-1)
+
+/* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn
+ * style visual expansions. */
+protected int ct_visual_width(Char);
+
+/* Turn the given character into the appropriate visual format, matching
+ * the width given by ct_visual_width(). Returns the number of characters used
+ * up, or -1 if insufficient space. Buffer length is in count of Char's. */
+protected ssize_t ct_visual_char(Char *, size_t, Char);
+
+/* Convert the given string into visual format, using the ct_visual_char()
+ * function. Uses a static buffer, so not threadsafe. */
+protected const Char *ct_visual_string(const Char *);
+
+
+/* printable character, use ct_visual_width() to find out display width */
+#define CHTYPE_PRINT        ( 0)
+/* control character found inside the ASCII portion of the charset */
+#define CHTYPE_ASCIICTL     (-1)
+/* a \t */
+#define CHTYPE_TAB          (-2)
+/* a \n */
+#define CHTYPE_NL           (-3)
+/* non-printable character */
+#define CHTYPE_NONPRINT     (-4)
+/* classification of character c, as one of the above defines */
+protected int ct_chr_class(Char c);
+#endif
+
+
+#endif /* _chartype_f */
diff --git a/lib/libedit/common.c b/lib/libedit/common.c
new file mode 100644 (file)
index 0000000..1726b0f
--- /dev/null
@@ -0,0 +1,919 @@
+/*     $NetBSD: common.c,v 1.29 2012/03/24 20:08:43 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)common.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: common.c,v 1.29 2012/03/24 20:08:43 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * common.c: Common Editor functions
+ */
+#include "el.h"
+
+/* ed_end_of_file():
+ *     Indicate end of file
+ *     [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_end_of_file(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       re_goto_bottom(el);
+       *el->el_line.lastchar = '\0';
+       return CC_EOF;
+}
+
+
+/* ed_insert():
+ *     Add character to the line
+ *     Insert a character [bound to all insert keys]
+ */
+protected el_action_t
+ed_insert(EditLine *el, Int c)
+{
+       int count = el->el_state.argument;
+
+       if (c == '\0')
+               return CC_ERROR;
+
+       if (el->el_line.lastchar + el->el_state.argument >=
+           el->el_line.limit) {
+               /* end of buffer space, try to allocate more */
+               if (!ch_enlargebufs(el, (size_t) count))
+                       return CC_ERROR;        /* error allocating more */
+       }
+
+       if (count == 1) {
+               if (el->el_state.inputmode == MODE_INSERT
+                   || el->el_line.cursor >= el->el_line.lastchar)
+                       c_insert(el, 1);
+
+               *el->el_line.cursor++ = c;
+               re_fastaddc(el);                /* fast refresh for one char. */
+       } else {
+               if (el->el_state.inputmode != MODE_REPLACE_1)
+                       c_insert(el, el->el_state.argument);
+
+               while (count-- && el->el_line.cursor < el->el_line.lastchar)
+                       *el->el_line.cursor++ = c;
+               re_refresh(el);
+       }
+
+       if (el->el_state.inputmode == MODE_REPLACE_1)
+               return vi_command_mode(el, 0);
+
+       return CC_NORM;
+}
+
+
+/* ed_delete_prev_word():
+ *     Delete from beginning of current word to cursor
+ *     [M-^?] [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *p, *kp;
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+           el->el_state.argument, ce__isword);
+
+       for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
+               *kp++ = *p;
+       el->el_chared.c_kill.last = kp;
+
+       c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
+       el->el_line.cursor = cp;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer; /* bounds check */
+       return CC_REFRESH;
+}
+
+
+/* ed_delete_next_char():
+ *     Delete character under cursor
+ *     [^D] [x]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+#ifdef DEBUG_EDIT
+#define        EL      el->el_line
+       (void) fprintf(el->el_errlfile,
+           "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
+           EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
+           EL.lastchar, EL.limit, EL.limit);
+#endif
+       if (el->el_line.cursor == el->el_line.lastchar) {
+                       /* if I'm at the end */
+               if (el->el_map.type == MAP_VI) {
+                       if (el->el_line.cursor == el->el_line.buffer) {
+                               /* if I'm also at the beginning */
+#ifdef KSHVI
+                               return CC_ERROR;
+#else
+                               /* then do an EOF */
+                               terminal_writec(el, c);
+                               return CC_EOF;
+#endif
+                       } else {
+#ifdef KSHVI
+                               el->el_line.cursor--;
+#else
+                               return CC_ERROR;
+#endif
+                       }
+               } else
+                               return CC_ERROR;
+       }
+       c_delafter(el, el->el_state.argument);  /* delete after dot */
+       if (el->el_map.type == MAP_VI &&
+           el->el_line.cursor >= el->el_line.lastchar &&
+           el->el_line.cursor > el->el_line.buffer)
+                       /* bounds check */
+               el->el_line.cursor = el->el_line.lastchar - 1;
+       return CC_REFRESH;
+}
+
+
+/* ed_kill_line():
+ *     Cut to the end of line
+ *     [^K] [^K]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_kill_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       cp = el->el_line.cursor;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.lastchar)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+                       /* zap! -- delete to end */
+       el->el_line.lastchar = el->el_line.cursor;
+       return CC_REFRESH;
+}
+
+
+/* ed_move_to_end():
+ *     Move cursor to the end of line
+ *     [^E] [^E]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_move_to_end(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.lastchar;
+       if (el->el_map.type == MAP_VI) {
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+#ifdef VI_MOVE
+               el->el_line.cursor--;
+#endif
+       }
+       return CC_CURSOR;
+}
+
+
+/* ed_move_to_beg():
+ *     Move cursor to the beginning of line
+ *     [^A] [^A]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_move_to_beg(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.buffer;
+
+       if (el->el_map.type == MAP_VI) {
+                       /* We want FIRST non space character */
+               while (Isspace(*el->el_line.cursor))
+                       el->el_line.cursor++;
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       }
+       return CC_CURSOR;
+}
+
+
+/* ed_transpose_chars():
+ *     Exchange the character to the left of the cursor with the one under it
+ *     [^T] [^T]
+ */
+protected el_action_t
+ed_transpose_chars(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               if (el->el_line.lastchar <= &el->el_line.buffer[1])
+                       return CC_ERROR;
+               else
+                       el->el_line.cursor++;
+       }
+       if (el->el_line.cursor > &el->el_line.buffer[1]) {
+               /* must have at least two chars entered */
+               c = el->el_line.cursor[-2];
+               el->el_line.cursor[-2] = el->el_line.cursor[-1];
+               el->el_line.cursor[-1] = c;
+               return CC_REFRESH;
+       } else
+               return CC_ERROR;
+}
+
+
+/* ed_next_char():
+ *     Move to the right one character
+ *     [^F] [^F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *lim = el->el_line.lastchar;
+
+       if (el->el_line.cursor >= lim ||
+           (el->el_line.cursor == lim - 1 &&
+           el->el_map.type == MAP_VI &&
+           el->el_chared.c_vcmd.action == NOP))
+               return CC_ERROR;
+
+       el->el_line.cursor += el->el_state.argument;
+       if (el->el_line.cursor > lim)
+               el->el_line.cursor = lim;
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* ed_prev_word():
+ *     Move to the beginning of the current word
+ *     [M-b] [b]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       el->el_line.cursor = c__prev_word(el->el_line.cursor,
+           el->el_line.buffer,
+           el->el_state.argument,
+           ce__isword);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* ed_prev_char():
+ *     Move to the left one character
+ *     [^B] [^B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor > el->el_line.buffer) {
+               el->el_line.cursor -= el->el_state.argument;
+               if (el->el_line.cursor < el->el_line.buffer)
+                       el->el_line.cursor = el->el_line.buffer;
+
+               if (el->el_map.type == MAP_VI)
+                       if (el->el_chared.c_vcmd.action != NOP) {
+                               cv_delfini(el);
+                               return CC_REFRESH;
+                       }
+               return CC_CURSOR;
+       } else
+               return CC_ERROR;
+}
+
+
+/* ed_quoted_insert():
+ *     Add the next character typed verbatim
+ *     [^V] [^V]
+ */
+protected el_action_t
+ed_quoted_insert(EditLine *el, Int c)
+{
+       int num;
+       Char tc;
+
+       tty_quotemode(el);
+       num = FUN(el,getc)(el, &tc);
+       c = tc;
+       tty_noquotemode(el);
+       if (num == 1)
+               return ed_insert(el, c);
+       else
+               return ed_end_of_file(el, 0);
+}
+
+
+/* ed_digit():
+ *     Adds to argument or enters a digit
+ */
+protected el_action_t
+ed_digit(EditLine *el, Int c)
+{
+
+       if (!Isdigit(c))
+               return CC_ERROR;
+
+       if (el->el_state.doingarg) {
+                       /* if doing an arg, add this in... */
+               if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
+                       el->el_state.argument = c - '0';
+               else {
+                       if (el->el_state.argument > 1000000)
+                               return CC_ERROR;
+                       el->el_state.argument =
+                           (el->el_state.argument * 10) + (c - '0');
+               }
+               return CC_ARGHACK;
+       }
+
+       return ed_insert(el, c);
+}
+
+
+/* ed_argument_digit():
+ *     Digit that starts argument
+ *     For ESC-n
+ */
+protected el_action_t
+ed_argument_digit(EditLine *el, Int c)
+{
+
+       if (!Isdigit(c))
+               return CC_ERROR;
+
+       if (el->el_state.doingarg) {
+               if (el->el_state.argument > 1000000)
+                       return CC_ERROR;
+               el->el_state.argument = (el->el_state.argument * 10) +
+                   (c - '0');
+       } else {                /* else starting an argument */
+               el->el_state.argument = c - '0';
+               el->el_state.doingarg = 1;
+       }
+       return CC_ARGHACK;
+}
+
+
+/* ed_unassigned():
+ *     Indicates unbound character
+ *     Bound to keys that are not assigned
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_unassigned(EditLine *el __attribute__((__unused__)),
+    Int c __attribute__((__unused__)))
+{
+
+       return CC_ERROR;
+}
+
+
+/**
+ ** TTY key handling.
+ **/
+
+/* ed_tty_sigint():
+ *     Tty interrupt character
+ *     [^C]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigint(EditLine *el __attribute__((__unused__)), 
+             Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_dsusp():
+ *     Tty delayed suspend character
+ *     [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_dsusp(EditLine *el __attribute__((__unused__)), 
+            Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_flush_output():
+ *     Tty flush output characters
+ *     [^O]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_flush_output(EditLine *el __attribute__((__unused__)), 
+                   Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_sigquit():
+ *     Tty quit character
+ *     [^\]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigquit(EditLine *el __attribute__((__unused__)), 
+              Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_sigtstp():
+ *     Tty suspend character
+ *     [^Z]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), 
+              Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_stop_output():
+ *     Tty disallow output characters
+ *     [^S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_stop_output(EditLine *el __attribute__((__unused__)), 
+                  Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_start_output():
+ *     Tty allow output characters
+ *     [^Q]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_start_output(EditLine *el __attribute__((__unused__)), 
+                   Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_newline():
+ *     Execute command
+ *     [^J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_newline(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       re_goto_bottom(el);
+       *el->el_line.lastchar++ = '\n';
+       *el->el_line.lastchar = '\0';
+       return CC_NEWLINE;
+}
+
+
+/* ed_delete_prev_char():
+ *     Delete the character to the left of the cursor
+ *     [^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor <= el->el_line.buffer)
+               return CC_ERROR;
+
+       c_delbefore(el, el->el_state.argument);
+       el->el_line.cursor -= el->el_state.argument;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+       return CC_REFRESH;
+}
+
+
+/* ed_clear_screen():
+ *     Clear screen leaving current line at the top
+ *     [^L]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_clear_screen(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       terminal_clear_screen(el);      /* clear the whole real screen */
+       re_clear_display(el);   /* reset everything */
+       return CC_REFRESH;
+}
+
+
+/* ed_redisplay():
+ *     Redisplay everything
+ *     ^R
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_redisplay(EditLine *el __attribute__((__unused__)), 
+            Int c __attribute__((__unused__)))
+{
+
+       return CC_REDISPLAY;
+}
+
+
+/* ed_start_over():
+ *     Erase current line and start from scratch
+ *     [^G]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_start_over(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       ch_reset(el, 0);
+       return CC_REFRESH;
+}
+
+
+/* ed_sequence_lead_in():
+ *     First character in a bound sequence
+ *     Placeholder for external keys
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 
+                   Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_prev_history():
+ *     Move to the previous history line
+ *     [^P] [k]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_history(EditLine *el, Int c __attribute__((__unused__)))
+{
+       char beep = 0;
+       int sv_event = el->el_history.eventno;
+
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';           /* just in case */
+
+       if (el->el_history.eventno == 0) {      /* save the current buffer
+                                                * away */
+               (void) Strncpy(el->el_history.buf, el->el_line.buffer,
+                   EL_BUFSIZ);
+               el->el_history.last = el->el_history.buf +
+                   (el->el_line.lastchar - el->el_line.buffer);
+       }
+       el->el_history.eventno += el->el_state.argument;
+
+       if (hist_get(el) == CC_ERROR) {
+               if (el->el_map.type == MAP_VI) {
+                       el->el_history.eventno = sv_event;
+                       
+               }
+               beep = 1;
+               /* el->el_history.eventno was fixed by first call */
+               (void) hist_get(el);
+       }
+       if (beep)
+               return CC_REFRESH_BEEP;
+       return CC_REFRESH;
+}
+
+
+/* ed_next_history():
+ *     Move to the next history line
+ *     [^N] [j]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_history(EditLine *el, Int c __attribute__((__unused__)))
+{
+       el_action_t beep = CC_REFRESH, rval;
+
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
+
+       el->el_history.eventno -= el->el_state.argument;
+
+       if (el->el_history.eventno < 0) {
+               el->el_history.eventno = 0;
+               beep = CC_REFRESH_BEEP;
+       }
+       rval = hist_get(el);
+       if (rval == CC_REFRESH)
+               return beep;
+       return rval;
+
+}
+
+
+/* ed_search_prev_history():
+ *     Search previous in history for a line matching the current
+ *     next search history [M-P] [K]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_search_prev_history(EditLine *el, Int c __attribute__((__unused__)))
+{
+       const Char *hp;
+       int h;
+       bool_t found = 0;
+
+       el->el_chared.c_vcmd.action = NOP;
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
+       if (el->el_history.eventno < 0) {
+#ifdef DEBUG_EDIT
+               (void) fprintf(el->el_errfile,
+                   "e_prev_search_hist(): eventno < 0;\n");
+#endif
+               el->el_history.eventno = 0;
+               return CC_ERROR;
+       }
+       if (el->el_history.eventno == 0) {
+               (void) Strncpy(el->el_history.buf, el->el_line.buffer,
+                   EL_BUFSIZ);
+               el->el_history.last = el->el_history.buf +
+                   (el->el_line.lastchar - el->el_line.buffer);
+       }
+       if (el->el_history.ref == NULL)
+               return CC_ERROR;
+
+       hp = HIST_FIRST(el);
+       if (hp == NULL)
+               return CC_ERROR;
+
+       c_setpat(el);           /* Set search pattern !! */
+
+       for (h = 1; h <= el->el_history.eventno; h++)
+               hp = HIST_NEXT(el);
+
+       while (hp != NULL) {
+#ifdef SDEBUG
+               (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+#endif
+               if ((Strncmp(hp, el->el_line.buffer, (size_t)
+                           (el->el_line.lastchar - el->el_line.buffer)) ||
+                       hp[el->el_line.lastchar - el->el_line.buffer]) &&
+                   c_hmatch(el, hp)) {
+                       found++;
+                       break;
+               }
+               h++;
+               hp = HIST_NEXT(el);
+       }
+
+       if (!found) {
+#ifdef SDEBUG
+               (void) fprintf(el->el_errfile, "not found\n");
+#endif
+               return CC_ERROR;
+       }
+       el->el_history.eventno = h;
+
+       return hist_get(el);
+}
+
+
+/* ed_search_next_history():
+ *     Search next in history for a line matching the current
+ *     [M-N] [J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_search_next_history(EditLine *el, Int c __attribute__((__unused__)))
+{
+       const Char *hp;
+       int h;
+       bool_t found = 0;
+
+       el->el_chared.c_vcmd.action = NOP;
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
+
+       if (el->el_history.eventno == 0)
+               return CC_ERROR;
+
+       if (el->el_history.ref == NULL)
+               return CC_ERROR;
+
+       hp = HIST_FIRST(el);
+       if (hp == NULL)
+               return CC_ERROR;
+
+       c_setpat(el);           /* Set search pattern !! */
+
+       for (h = 1; h < el->el_history.eventno && hp; h++) {
+#ifdef SDEBUG
+               (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+#endif
+               if ((Strncmp(hp, el->el_line.buffer, (size_t)
+                           (el->el_line.lastchar - el->el_line.buffer)) ||
+                       hp[el->el_line.lastchar - el->el_line.buffer]) &&
+                   c_hmatch(el, hp))
+                       found = h;
+               hp = HIST_NEXT(el);
+       }
+
+       if (!found) {           /* is it the current history number? */
+               if (!c_hmatch(el, el->el_history.buf)) {
+#ifdef SDEBUG
+                       (void) fprintf(el->el_errfile, "not found\n");
+#endif
+                       return CC_ERROR;
+               }
+       }
+       el->el_history.eventno = found;
+
+       return hist_get(el);
+}
+
+
+/* ed_prev_line():
+ *     Move up one line
+ *     Could be [k] [^p]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *ptr;
+       int nchars = c_hpos(el);
+
+       /*
+         * Move to the line requested
+         */
+       if (*(ptr = el->el_line.cursor) == '\n')
+               ptr--;
+
+       for (; ptr >= el->el_line.buffer; ptr--)
+               if (*ptr == '\n' && --el->el_state.argument <= 0)
+                       break;
+
+       if (el->el_state.argument > 0)
+               return CC_ERROR;
+
+       /*
+         * Move to the beginning of the line
+         */
+       for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
+               continue;
+
+       /*
+         * Move to the character requested
+         */
+       for (ptr++;
+           nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+           ptr++)
+               continue;
+
+       el->el_line.cursor = ptr;
+       return CC_CURSOR;
+}
+
+
+/* ed_next_line():
+ *     Move down one line
+ *     Could be [j] [^n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *ptr;
+       int nchars = c_hpos(el);
+
+       /*
+         * Move to the line requested
+         */
+       for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
+               if (*ptr == '\n' && --el->el_state.argument <= 0)
+                       break;
+
+       if (el->el_state.argument > 0)
+               return CC_ERROR;
+
+       /*
+         * Move to the character requested
+         */
+       for (ptr++;
+           nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+           ptr++)
+               continue;
+
+       el->el_line.cursor = ptr;
+       return CC_CURSOR;
+}
+
+
+/* ed_command():
+ *     Editline extended command
+ *     [M-X] [:]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_command(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char tmpbuf[EL_BUFSIZ];
+       int tmplen;
+
+       tmplen = c_gets(el, tmpbuf, STR("\n: "));
+       terminal__putc(el, '\n');
+
+       if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
+               terminal_beep(el);
+
+       el->el_map.current = el->el_map.key;
+       re_clear_display(el);
+       return CC_REFRESH;
+}
diff --git a/lib/libedit/complete.c b/lib/libedit/complete.c
deleted file mode 100644 (file)
index cfdff49..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
-**  History and file completion functions for editline library.
-*/
-#include "editline.h"
-
-
-#if    defined(NEED_STRDUP)
-/*
-**  Return an allocated copy of a string.
-*/
-char *
-strdup(p)
-    char       *p;
-{
-    char       *new;
-
-    if ((new = NEW(char, strlen(p) + 1)) != NULL)
-       (void)strcpy(new, p);
-    return new;
-}
-#endif /* defined(NEED_STRDUP) */
-
-/*
-**  strcmp-like sorting predicate for qsort.
-*/
-STATIC int
-compare(p1, p2)
-    CONST void *p1;
-    CONST void *p2;
-{
-    CONST char **v1;
-    CONST char **v2;
-
-    v1 = (CONST char **)p1;
-    v2 = (CONST char **)p2;
-    return strcmp(*v1, *v2);
-}
-
-/*
-**  Fill in *avp with an array of names that match file, up to its length.
-**  Ignore . and .. .
-*/
-STATIC int
-FindMatches(dir, file, avp)
-    char       *dir;
-    char       *file;
-    char       ***avp;
-{
-    char       **av;
-    char       **new;
-    char       *p;
-    DIR                *dp;
-    DIRENTRY   *ep;
-    SIZE_T     ac;
-    SIZE_T     len;
-    SIZE_T     choices;
-    SIZE_T     total;
-#define MAX_TOTAL      (256 << sizeof(char *))
-
-    if ((dp = opendir(dir)) == NULL)
-       return 0;
-
-    av = NULL;
-    ac = 0;
-    len = strlen(file);
-    choices = 0;
-    total = 0;
-    while ((ep = readdir(dp)) != NULL) {
-       p = ep->d_name;
-       if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
-           continue;
-       if (len && strncmp(p, file, len) != 0)
-           continue;
-
-       choices++;
-       if ((total += strlen(p)) > MAX_TOTAL) {
-           /* This is a bit too much. */
-           while (ac > 0) DISPOSE(av[--ac]);
-           continue;
-       }
-
-       if ((ac % MEM_INC) == 0) {
-           if ((new = NEW(char*, ac + MEM_INC)) == NULL) {
-               total = 0;
-               break;
-           }
-           if (ac) {
-               COPYFROMTO(new, av, ac * sizeof (char **));
-               DISPOSE(av);
-           }
-           *avp = av = new;
-       }
-
-       if ((av[ac] = strdup(p)) == NULL) {
-           if (ac == 0)
-               DISPOSE(av);
-           total = 0;
-           break;
-       }
-       ac++;
-    }
-
-    /* Clean up and return. */
-    (void)closedir(dp);
-    if (total > MAX_TOTAL) {
-       char many[sizeof(total) * 3];
-       p = many + sizeof(many);
-       *--p = '\0';
-       while (choices > 0) {
-          *--p = '0' + choices % 10;
-          choices /= 10;
-       }
-       while (p > many + sizeof(many) - 8) *--p = ' ';
-       if ((p = strdup(p)) != NULL) av[ac++] = p;
-       if ((p = strdup("choices")) != NULL) av[ac++] = p;
-    } else {
-       if (ac)
-           qsort(av, ac, sizeof (char **), compare);
-    }
-    return ac;
-}
-
-/*
-**  Split a pathname into allocated directory and trailing filename parts.
-*/
-STATIC int
-SplitPath(path, dirpart, filepart)
-    char       *path;
-    char       **dirpart;
-    char       **filepart;
-{
-    static char        DOT[] = ".";
-    char       *dpart;
-    char       *fpart;
-
-    if ((fpart = strrchr(path, '/')) == NULL) {
-       if ((dpart = strdup(DOT)) == NULL)
-           return -1;
-       if ((fpart = strdup(path)) == NULL) {
-           DISPOSE(dpart);
-           return -1;
-       }
-    }
-    else {
-       if ((dpart = strdup(path)) == NULL)
-           return -1;
-       dpart[fpart - path + 1] = '\0';
-       if ((fpart = strdup(++fpart)) == NULL) {
-           DISPOSE(dpart);
-           return -1;
-       }
-    }
-    *dirpart = dpart;
-    *filepart = fpart;
-    return 0;
-}
-
-/*
-**  Attempt to complete the pathname, returning an allocated copy.
-**  Fill in *unique if we completed it, or set it to 0 if ambiguous.
-*/
-char *
-rl_complete(pathname, unique)
-    char       *pathname;
-    int                *unique;
-{
-    char       **av;
-    char       *dir;
-    char       *file;
-    char       *new;
-    char       *p;
-    SIZE_T     ac;
-    SIZE_T     end;
-    SIZE_T     i;
-    SIZE_T     j;
-    SIZE_T     len;
-
-    if (SplitPath(pathname, &dir, &file) < 0)
-       return NULL;
-    if ((ac = FindMatches(dir, file, &av)) == 0) {
-       DISPOSE(dir);
-       DISPOSE(file);
-       return NULL;
-    }
-
-    p = NULL;
-    len = strlen(file);
-    if (ac == 1) {
-       /* Exactly one match -- finish it off. */
-       *unique = 1;
-       j = strlen(av[0]) - len + 1;
-       if ((p = NEW(char, j + 1)) != NULL) {
-           COPYFROMTO(p, av[0] + len, j);
-           if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
-               (void)strcpy(new, dir);
-               (void)strcat(new, "/");
-               (void)strcat(new, av[0]);
-               rl_add_slash(new, p);
-               DISPOSE(new);
-           }
-       }
-    }
-    else {
-       *unique = 0;
-       if (len) {
-           /* Find largest matching substring. */
-           for (i = len, end = strlen(av[0]); i < end; i++)
-               for (j = 1; j < ac; j++)
-                   if (av[0][i] != av[j][i])
-                       goto breakout;
-  breakout:
-           if (i > len) {
-               j = i - len + 1;
-               if ((p = NEW(char, j)) != NULL) {
-                   COPYFROMTO(p, av[0] + len, j);
-                   p[j - 1] = '\0';
-               }
-           }
-       }
-    }
-
-    /* Clean up and return. */
-    DISPOSE(dir);
-    DISPOSE(file);
-    for (i = 0; i < ac; i++)
-       DISPOSE(av[i]);
-    DISPOSE(av);
-    return p;
-}
-
-/*
-**  Return all possible completions.
-*/
-int
-rl_list_possib(pathname, avp)
-    char       *pathname;
-    char       ***avp;
-{
-    char       *dir;
-    char       *file;
-    int                ac;
-
-    if (SplitPath(pathname, &dir, &file) < 0)
-       return 0;
-    ac = FindMatches(dir, file, avp);
-    DISPOSE(dir);
-    DISPOSE(file);
-    return ac;
-}
-
-/*
- * $PchId: complete.c,v 1.3 1996/02/22 21:18:51 philip Exp $
- */
diff --git a/lib/libedit/config.h b/lib/libedit/config.h
new file mode 100644 (file)
index 0000000..a42cf02
--- /dev/null
@@ -0,0 +1,291 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to 1 if you have the <curses.h> header file. */
+#define HAVE_CURSES_H 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `endpwent' function. */
+#define HAVE_ENDPWENT 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fgetln' function. */
+#define HAVE_FGETLN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have getpwnam_r and getpwuid_r that are draft POSIX.1
+   versions. */
+/* #undef HAVE_GETPW_R_DRAFT */
+
+/* Define to 1 if you have getpwnam_r and getpwuid_r that are POSIX.1
+   compatible. */
+#define HAVE_GETPW_R_POSIX 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `issetugid' function. */
+#define HAVE_ISSETUGID 1
+
+/* Define to 1 if you have the `curses' library (-lcurses). */
+/* #undef HAVE_LIBCURSES */
+
+/* Define to 1 if you have the `ncurses' library (-lncurses). */
+/* #undef HAVE_LIBNCURSES */
+
+/* Define to 1 if you have the `termcap' library (-ltermcap). */
+/* #undef HAVE_LIBTERMCAP */
+
+/* Define to 1 if you have the `terminfo' library (-lterminfo). */
+#define HAVE_LIBTERMINFO 1
+
+/* Define to 1 if you have the `termlib' library (-ltermlib). */
+/* #undef HAVE_LIBTERMLIB */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+/* #undef HAVE_NCURSES_H */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the `regcomp' function. */
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the `re_comp' function. */
+/* #undef HAVE_RE_COMP */
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strcspn' function. */
+#define HAVE_STRCSPN 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+#ifndef __minix
+/* Define to 1 if struct dirent has member d_namlen */
+#define HAVE_STRUCT_DIRENT_D_NAMLEN 1
+#endif
+
+/* Define to 1 if you have the `strunvis' function. */
+#define HAVE_STRUNVIS 1
+
+/* Define to 1 if you have the `strvis' function. */
+#define HAVE_STRVIS 1
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termcap.h> header file. */
+#define HAVE_TERMCAP_H 1
+
+/* Define to 1 if you have the <term.h> header file. */
+#define HAVE_TERM_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if the system has the type `u_int32_t'. */
+#define HAVE_U_INT32_T 1
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vis' function. */
+#define HAVE_VIS 1
+
+/* Define to 1 if you have the `wcsdup' function. */
+#define HAVE_WCSDUP 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "libedit-20110729"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libedit"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libedit 3.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libedit-20110729"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.0"
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Version number of package */
+#define VERSION "3.0"
+
+/* Define to 1 if you want wide-character code */
+/* #undef WIDECHAR */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
+
+
+#include "sys.h"
+/* #undef SCCSID */
+/* #undef LIBC_SCCS */
+/* #undef lint */
+
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
new file mode 100644 (file)
index 0000000..e869161
--- /dev/null
@@ -0,0 +1,891 @@
+.\"    $NetBSD: editline.3,v 1.77 2012/09/11 20:29:58 christos Exp $
+.\"
+.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd September 11, 2012
+.Dt EDITLINE 3
+.Os
+.Sh NAME
+.Nm editline ,
+.Nm el_init ,
+.Nm el_end ,
+.Nm el_reset ,
+.Nm el_gets ,
+.Nm el_wgets ,
+.Nm el_getc ,
+.Nm el_wgetc ,
+.Nm el_push ,
+.Nm el_wpush ,
+.Nm el_parse ,
+.Nm el_wparse ,
+.Nm el_set ,
+.Nm el_wset ,
+.Nm el_get ,
+.Nm el_wget ,
+.Nm el_source ,
+.Nm el_resize ,
+.Nm el_line ,
+.Nm el_wline ,
+.Nm el_insertstr ,
+.Nm el_winsertstr ,
+.Nm el_deletestr ,
+.Nm el_wdeletestr ,
+.Nm history_init ,
+.Nm history_winit ,
+.Nm history_end ,
+.Nm history_wend ,
+.Nm history ,
+.Nm history_w ,
+.Nm tok_init ,
+.Nm tok_winit ,
+.Nm tok_end ,
+.Nm tok_wend ,
+.Nm tok_reset ,
+.Nm tok_wreset ,
+.Nm tok_line ,
+.Nm tok_wline ,
+.Nm tok_str
+.Nm tok_wstr
+.Nd line editor, history and tokenization functions
+.Sh LIBRARY
+.Lb libedit
+.Sh SYNOPSIS
+.In histedit.h
+.Ft EditLine *
+.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr"
+.Ft void
+.Fn el_end "EditLine *e"
+.Ft void
+.Fn el_reset "EditLine *e"
+.Ft const char *
+.Fn el_gets "EditLine *e" "int *count"
+.Ft const wchar_t *
+.Fn el_wgets "EditLine *e" "int *count"
+.Ft int
+.Fn el_getc "EditLine *e" "char *ch"
+.Ft int
+.Fn el_wgetc "EditLine *e" "wchar_t *ch"
+.Ft void
+.Fn el_push "EditLine *e" "const char *str"
+.Ft void
+.Fn el_wpush "EditLine *e" "const wchar_t *str"
+.Ft int
+.Fn el_parse "EditLine *e" "int argc" "const char *argv[]"
+.Ft int
+.Fn el_wparse "EditLine *e" "int argc" "const wchar_t *argv[]"
+.Ft int
+.Fn el_set "EditLine *e" "int op" "..."
+.Ft int
+.Fn el_wset "EditLine *e" "int op" "..."
+.Ft int
+.Fn el_get "EditLine *e" "int op" "..."
+.Ft int
+.Fn el_wget "EditLine *e" "int op" "..."
+.Ft int
+.Fn el_source "EditLine *e" "const char *file"
+.Ft void
+.Fn el_resize "EditLine *e"
+.Ft const LineInfo *
+.Fn el_line "EditLine *e"
+.Ft int
+.Fn el_insertstr "EditLine *e" "const char *str"
+.Ft int
+.Fn el_winsertstr "EditLine *e" "const wchar_t *str"
+.Ft void
+.Fn el_deletestr "EditLine *e" "int count"
+.Ft void
+.Fn el_wdeletestr "EditLine *e" "int count"
+.Ft History *
+.Fn history_init
+.Ft HistoryW *
+.Fn history_winit
+.Ft void
+.Fn history_end "History *h"
+.Ft void
+.Fn history_wend "HistoryW *h"
+.Ft int
+.Fn history "History *h" "HistEvent *ev" "int op" "..."
+.Ft int
+.Fn history_w "HistoryW *h" "HistEventW *ev" "int op" "..."
+.Ft Tokenizer *
+.Fn tok_init "const char *IFS"
+.Ft TokenizerW *
+.Fn tok_winit "const wchar_t *IFS"
+.Ft void
+.Fn tok_end "Tokenizer *t"
+.Ft void
+.Fn tok_wend "TokenizerW *t"
+.Ft void
+.Fn tok_reset "Tokenizer *t"
+.Ft void
+.Fn tok_wreset "TokenizerW *t"
+.Ft int
+.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro"
+.Ft int
+.Fn tok_wline "TokenizerW *t" "const LineInfoW *li" "int *argc" "const wchar_t **argv[]" "int *cursorc" "int *cursoro"
+.Ft int
+.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]"
+.Ft int
+.Fn tok_wstr "TokenizerW *t" "const wchar_t *str" "int *argc" "const wchar_t **argv[]"
+.Sh DESCRIPTION
+The
+.Nm
+library provides generic line editing, history and tokenization functions,
+similar to those found in
+.Xr sh 1 .
+.Pp
+These functions are available in the
+.Nm libedit
+library (which needs the
+.Nm libtermcap
+library).
+Programs should be linked with
+.Fl ledit ltermcap .
+.Sh LINE EDITING FUNCTIONS
+The line editing functions use a common data structure,
+.Fa EditLine ,
+which is created by
+.Fn el_init
+and freed by
+.Fn el_end .
+.Pp
+The wide-character functions behave the same way as their narrow
+counterparts.
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn el_init
+Initialise the line editor, and return a data structure
+to be used by all other line editing functions.
+.Fa prog
+is the name of the invoking program, used when reading the
+.Xr editrc 5
+file to determine which settings to use.
+.Fa fin ,
+.Fa fout
+and
+.Fa ferr
+are the input, output, and error streams (respectively) to use.
+In this documentation, references to
+.Dq the tty
+are actually to this input/output stream combination.
+.It Fn el_end
+Clean up and finish with
+.Fa e ,
+assumed to have been created with
+.Fn el_init .
+.It Fn el_reset
+Reset the tty and the parser.
+This should be called after an error which may have upset the tty's
+state.
+.It Fn el_gets
+Read a line from the tty.
+.Fa count
+is modified to contain the number of characters read.
+Returns the line read if successful, or
+.Dv NULL
+if no characters were read or if an error occurred.
+If an error occurred,
+.Fa count
+is set to \-1 and
+.Dv errno
+contains the error code that caused it.
+The return value may not remain valid across calls to
+.Fn el_gets
+and must be copied if the data is to be retained.
+.It Fn el_getc
+Read a character from the tty.
+.Fa ch
+is modified to contain the character read.
+Returns the number of characters read if successful, \-1 otherwise,
+in which case
+.Dv errno
+can be inspected for the cause.
+.It Fn el_push
+Pushes
+.Fa str
+back onto the input stream.
+This is used by the macro expansion mechanism.
+Refer to the description of
+.Ic bind
+.Fl s
+in
+.Xr editrc 5
+for more information.
+.It Fn el_parse
+Parses the
+.Fa argv
+array (which is
+.Fa argc
+elements in size)
+to execute builtin
+.Nm
+commands.
+If the command is prefixed with
+.Dq prog :
+then
+.Fn el_parse
+will only execute the command if
+.Dq prog
+matches the
+.Fa prog
+argument supplied to
+.Fn el_init .
+The return value is
+\-1 if the command is unknown,
+0 if there was no error or
+.Dq prog
+didn't match, or
+1 if the command returned an error.
+Refer to
+.Xr editrc 5
+for more information.
+.It Fn el_set
+Set
+.Nm
+parameters.
+.Fa op
+determines which parameter to set, and each operation has its
+own parameter list.
+.Pp
+The following values for
+.Fa op
+are supported, along with the required argument list:
+.Bl -tag -width 4n
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
+Define prompt printing function as
+.Fa f ,
+which is to return a string that contains the prompt.
+.It Dv EL_PROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c"
+Same as
+.Dv EL_PROMPT ,
+but the
+.Fa c
+argument indicates the start/stop literal prompt character.
+.Pp
+If a start/stop literal character is found in the prompt, the
+character itself
+is not printed, but characters after it are printed directly to the
+terminal without affecting the state of the current line.
+A subsequent second start/stop literal character ends this behavior.
+This is typically used to embed literal escape sequences that change the
+color/style of the terminal in the prompt.
+.Dv 0
+unsets it.
+.It Dv EL_REFRESH
+Re-display the current line on the next terminal line.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
+Define right side prompt printing function as
+.Fa f ,
+which is to return a string that contains the prompt.
+.It Dv EL_RPROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c"
+Define the right prompt printing function but with a literal escape character.
+.It Dv EL_TERMINAL , Fa "const char *type"
+Define terminal type of the tty to be
+.Fa type ,
+or to
+.Ev TERM
+if
+.Fa type
+is
+.Dv NULL .
+.It Dv EL_EDITOR , Fa "const char *mode"
+Set editing mode to
+.Fa mode ,
+which must be one of
+.Dq emacs
+or
+.Dq vi .
+.It Dv EL_SIGNAL , Fa "int flag"
+If
+.Fa flag
+is non-zero,
+.Nm
+will install its own signal handler for the following signals when
+reading command input:
+.Dv SIGCONT ,
+.Dv SIGHUP ,
+.Dv SIGINT ,
+.Dv SIGQUIT ,
+.Dv SIGSTOP ,
+.Dv SIGTERM ,
+.Dv SIGTSTP ,
+and
+.Dv SIGWINCH .
+Otherwise, the current signal handlers will be used.
+.It Dv EL_BIND , Fa "const char *" , Fa "..." , Dv NULL
+Perform the
+.Ic bind
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_ECHOTC , Fa "const char *" , Fa "..." , Dv NULL
+Perform the
+.Ic echotc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_SETTC , Fa "const char *" , Fa "..." , Dv NULL
+Perform the
+.Ic settc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_SETTY , Fa "const char *" , Fa "..." , Dv NULL
+Perform the
+.Ic setty
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_TELLTC , Fa "const char *" , Fa "..." , Dv NULL
+Perform the
+.Ic telltc
+builtin command.
+Refer to
+.Xr editrc 5
+for more information.
+.It Dv EL_ADDFN , Fa "const char *name" , Fa "const char *help" , \
+Fa "unsigned char (*func)(EditLine *e, int ch)"
+Add a user defined function,
+.Fn func ,
+referred to as
+.Fa name
+which is invoked when a key which is bound to
+.Fa name
+is entered.
+.Fa help
+is a description of
+.Fa name .
+At invocation time,
+.Fa ch
+is the key which caused the invocation.
+The return value of
+.Fn func
+should be one of:
+.Bl -tag -width "CC_REDISPLAY"
+.It Dv CC_NORM
+Add a normal character.
+.It Dv CC_NEWLINE
+End of line was entered.
+.It Dv CC_EOF
+EOF was entered.
+.It Dv CC_ARGHACK
+Expecting further command input as arguments, do nothing visually.
+.It Dv CC_REFRESH
+Refresh display.
+.It Dv CC_REFRESH_BEEP
+Refresh display, and beep.
+.It Dv CC_CURSOR
+Cursor moved, so update and perform
+.Dv CC_REFRESH .
+.It Dv CC_REDISPLAY
+Redisplay entire input line.
+This is useful if a key binding outputs extra information.
+.It Dv CC_ERROR
+An error occurred.
+Beep, and flush tty.
+.It Dv CC_FATAL
+Fatal error, reset tty to known state.
+.El
+.It Dv EL_HIST , Fa "History *(*func)(History *, int op, ...)" , \
+Fa "const char *ptr"
+Defines which history function to use, which is usually
+.Fn history .
+.Fa ptr
+should be the value returned by
+.Fn history_init .
+.It Dv EL_EDITMODE , Fa "int flag"
+If
+.Fa flag
+is non-zero,
+editing is enabled (the default).
+Note that this is only an indication, and does not
+affect the operation of
+.Nm .
+At this time, it is the caller's responsibility to
+check this
+(using
+.Fn el_get )
+to determine if editing should be enabled or not.
+.It Dv EL_UNBUFFERED , Fa "int flag"
+If
+.Fa flag
+is zero,
+unbuffered mode is disabled (the default).
+In unbuffered mode,
+.Fn el_gets
+will return immediately after processing a single character.
+.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)"
+Define the character reading function as
+.Fa f ,
+which is to return the number of characters read and store them in
+.Fa c .
+This function is called internally by
+.Fn el_gets
+and
+.Fn el_getc .
+The builtin function can be set or restored with the special function
+name
+.Dq Dv EL_BUILTIN_GETCFN .
+.It Dv EL_CLIENTDATA , Fa "void *data"
+Register
+.Fa data
+to be associated with this EditLine structure.
+It can be retrieved with the corresponding
+.Fn el_get
+call.
+.It Dv EL_SETFP , Fa "int fd" , Fa "FILE *fp"
+Set the current
+.Nm editline
+file pointer for
+.Dq input
+.Fa fd
+=
+.Dv 0 ,
+.Dq output
+.Fa fd
+=
+.Dv 1 ,
+or
+.Dq error
+.Fa fd
+=
+.Dv 2
+from
+.Fa fp .
+.El
+.It Fn el_get
+Get
+.Nm
+parameters.
+.Fa op
+determines which parameter to retrieve into
+.Fa result .
+Returns 0 if successful, \-1 otherwise.
+.Pp
+The following values for
+.Fa op
+are supported, along with actual type of
+.Fa result :
+.Bl -tag -width 4n
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c"
+Return a pointer to the function that displays the prompt in
+.Fa f .
+If
+.Fa c
+is not
+.Dv NULL ,
+return the start/stop literal prompt character in it.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c"
+Return a pointer to the function that displays the prompt in
+.Fa f .
+If
+.Fa c
+is not
+.Dv NULL ,
+return the start/stop literal prompt character in it.
+.It Dv EL_EDITOR , Fa "const char **"
+Return the name of the editor, which will be one of
+.Dq emacs
+or
+.Dq vi .
+.It Dv EL_GETTC , Fa "const char *name" , Fa "void *value"
+Return non-zero if
+.Fa name
+is a valid
+.Xr termcap 5
+capability
+and set
+.Fa value
+to the current value of that capability.
+.It Dv EL_SIGNAL , Fa "int *"
+Return non-zero if
+.Nm
+has installed private signal handlers (see
+.Fn el_get
+above).
+.It Dv EL_EDITMODE , Fa "int *"
+Return non-zero if editing is enabled.
+.It Dv EL_GETCFN , Fa "int (**f)(EditLine *, char *)"
+Return a pointer to the function that read characters, which is equal to
+.Dq Dv EL_BUILTIN_GETCFN
+in the case of the default builtin function.
+.It Dv EL_CLIENTDATA , Fa "void **data"
+Retrieve
+.Fa data
+previously registered with the corresponding
+.Fn el_set
+call.
+.It Dv EL_UNBUFFERED , Fa "int"
+Return non-zero if unbuffered mode is enabled.
+.It Dv EL_PREP_TERM , Fa "int"
+Sets or clears terminal editing mode.
+.It Dv EL_GETFP , Fa "int fd", Fa "FILE **fp"
+Return in
+.Fa fp
+the current
+.Nm editline
+file pointer for
+.Dq input
+.Fa fd
+=
+.Dv 0 ,
+.Dq output
+.Fa fd
+=
+.Dv 1 ,
+or
+.Dq error
+.Fa fd
+=
+.Dv 2 .
+.El
+.It Fn el_source
+Initialise
+.Nm
+by reading the contents of
+.Fa file .
+.Fn el_parse
+is called for each line in
+.Fa file .
+If
+.Fa file
+is
+.Dv NULL ,
+try
+.Pa $PWD/.editrc
+then
+.Pa $HOME/.editrc .
+Refer to
+.Xr editrc 5
+for details on the format of
+.Fa file .
+.It Fn el_resize
+Must be called if the terminal size changes.
+If
+.Dv EL_SIGNAL
+has been set with
+.Fn el_set ,
+then this is done automatically.
+Otherwise, it's the responsibility of the application to call
+.Fn el_resize
+on the appropriate occasions.
+.It Fn el_line
+Return the editing information for the current line in a
+.Fa LineInfo
+structure, which is defined as follows:
+.Bd -literal
+typedef struct lineinfo {
+    const char *buffer;    /* address of buffer */
+    const char *cursor;    /* address of cursor */
+    const char *lastchar;  /* address of last character */
+} LineInfo;
+.Ed
+.Pp
+.Fa buffer
+is not NUL terminated.
+This function may be called after
+.Fn el_gets
+to obtain the
+.Fa LineInfo
+structure pertaining to line returned by that function,
+and from within user defined functions added with
+.Dv EL_ADDFN .
+.It Fn el_insertstr
+Insert
+.Fa str
+into the line at the cursor.
+Returns \-1 if
+.Fa str
+is empty or won't fit, and 0 otherwise.
+.It Fn el_deletestr
+Delete
+.Fa count
+characters before the cursor.
+.El
+.Sh HISTORY LIST FUNCTIONS
+The history functions use a common data structure,
+.Fa History ,
+which is created by
+.Fn history_init
+and freed by
+.Fn history_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn history_init
+Initialise the history list, and return a data structure
+to be used by all other history list functions.
+.It Fn history_end
+Clean up and finish with
+.Fa h ,
+assumed to have been created with
+.Fn history_init .
+.It Fn history
+Perform operation
+.Fa op
+on the history list, with optional arguments as needed by the
+operation.
+.Fa ev
+is changed accordingly to operation.
+The following values for
+.Fa op
+are supported, along with the required argument list:
+.Bl -tag -width 4n
+.It Dv H_SETSIZE , Fa "int size"
+Set size of history to
+.Fa size
+elements.
+.It Dv H_GETSIZE
+Get number of events currently in history.
+.It Dv H_END
+Cleans up and finishes with
+.Fa h ,
+assumed to be created with
+.Fn history_init .
+.It Dv H_CLEAR
+Clear the history.
+.It Dv H_FUNC , Fa "void *ptr" , Fa "history_gfun_t first" , \
+Fa "history_gfun_t next" , Fa "history_gfun_t last" , \
+Fa "history_gfun_t prev" , Fa "history_gfun_t curr" , \
+Fa "history_sfun_t set" , Fa "history_vfun_t clear" , \
+Fa "history_efun_t enter" , Fa "history_efun_t add"
+Define functions to perform various history operations.
+.Fa ptr
+is the argument given to a function when it's invoked.
+.It Dv H_FIRST
+Return the first element in the history.
+.It Dv H_LAST
+Return the last element in the history.
+.It Dv H_PREV
+Return the previous element in the history.
+.It Dv H_NEXT
+Return the next element in the history.
+.It Dv H_CURR
+Return the current element in the history.
+.It Dv H_SET
+Set the cursor to point to the requested element.
+.It Dv H_ADD , Fa "const char *str"
+Append
+.Fa str
+to the current element of the history, or perform the
+.Dv H_ENTER
+operation with argument
+.Fa str
+if there is no current element.
+.It Dv H_APPEND , Fa "const char *str"
+Append
+.Fa str
+to the last new element of the history.
+.It Dv H_ENTER , Fa "const char *str"
+Add
+.Fa str
+as a new element to the history, and, if necessary,
+removing the oldest entry to keep the list to the created size.
+If
+.Dv H_SETUNIQUE
+was has been called with a non-zero arguments, the element
+will not be entered into the history if its contents match
+the ones of the current history element.
+If the element is entered
+.Fn history
+returns 1, if it is ignored as a duplicate returns 0.
+Finally
+.Fn history
+returns \-1 if an error occurred.
+.It Dv H_PREV_STR , Fa "const char *str"
+Return the closest previous event that starts with
+.Fa str .
+.It Dv H_NEXT_STR , Fa "const char *str"
+Return the closest next event that starts with
+.Fa str .
+.It Dv H_PREV_EVENT , Fa "int e"
+Return the previous event numbered
+.Fa e .
+.It Dv H_NEXT_EVENT , Fa "int e"
+Return the next event numbered
+.Fa e .
+.It Dv H_LOAD , Fa "const char *file"
+Load the history list stored in
+.Fa file .
+.It Dv H_SAVE , Fa "const char *file"
+Save the history list to
+.Fa file .
+.It Dv H_SETUNIQUE , Fa "int unique"
+Set flag that adjacent identical event strings should not be entered
+into the history.
+.It Dv H_GETUNIQUE
+Retrieve the current setting if adjacent identical elements should
+be entered into the history.
+.It Dv H_DEL , Fa "int e"
+Delete the event numbered
+.Fa e .
+This function is only provided for
+.Xr readline 3
+compatibility.
+The caller is responsible for free'ing the string in the returned
+.Fa HistEvent .
+.El
+.Pp
+.Fn history
+returns \*[Gt]= 0 if the operation
+.Fa op
+succeeds.
+Otherwise, \-1 is returned and
+.Fa ev
+is updated to contain more details about the error.
+.El
+.Sh TOKENIZATION FUNCTIONS
+The tokenization functions use a common data structure,
+.Fa Tokenizer ,
+which is created by
+.Fn tok_init
+and freed by
+.Fn tok_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn tok_init
+Initialise the tokenizer, and return a data structure
+to be used by all other tokenizer functions.
+.Fa IFS
+contains the Input Field Separators, which defaults to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline
+if
+.Dv NULL .
+.It Fn tok_end
+Clean up and finish with
+.Fa t ,
+assumed to have been created with
+.Fn tok_init .
+.It Fn tok_reset
+Reset the tokenizer state.
+Use after a line has been successfully tokenized
+by
+.Fn tok_line
+or
+.Fn tok_str
+and before a new line is to be tokenized.
+.It Fn tok_line
+Tokenize
+.Fa li ,
+If successful, modify:
+.Fa argv
+to contain the words,
+.Fa argc
+to contain the number of words,
+.Fa cursorc
+(if not
+.Dv NULL )
+to contain the index of the word containing the cursor,
+and
+.Fa cursoro
+(if not
+.Dv NULL )
+to contain the offset within
+.Fa argv[cursorc]
+of the cursor.
+.Pp
+Returns
+0 if successful,
+\-1 for an internal error,
+1 for an unmatched single quote,
+2 for an unmatched double quote,
+and
+3 for a backslash quoted
+.Aq newline .
+A positive exit code indicates that another line should be read
+and tokenization attempted again.
+.
+.It Fn tok_str
+A simpler form of
+.Fn tok_line ;
+.Fa str
+is a NUL terminated string to tokenize.
+.El
+.
+.\"XXX.Sh EXAMPLES
+.\"XXX: provide some examples
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr signal 3 ,
+.Xr termcap 3 ,
+.Xr editrc 5 ,
+.Xr termcap 5
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Bx 4.4 .
+.Dv CC_REDISPLAY
+appeared in
+.Nx 1.3 .
+.Dv CC_REFRESH_BEEP ,
+.Dv EL_EDITMODE
+and the readline emulation appeared in
+.Nx 1.4 .
+.Dv EL_RPROMPT
+appeared in
+.Nx 1.5 .
+.Sh AUTHORS
+The
+.Nm
+library was written by Christos Zoulas.
+Luke Mewburn wrote this manual and implemented
+.Dv CC_REDISPLAY ,
+.Dv CC_REFRESH_BEEP ,
+.Dv EL_EDITMODE ,
+and
+.Dv EL_RPROMPT .
+Jaromir Dolecek implemented the readline emulation.
+Johny Mattsson implemented wide-character support.
+.Sh BUGS
+At this time, it is the responsibility of the caller to
+check the result of the
+.Dv EL_EDITMODE
+operation of
+.Fn el_get
+(after an
+.Fn el_source
+or
+.Fn el_parse )
+to determine if
+.Nm
+should be used for further input.
+I.e.,
+.Dv EL_EDITMODE
+is purely an indication of the result of the most recent
+.Xr editrc 5
+.Ic edit
+command.
diff --git a/lib/libedit/editline.c b/lib/libedit/editline.c
deleted file mode 100644 (file)
index feda30b..0000000
+++ /dev/null
@@ -1,1469 +0,0 @@
-/*
-**  Main editing routines for editline library.
-*/
-#include "editline.h"
-#include <signal.h>
-#include <errno.h>
-#include <ctype.h>
-#include <termcap.h>
-#include <unistd.h>
-
-/*
-**  Manifest constants.
-*/
-#define SCREEN_WIDTH   80
-#define SCREEN_ROWS    24
-#define NO_ARG         (-1)
-#define DEL            127
-#define CTL(x)         ((x) & 0x1F)
-#define ISCTL(x)       ((x) && (x) < ' ')
-#define UNCTL(x)       ((x) + 64)
-#define META(x)                ((x) | 0x80)
-#define ISMETA(x)      ((x) & 0x80)
-#define UNMETA(x)      ((x) & 0x7F)
-#if    !defined(HIST_SIZE)
-#define HIST_SIZE      20
-#endif /* !defined(HIST_SIZE) */
-
-/*
-**  Command status codes.
-*/
-typedef enum _STATUS {
-    CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
-} STATUS;
-
-/*
-**  The type of case-changing to perform.
-*/
-typedef enum _CASE {
-    TOupper, TOlower
-} CASE;
-
-/*
-**  Key to command mapping.
-*/
-typedef struct _KEYMAP {
-    CHAR       Key;
-    STATUS     (*Function)();
-} KEYMAP;
-
-/*
-**  Command history structure.
-*/
-typedef struct _HISTORY {
-    int                Size;
-    int                Pos;
-    CHAR       *Lines[HIST_SIZE];
-} HISTORY;
-
-/*
-**  Globals.
-*/
-int            rl_eof;
-int            rl_erase;
-int            rl_intr;
-int            rl_kill;
-int            rl_quit;
-
-STATIC CHAR            NIL[] = "";
-STATIC CONST CHAR      *Input = NIL;
-STATIC CHAR            *Line;
-STATIC CONST char      *Prompt;
-STATIC CHAR            *Yanked;
-STATIC char            *Screen;
-STATIC char            NEWLINE[]= CRLF;
-STATIC HISTORY         H;
-STATIC int             Repeat;
-STATIC int             End;
-STATIC int             Mark;
-STATIC int             OldPoint;
-STATIC int             Point;
-STATIC int             PushBack;
-STATIC int             Pushed;
-STATIC int             Signal;
-static KEYMAP          Map[33];
-static KEYMAP          MetaMap[17];
-STATIC SIZE_T          Length;
-STATIC SIZE_T          ScreenCount;
-STATIC SIZE_T          ScreenSize;
-STATIC char            *backspace;
-STATIC int             TTYwidth;
-STATIC int             TTYrows;
-
-/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
-int            rl_meta_chars = 0;
-
-/*
-**  Declarations.
-*/
-STATIC CHAR    *editinput();
-#if    defined(USE_TERMCAP)
-extern char    *tgetstr();
-extern int     tgetent();
-#endif /* defined(USE_TERMCAP) */
-\f
-/*
-**  TTY input/output functions.
-*/
-
-STATIC void
-TTYflush()
-{
-    if (ScreenCount) {
-       (void)write(1, Screen, ScreenCount);
-       ScreenCount = 0;
-    }
-}
-
-STATIC void
-TTYput(c)
-    CHAR       c;
-{
-    Screen[ScreenCount] = c;
-    if (++ScreenCount >= ScreenSize - 1) {
-       ScreenSize += SCREEN_INC;
-       RENEW(Screen, char, ScreenSize);
-    }
-}
-
-STATIC void
-TTYputs(p)
-    CHAR       *p;
-{
-    while (*p)
-       TTYput(*p++);
-}
-
-STATIC void
-TTYshow(c)
-    CHAR       c;
-{
-    if (c == DEL) {
-       TTYput('^');
-       TTYput('?');
-    }
-    else if (ISCTL(c)) {
-       TTYput('^');
-       TTYput(UNCTL(c));
-    }
-    else if (rl_meta_chars && ISMETA(c)) {
-       TTYput('M');
-       TTYput('-');
-       TTYput(UNMETA(c));
-    }
-    else
-       TTYput(c);
-}
-
-STATIC void
-TTYstring(p)
-    CHAR       *p;
-{
-    while (*p)
-       TTYshow(*p++);
-}
-
-STATIC unsigned int
-TTYget()
-{
-    CHAR       c;
-    int r;
-
-    TTYflush();
-    if (Pushed) {
-       Pushed = 0;
-       return PushBack;
-    }
-    if (*Input)
-       return *Input++;
-    do
-    {
-       r= read(0, &c, (SIZE_T)1);
-    } while (r == -1 && errno == EINTR);
-    return r  == 1 ? c : EOF;
-}
-
-#define TTYback()      (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
-
-STATIC void
-TTYbackn(n)
-    int                n;
-{
-    while (--n >= 0)
-       TTYback();
-}
-
-STATIC void
-TTYinfo()
-{
-    static int         init;
-#if    defined(USE_TERMCAP)
-    char               *term;
-    char               buff[2048];
-    char               *bp;
-#endif /* defined(USE_TERMCAP) */
-#if    defined(TIOCGWINSZ)
-    struct winsize     W;
-#endif /* defined(TIOCGWINSZ) */
-
-    if (init) {
-#if    defined(TIOCGWINSZ)
-       /* Perhaps we got resized. */
-       if (ioctl(0, TIOCGWINSZ, &W) >= 0
-        && W.ws_col > 0 && W.ws_row > 0) {
-           TTYwidth = (int)W.ws_col;
-           TTYrows = (int)W.ws_row;
-       }
-#endif /* defined(TIOCGWINSZ) */
-       return;
-    }
-    init++;
-
-    TTYwidth = TTYrows = 0;
-#if    defined(USE_TERMCAP)
-    bp = &buff[0];
-    if ((term = getenv("TERM")) == NULL)
-       term = "dumb";
-    if (tgetent(buff, term) < 0) {
-       TTYwidth = SCREEN_WIDTH;
-       TTYrows = SCREEN_ROWS;
-       return;
-    }
-    if ((backspace = tgetstr("le", &bp)) != NULL)
-       backspace = strdup(backspace);
-    TTYwidth = tgetnum("co");
-    TTYrows = tgetnum("li");
-#endif /* defined(USE_TERMCAP) */
-
-#if    defined(TIOCGWINSZ)
-    if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
-       TTYwidth = (int)W.ws_col;
-       TTYrows = (int)W.ws_row;
-    }
-#endif /* defined(TIOCGWINSZ) */
-
-    if (TTYwidth <= 0 || TTYrows <= 0) {
-       TTYwidth = SCREEN_WIDTH;
-       TTYrows = SCREEN_ROWS;
-    }
-}
-\f
-
-/*
-**  Print an array of words in columns.
-*/
-STATIC void
-columns(ac, av)
-    int                ac;
-    CHAR       **av;
-{
-    CHAR       *p;
-    int                i;
-    int                j;
-    int                k;
-    int                len;
-    int                skip;
-    int                longest;
-    int                cols;
-
-    /* Find longest name, determine column count from that. */
-    for (longest = 0, i = 0; i < ac; i++)
-       if ((j = strlen((char *)av[i])) > longest)
-           longest = j;
-    cols = TTYwidth / (longest + 3);
-
-    TTYputs((CHAR *)NEWLINE);
-    for (skip = ac / cols + 1, i = 0; i < skip; i++) {
-       for (j = i; j < ac; j += skip) {
-           for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
-               TTYput(*p);
-           if (j + skip < ac)
-               while (++len < longest + 3)
-                   TTYput(' ');
-       }
-       TTYputs((CHAR *)NEWLINE);
-    }
-}
-
-STATIC void
-reposition()
-{
-    int                i;
-    CHAR       *p;
-
-    TTYput('\r');
-    TTYputs((CHAR *)Prompt);
-    for (i = Point, p = Line; --i >= 0; p++)
-       TTYshow(*p);
-}
-
-STATIC void
-left(Change)
-    STATUS     Change;
-{
-    TTYback();
-    if (Point) {
-       if (ISCTL(Line[Point - 1]))
-           TTYback();
-        else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
-           TTYback();
-           TTYback();
-       }
-    }
-    if (Change == CSmove)
-       Point--;
-}
-
-STATIC void
-right(Change)
-    STATUS     Change;
-{
-    TTYshow(Line[Point]);
-    if (Change == CSmove)
-       Point++;
-}
-
-STATIC STATUS
-ring_bell()
-{
-    TTYput('\07');
-    TTYflush();
-    return CSstay;
-}
-
-STATIC STATUS
-do_macro(c)
-    unsigned int       c;
-{
-    CHAR               name[4];
-
-    name[0] = '_';
-    name[1] = c;
-    name[2] = '_';
-    name[3] = '\0';
-
-    if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
-       Input = NIL;
-       return ring_bell();
-    }
-    return CSstay;
-}
-
-STATIC STATUS
-do_forward(move)
-    STATUS     move;
-{
-    int                i;
-    CHAR       *p;
-
-    i = 0;
-    do {
-       p = &Line[Point];
-       for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
-           if (move == CSmove)
-               right(CSstay);
-
-       for (; Point < End && isalnum(*p); Point++, p++)
-           if (move == CSmove)
-               right(CSstay);
-
-       if (Point == End)
-           break;
-    } while (++i < Repeat);
-
-    return CSstay;
-}
-
-STATIC STATUS
-do_case(type)
-    CASE       type;
-{
-    int                i;
-    int                end;
-    int                count;
-    CHAR       *p;
-
-    (void)do_forward(CSstay);
-    if (OldPoint != Point) {
-       if ((count = Point - OldPoint) < 0)
-           count = -count;
-       Point = OldPoint;
-       if ((end = Point + count) > End)
-           end = End;
-       for (i = Point, p = &Line[i]; i < end; i++, p++) {
-           if (type == TOupper) {
-               if (islower(*p))
-                   *p = toupper(*p);
-           }
-           else if (isupper(*p))
-               *p = tolower(*p);
-           right(CSmove);
-       }
-    }
-    return CSstay;
-}
-
-STATIC STATUS
-case_down_word()
-{
-    return do_case(TOlower);
-}
-
-STATIC STATUS
-case_up_word()
-{
-    return do_case(TOupper);
-}
-
-STATIC void
-ceol()
-{
-    int                extras;
-    int                i;
-    CHAR       *p;
-
-    for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
-       TTYput(' ');
-       if (ISCTL(*p)) {
-           TTYput(' ');
-           extras++;
-       }
-       else if (rl_meta_chars && ISMETA(*p)) {
-           TTYput(' ');
-           TTYput(' ');
-           extras += 2;
-       }
-    }
-
-    for (i += extras; i > Point; i--)
-       TTYback();
-}
-
-STATIC void
-clear_line()
-{
-    Point = -strlen(Prompt);
-    TTYput('\r');
-    ceol();
-    Point = 0;
-    End = 0;
-    Line[0] = '\0';
-}
-
-STATIC STATUS
-insert_string(p)
-    CHAR       *p;
-{
-    SIZE_T     len;
-    int                i;
-    CHAR       *new;
-    CHAR       *q;
-
-    len = strlen((char *)p);
-    if (End + len >= Length) {
-       if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
-           return CSstay;
-       if (Length) {
-           COPYFROMTO(new, Line, Length);
-           DISPOSE(Line);
-       }
-       Line = new;
-       Length += len + MEM_INC;
-    }
-
-    for (q = &Line[Point], i = End - Point; --i >= 0; )
-       q[len + i] = q[i];
-    COPYFROMTO(&Line[Point], p, len);
-    End += len;
-    Line[End] = '\0';
-    TTYstring(&Line[Point]);
-    Point += len;
-
-    return Point == End ? CSstay : CSmove;
-}
-
-STATIC STATUS
-redisplay()
-{
-    TTYputs((CHAR *) NEWLINE);
-    TTYputs((CHAR *)Prompt);
-    TTYstring(Line);
-    return CSmove;
-}
-
-STATIC STATUS
-toggle_meta_mode()
-{
-    rl_meta_chars = ! rl_meta_chars;
-    return redisplay();
-}
-\f
-
-STATIC CHAR *
-next_hist()
-{
-    return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
-}
-
-STATIC CHAR *
-prev_hist()
-{
-    return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
-}
-
-STATIC STATUS
-do_insert_hist(p)
-    CHAR       *p;
-{
-    if (p == NULL)
-       return ring_bell();
-    Point = 0;
-    reposition();
-    ceol();
-    End = 0;
-    return insert_string(p);
-}
-
-STATIC STATUS
-do_hist(move)
-    CHAR       *(*move)();
-{
-    CHAR       *p;
-    int                i;
-
-    i = 0;
-    do {
-       if ((p = (*move)()) == NULL)
-           return ring_bell();
-    } while (++i < Repeat);
-    return do_insert_hist(p);
-}
-
-STATIC STATUS
-h_next()
-{
-    return do_hist(next_hist);
-}
-
-STATIC STATUS
-h_prev()
-{
-    return do_hist(prev_hist);
-}
-
-STATIC STATUS
-h_first()
-{
-    return do_insert_hist(H.Lines[H.Pos = 0]);
-}
-
-STATIC STATUS
-h_last()
-{
-    return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
-}
-
-/*
-**  Return zero if pat appears as a substring in text.
-*/
-STATIC int
-substrcmp(text, pat, len)
-    char       *text;
-    char       *pat;
-    int                len;
-{
-    char       c;
-
-    if ((c = *pat) == '\0')
-        return *text == '\0';
-    for ( ; *text; text++)
-        if (*text == c && strncmp(text, pat, len) == 0)
-            return 0;
-    return 1;
-}
-
-STATIC CHAR *
-search_hist(search, move)
-    CHAR       *search;
-    CHAR       *(*move)();
-{
-    static CHAR        *old_search;
-    int                len;
-    int                pos;
-    int                (*match)();
-    char       *pat;
-
-    /* Save or get remembered search pattern. */
-    if (search && *search) {
-       if (old_search)
-           DISPOSE(old_search);
-       old_search = (CHAR *)strdup((char *)search);
-    }
-    else {
-       if (old_search == NULL || *old_search == '\0')
-            return NULL;
-       search = old_search;
-    }
-
-    /* Set up pattern-finder. */
-    if (*search == '^') {
-       match = strncmp;
-       pat = (char *)(search + 1);
-    }
-    else {
-       match = substrcmp;
-       pat = (char *)search;
-    }
-    len = strlen(pat);
-
-    for (pos = H.Pos; (*move)() != NULL; )
-       if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
-            return H.Lines[H.Pos];
-    H.Pos = pos;
-    return NULL;
-}
-
-STATIC STATUS
-h_search()
-{
-    static int Searching;
-    CONST char *old_prompt;
-    CHAR       *(*move)();
-    CHAR       *p;
-
-    if (Searching)
-       return ring_bell();
-    Searching = 1;
-
-    clear_line();
-    old_prompt = Prompt;
-    Prompt = "Search: ";
-    TTYputs((CHAR *)Prompt);
-    move = Repeat == NO_ARG ? prev_hist : next_hist;
-    p = editinput();
-    Prompt = old_prompt;
-    Searching = 0;
-    TTYputs((CHAR *)Prompt);
-    if (p == NULL && Signal > 0) {
-       Signal = 0;
-       clear_line();
-       return redisplay();
-    }
-    p = search_hist(p, move);
-    clear_line();
-    if (p == NULL) {
-       (void)ring_bell();
-       return redisplay();
-    }
-    return do_insert_hist(p);
-}
-
-STATIC STATUS
-fd_char()
-{
-    int                i;
-
-    i = 0;
-    do {
-       if (Point >= End)
-           break;
-       right(CSmove);
-    } while (++i < Repeat);
-    return CSstay;
-}
-
-STATIC void
-save_yank(begin, i)
-    int                begin;
-    int                i;
-{
-    if (Yanked) {
-       DISPOSE(Yanked);
-       Yanked = NULL;
-    }
-
-    if (i < 1)
-       return;
-
-    if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
-       COPYFROMTO(Yanked, &Line[begin], i);
-       Yanked[i] = '\0';
-    }
-}
-
-STATIC STATUS
-delete_string(count)
-    int                count;
-{
-    int                i;
-    CHAR       *p;
-
-    if (count <= 0 || End == Point)
-       return ring_bell();
-
-    if (count == 1 && Point == End - 1) {
-       /* Optimize common case of delete at end of line. */
-       End--;
-       p = &Line[Point];
-       i = 1;
-       TTYput(' ');
-       if (ISCTL(*p)) {
-           i = 2;
-           TTYput(' ');
-       }
-       else if (rl_meta_chars && ISMETA(*p)) {
-           i = 3;
-           TTYput(' ');
-           TTYput(' ');
-       }
-       TTYbackn(i);
-       *p = '\0';
-       return CSmove;
-    }
-    if (Point + count > End && (count = End - Point) <= 0)
-       return CSstay;
-
-    if (count > 1)
-       save_yank(Point, count);
-
-    for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
-       p[0] = p[count];
-    ceol();
-    End -= count;
-    TTYstring(&Line[Point]);
-    return CSmove;
-}
-
-STATIC STATUS
-bk_char()
-{
-    int                i;
-
-    i = 0;
-    do {
-       if (Point == 0)
-           break;
-       left(CSmove);
-    } while (++i < Repeat);
-
-    return CSstay;
-}
-
-STATIC STATUS
-bk_del_char()
-{
-    int                i;
-
-    i = 0;
-    do {
-       if (Point == 0)
-           break;
-       left(CSmove);
-    } while (++i < Repeat);
-
-    return delete_string(i);
-}
-
-STATIC STATUS
-kill_line()
-{
-    int                i;
-
-    if (Repeat != NO_ARG) {
-       if (Repeat < Point) {
-           i = Point;
-           Point = Repeat;
-           reposition();
-           (void)delete_string(i - Point);
-       }
-       else if (Repeat > Point) {
-           right(CSmove);
-           (void)delete_string(Repeat - Point - 1);
-       }
-       return CSmove;
-    }
-
-    save_yank(Point, End - Point);
-    Line[Point] = '\0';
-    ceol();
-    End = Point;
-    return CSstay;
-}
-
-STATIC STATUS
-insert_char(c)
-    int                c;
-{
-    STATUS     s;
-    CHAR       buff[2];
-    CHAR       *p;
-    CHAR       *q;
-    int                i;
-
-    if (Repeat == NO_ARG || Repeat < 2) {
-       buff[0] = c;
-       buff[1] = '\0';
-       return insert_string(buff);
-    }
-
-    if ((p = NEW(CHAR, Repeat + 1)) == NULL)
-       return CSstay;
-    for (i = Repeat, q = p; --i >= 0; )
-       *q++ = c;
-    *q = '\0';
-    Repeat = 0;
-    s = insert_string(p);
-    DISPOSE(p);
-    return s;
-}
-
-STATIC STATUS
-meta()
-{
-    unsigned int       c;
-    KEYMAP             *kp;
-
-    if ((c = TTYget()) == EOF)
-       return CSeof;
-#if    defined(ANSI_ARROWS)
-    /* Also include VT-100 arrows. */
-    if (c == '[' || c == 'O')
-       switch (c = TTYget()) {
-       default:        return ring_bell();
-       case EOF:       return CSeof;
-       case 'A':       return h_prev();
-       case 'B':       return h_next();
-       case 'C':       return fd_char();
-       case 'D':       return bk_char();
-       }
-#endif /* defined(ANSI_ARROWS) */
-
-    if (isdigit(c)) {
-       for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
-           Repeat = Repeat * 10 + c - '0';
-       Pushed = 1;
-       PushBack = c;
-       return CSstay;
-    }
-
-    if (isupper(c))
-       return do_macro(c);
-    for (kp = MetaMap; kp->Function; kp++)
-       if (kp->Key == c)
-           return (*kp->Function)();
-
-    return ring_bell();
-}
-
-STATIC STATUS
-emacs(c)
-    unsigned int       c;
-{
-    STATUS             s;
-    KEYMAP             *kp;
-
-    OldPoint = Point;
-    if (rl_meta_chars && ISMETA(c)) {
-       Pushed = 1;
-       PushBack = UNMETA(c);
-       return meta();
-    }
-    for (kp = Map; kp->Function; kp++)
-       if (kp->Key == c)
-           break;
-    s = kp->Function ? (*kp->Function)() : insert_char((int)c);
-    if (!Pushed)
-       /* No pushback means no repeat count; hacky, but true. */
-       Repeat = NO_ARG;
-    return s;
-}
-
-STATIC STATUS
-TTYspecial(c)
-    unsigned int       c;
-{
-    if (ISMETA(c))
-       return CSdispatch;
-
-    if (c == rl_erase || c == DEL)
-       return bk_del_char();
-    if (c == rl_kill) {
-       if (Point != 0) {
-           Point = 0;
-           reposition();
-       }
-       Repeat = NO_ARG;
-       return kill_line();
-    }
-    if (c == rl_eof && Point == 0 && End == 0)
-       return CSeof;
-    if (c == rl_intr) {
-       Signal = SIGINT;
-       return CSsignal;
-    }
-    if (c == rl_quit) {
-       Signal = SIGQUIT;
-       return CSeof;
-    }
-
-    return CSdispatch;
-}
-
-STATIC CHAR *
-editinput()
-{
-    unsigned int       c;
-
-    Repeat = NO_ARG;
-    OldPoint = Point = Mark = End = 0;
-    Line[0] = '\0';
-
-    Signal = -1;
-    while ((c = TTYget()) != EOF)
-       switch (TTYspecial(c)) {
-       case CSdone:
-           return Line;
-       case CSeof:
-           return NULL;
-       case CSsignal:
-           return (CHAR *)"";
-       case CSmove:
-           reposition();
-           break;
-       case CSdispatch:
-           switch (emacs(c)) {
-           case CSdone:
-               return Line;
-           case CSeof:
-               return NULL;
-           case CSsignal:
-               return (CHAR *)"";
-           case CSmove:
-               reposition();
-               break;
-           case CSdispatch:
-           case CSstay:
-               break;
-           }
-           break;
-       case CSstay:
-           break;
-       }
-    return NULL;
-}
-
-STATIC void
-hist_add(p)
-    CHAR       *p;
-{
-    int                i;
-
-    if ((p = (CHAR *)strdup((char *)p)) == NULL)
-       return;
-    if (H.Size < HIST_SIZE)
-       H.Lines[H.Size++] = p;
-    else {
-       DISPOSE(H.Lines[0]);
-       for (i = 0; i < HIST_SIZE - 1; i++)
-           H.Lines[i] = H.Lines[i + 1];
-       H.Lines[i] = p;
-    }
-    H.Pos = H.Size - 1;
-}
-
-/*
-**  For compatibility with FSF readline.
-*/
-/* ARGSUSED0 */
-void
-rl_reset_terminal(p)
-    char       *p;
-{
-}
-
-void
-rl_initialize()
-{
-}
-
-char *
-readline(prompt)
-    CONST char *prompt;
-{
-    CHAR       *line;
-    int                s;
-
-    if (Line == NULL) {
-       Length = MEM_INC;
-       if ((Line = NEW(CHAR, Length)) == NULL)
-           return NULL;
-    }
-
-    TTYinfo();
-    rl_ttyset(0);
-    hist_add(NIL);
-    ScreenSize = SCREEN_INC;
-    Screen = NEW(char, ScreenSize);
-    Prompt = prompt ? prompt : (char *)NIL;
-    TTYputs((CHAR *)Prompt);
-    if ((line = editinput()) != NULL) {
-       line = (CHAR *)strdup((char *)line);
-       TTYputs((CHAR *)NEWLINE);
-       TTYflush();
-    }
-    rl_ttyset(1);
-    DISPOSE(Screen);
-    DISPOSE(H.Lines[--H.Size]);
-
-    if (line != NULL && *line != '\0'
-#if    defined(UNIQUE_HISTORY)
-       && !(H.Pos && strcmp((char *) line, (char *) H.Lines[H.Pos - 1]) == 0)
-#endif /* defined(UNIQUE_HISTORY) */
-       && !(H.Size && strcmp((char *) line, (char *) H.Lines[H.Size - 1]) == 0)
-    ) {
-       hist_add(line);
-    }
-
-    if (Signal > 0) {
-       s = Signal;
-       Signal = 0;
-       (void)kill(getpid(), s);
-    }
-    return (char *)line;
-}
-
-void
-add_history(p)
-    char       *p;
-{
-#ifdef obsolete                /* Made part of readline(). -- kjb */
-    if (p == NULL || *p == '\0')
-       return;
-
-#if    defined(UNIQUE_HISTORY)
-    if (H.Pos && strcmp(p, (char *) H.Lines[H.Pos - 1]) == 0)
-        return;
-#endif /* defined(UNIQUE_HISTORY) */
-    if (H.Size && strcmp(p, (char *) H.Lines[H.Size - 1]) == 0)
-       return;
-    hist_add((CHAR *)p);
-#endif
-}
-\f
-
-STATIC STATUS
-beg_line()
-{
-    if (Point) {
-       Point = 0;
-       return CSmove;
-    }
-    return CSstay;
-}
-
-STATIC STATUS
-del_char()
-{
-    return delete_string(Repeat == NO_ARG ? 1 : Repeat);
-}
-
-STATIC STATUS
-end_line()
-{
-    if (Point != End) {
-       Point = End;
-       return CSmove;
-    }
-    return CSstay;
-}
-
-STATIC char    SEPS[] = "\"#$&'()*:;<=>?[\\]^`{|}~\n\t ";
-
-/*
-**  Move back to the beginning of the current word and return an
-**  allocated copy of it.
-*/
-STATIC CHAR *
-find_word()
-{
-    CHAR       *p, *q;
-    CHAR       *new;
-    SIZE_T     len;
-
-    p = &Line[Point];
-    while (p > Line) {
-       p--;
-       if (p > Line && p[-1] == '\\') {
-           p--;
-       } else {
-           if (strchr(SEPS, (char) *p) != NULL) {
-               p++;
-               break;
-           }
-       }
-    }
-    len = Point - (p - Line) + 1;
-    if ((new = NEW(CHAR, len)) == NULL)
-       return NULL;
-    q = new;
-    while (p < &Line[Point]) {
-       if (*p == '\\') {
-           if (++p == &Line[Point]) break;
-       }
-       *q++ = *p++;
-    }
-    *q = '\0';
-    return new;
-}
-
-STATIC STATUS
-c_possible()
-{
-    CHAR       **av;
-    CHAR       *word;
-    int                ac;
-
-    word = find_word();
-    ac = rl_list_possib((char *)word, (char ***)&av);
-    if (word)
-       DISPOSE(word);
-    if (ac) {
-       columns(ac, av);
-       while (--ac >= 0)
-           DISPOSE(av[ac]);
-       DISPOSE(av);
-       return CSmove;
-    }
-    return ring_bell();
-}
-
-STATIC STATUS
-c_complete()
-{
-    CHAR       *p, *q;
-    CHAR       *word, *new;
-    SIZE_T     len;
-    int                unique;
-    STATUS     s;
-
-    word = find_word();
-    p = (CHAR *)rl_complete((char *)word, &unique);
-    if (word)
-       DISPOSE(word);
-    if (p) {
-       len = strlen((char *)p);
-       word = p;
-       new = q = NEW(CHAR, 2 * len + 1);
-       while (*p) {
-           if ((*p < ' ' || strchr(SEPS, (char) *p) != NULL)
-                               && (!unique || p[1] != 0)) {
-               *q++ = '\\';
-           }
-           *q++ = *p++;
-       }
-       *q = '\0';
-       DISPOSE(word);
-       if (len > 0) {
-           s = insert_string(new);
-#if ANNOYING_NOISE
-           if (!unique)
-               (void)ring_bell();
-#endif
-       }
-       DISPOSE(new);
-       if (len > 0) return s;
-    }
-    return c_possible();
-}
-
-STATIC STATUS
-accept_line()
-{
-    Line[End] = '\0';
-    return CSdone;
-}
-
-STATIC STATUS
-transpose()
-{
-    CHAR       c;
-
-    if (Point) {
-       if (Point == End)
-           left(CSmove);
-       c = Line[Point - 1];
-       left(CSstay);
-       Line[Point - 1] = Line[Point];
-       TTYshow(Line[Point - 1]);
-       Line[Point++] = c;
-       TTYshow(c);
-    }
-    return CSstay;
-}
-
-STATIC STATUS
-quote()
-{
-    unsigned int       c;
-
-    return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
-}
-
-STATIC STATUS
-wipe()
-{
-    int                i;
-
-    if (Mark > End)
-       return ring_bell();
-
-    if (Point > Mark) {
-       i = Point;
-       Point = Mark;
-       Mark = i;
-       reposition();
-    }
-
-    return delete_string(Mark - Point);
-}
-
-STATIC STATUS
-mk_set()
-{
-    Mark = Point;
-    return CSstay;
-}
-
-STATIC STATUS
-exchange()
-{
-    unsigned int       c;
-
-    if ((c = TTYget()) != CTL('X'))
-       return c == EOF ? CSeof : ring_bell();
-
-    if ((c = Mark) <= End) {
-       Mark = Point;
-       Point = c;
-       return CSmove;
-    }
-    return CSstay;
-}
-
-STATIC STATUS
-yank()
-{
-    if (Yanked && *Yanked)
-       return insert_string(Yanked);
-    return CSstay;
-}
-
-STATIC STATUS
-copy_region()
-{
-    if (Mark > End)
-       return ring_bell();
-
-    if (Point > Mark)
-       save_yank(Mark, Point - Mark);
-    else
-       save_yank(Point, Mark - Point);
-
-    return CSstay;
-}
-
-STATIC STATUS
-move_to_char()
-{
-    unsigned int       c;
-    int                        i;
-    CHAR               *p;
-
-    if ((c = TTYget()) == EOF)
-       return CSeof;
-    for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
-       if (*p == c) {
-           Point = i;
-           return CSmove;
-       }
-    return CSstay;
-}
-
-STATIC STATUS
-fd_word()
-{
-    return do_forward(CSmove);
-}
-
-STATIC STATUS
-fd_kill_word()
-{
-    int                i;
-
-    (void)do_forward(CSstay);
-    if (OldPoint != Point) {
-       i = Point - OldPoint;
-       Point = OldPoint;
-       return delete_string(i);
-    }
-    return CSstay;
-}
-
-STATIC STATUS
-bk_word()
-{
-    int                i;
-    CHAR       *p;
-
-    i = 0;
-    do {
-       for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
-           left(CSmove);
-
-       for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
-           left(CSmove);
-
-       if (Point == 0)
-           break;
-    } while (++i < Repeat);
-
-    return CSstay;
-}
-
-STATIC STATUS
-bk_kill_word()
-{
-    (void)bk_word();
-    if (OldPoint != Point)
-       return delete_string(OldPoint - Point);
-    return CSstay;
-}
-
-STATIC int
-argify(line, avp)
-    CHAR       *line;
-    CHAR       ***avp;
-{
-    CHAR       *c;
-    CHAR       **p;
-    CHAR       **new;
-    int                ac;
-    int                i;
-
-    i = MEM_INC;
-    if ((*avp = p = NEW(CHAR*, i))== NULL)
-        return 0;
-
-    for (c = line; isspace(*c); c++)
-       continue;
-    if (*c == '\n' || *c == '\0')
-       return 0;
-
-    for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
-       if (isspace(*c)) {
-           *c++ = '\0';
-           if (*c && *c != '\n') {
-               if (ac + 1 == i) {
-                   new = NEW(CHAR*, i + MEM_INC);
-                   if (new == NULL) {
-                       p[ac] = NULL;
-                       return ac;
-                   }
-                   COPYFROMTO(new, p, i * sizeof (char **));
-                   i += MEM_INC;
-                   DISPOSE(p);
-                   *avp = p = new;
-               }
-               p[ac++] = c;
-           }
-       }
-       else
-           c++;
-    }
-    *c = '\0';
-    p[ac] = NULL;
-    return ac;
-}
-
-STATIC STATUS
-last_argument()
-{
-    CHAR       **av;
-    CHAR       *p;
-    STATUS     s;
-    int                ac;
-
-    if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
-       return ring_bell();
-
-    if ((p = (CHAR *)strdup((char *)p)) == NULL)
-       return CSstay;
-    ac = argify(p, &av);
-
-    if (Repeat != NO_ARG)
-       s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
-    else
-       s = ac ? insert_string(av[ac - 1]) : CSstay;
-
-    if (ac)
-       DISPOSE(av);
-    DISPOSE(p);
-    return s;
-}
-
-STATIC KEYMAP  Map[33] = {
-    {  CTL('@'),       mk_set          },
-    {  CTL('A'),       beg_line        },
-    {  CTL('B'),       bk_char         },
-    {  CTL('D'),       del_char        },
-    {  CTL('E'),       end_line        },
-    {  CTL('F'),       fd_char         },
-    {  CTL('G'),       ring_bell       },
-    {  CTL('H'),       bk_del_char     },
-    {  CTL('I'),       c_complete      },
-    {  CTL('J'),       accept_line     },
-    {  CTL('K'),       kill_line       },
-    {  CTL('L'),       redisplay       },
-    {  CTL('M'),       accept_line     },
-    {  CTL('N'),       h_next          },
-    {  CTL('O'),       ring_bell       },
-    {  CTL('P'),       h_prev          },
-    {  CTL('Q'),       ring_bell       },
-    {  CTL('R'),       h_search        },
-    {  CTL('S'),       ring_bell       },
-    {  CTL('T'),       transpose       },
-    {  CTL('U'),       ring_bell       },
-    {  CTL('V'),       quote           },
-    {  CTL('W'),       bk_kill_word    },
-    {  CTL('X'),       exchange        },
-    {  CTL('Y'),       yank            },
-    {  CTL('Z'),       end_line        },
-    {  CTL('['),       meta            },
-    {  CTL(']'),       move_to_char    },
-    {  CTL('^'),       ring_bell       },
-    {  CTL('_'),       ring_bell       },
-    {  0,              NULL            }
-};
-
-STATIC KEYMAP  MetaMap[17]= {
-    {  CTL('H'),       wipe            },
-    {  DEL,            wipe            },
-    {  ' ',            mk_set          },
-    {  '.',            last_argument   },
-    {  '<',            h_first         },
-    {  '>',            h_last          },
-    {  '?',            c_possible      },
-    {  'b',            bk_word         },
-    {  'd',            fd_kill_word    },
-    {  'f',            fd_word         },
-    {  'l',            case_down_word  },
-    {  'm',            toggle_meta_mode },
-    {  'u',            case_up_word    },
-    {  'y',            yank            },
-    {  'w',            copy_region     },
-    {  0,              NULL            }
-};
-
-/*
- * $PchId: editline.c,v 1.4 1996/02/22 21:16:56 philip Exp $
- */
diff --git a/lib/libedit/editline.h b/lib/libedit/editline.h
deleted file mode 100644 (file)
index b63b69d..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-**  Internal header file for editline library.
-*/
-#include <stdio.h>
-#if    defined(HAVE_STDLIB)
-#include <stdlib.h>
-#include <string.h>
-#endif /* defined(HAVE_STDLIB) */
-#if    defined(SYS_UNIX)
-#include "unix.h"
-#endif /* defined(SYS_UNIX) */
-#if    defined(SYS_OS9)
-#include "os9.h"
-#endif /* defined(SYS_OS9) */
-
-#if    !defined(SIZE_T)
-#define SIZE_T unsigned int
-#endif /* !defined(SIZE_T) */
-
-typedef unsigned char  CHAR;
-
-#if    defined(HIDE)
-#define STATIC static
-#else
-#define STATIC /* NULL */
-#endif /* !defined(HIDE) */
-
-#if    !defined(CONST)
-#if    defined(__STDC__)
-#define CONST  const
-#else
-#define CONST
-#endif /* defined(__STDC__) */
-#endif /* !defined(CONST) */
-
-
-#define MEM_INC                64
-#define SCREEN_INC     256
-
-#define DISPOSE(p)     free((char *)(p))
-#define NEW(T, c)      \
-       ((T *)malloc((unsigned int)(sizeof (T) * (c))))
-#define RENEW(p, T, c) \
-       (p = (T *)realloc((char *)(p), (unsigned int)(sizeof (T) * (c))))
-#define COPYFROMTO(new, p, len)        \
-       (void)memcpy((char *)(new), (char *)(p), (int)(len))
-
-
-/*
-**  Variables and routines internal to this package.
-*/
-extern int     rl_eof;
-extern int     rl_erase;
-extern int     rl_intr;
-extern int     rl_kill;
-extern int     rl_quit;
-extern char    *rl_complete();
-extern int     rl_list_possib();
-extern void    rl_ttyset();
-extern void    rl_add_slash();
-
-#if    !defined(HAVE_STDLIB)
-extern char    *getenv();
-extern char    *malloc();
-extern char    *realloc();
-extern char    *memcpy();
-extern char    *strcat();
-extern char    *strchr();
-extern char    *strrchr();
-extern char    *strcpy();
-extern int     strcmp();
-extern int     strlen();
-extern int     strncmp();
-#endif /* !defined(HAVE_STDLIB) */
-
-#if    defined(NEED_STRDUP)
-extern char    *strdup();
-#endif
diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5
new file mode 100644 (file)
index 0000000..0c01605
--- /dev/null
@@ -0,0 +1,491 @@
+.\"    $NetBSD: editrc.5,v 1.26 2012/06/02 14:19:20 njoly Exp $
+.\"
+.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd October 18, 2003
+.Dt EDITRC 5
+.Os
+.Sh NAME
+.Nm editrc
+.Nd configuration file for editline library
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+file defines various settings to be used by the
+.Xr editline 3
+library.
+.Pp
+The format of each line is:
+.Dl [prog:]command [arg [...]]
+.Pp
+.Ar command
+is one of the
+.Xr editline 3
+builtin commands.
+Refer to
+.Sx BUILTIN COMMANDS
+for more information.
+.Pp
+.Ar prog
+is the program name string that a program defines when it calls
+.Xr el_init 3
+to set up
+.Xr editline 3 ,
+which is usually
+.Va argv[0] .
+.Ar command
+will be executed for any program which matches
+.Ar prog .
+.Pp
+.Ar prog
+may also be a
+.Xr regex 3
+style
+regular expression, in which case
+.Ar command
+will be executed for any program that matches the regular expression.
+.Pp
+If
+.Ar prog
+is absent,
+.Ar command
+is executed for all programs.
+.Sh BUILTIN COMMANDS
+The
+.Nm editline
+library has some builtin commands, which affect the way
+that the line editing and history functions operate.
+These are based on similar named builtins present in the
+.Xr tcsh 1
+shell.
+.Pp
+The following builtin commands are available:
+.Bl -tag -width 4n
+.It Ic bind Oo Fl a Oc Oo Fl e Oc Oo Fl k Oc Oo Fl l Oc Oo Fl r Oc \
+Oo Fl s Oc Oo Fl v Oc Oo Ar key Oo Ar command Oc Oc
+Without options, list all bound keys, and the editor command to which
+each is bound.
+If
+.Ar key
+is supplied, show the bindings for
+.Ar key .
+If
+.Ar key command
+is supplied, bind
+.Ar command
+to
+.Ar key .
+Options include:
+.Bl -tag -width 4n
+.It Fl e
+Bind all keys to the standard GNU Emacs-like bindings.
+.It Fl v
+Bind all keys to the standard
+.Xr vi 1 Ns -like
+bindings.
+.It Fl a
+List or change key bindings in the
+.Xr vi 1
+mode alternate (command mode) key map.
+.It Fl k
+.Ar key
+is interpreted as a symbolic arrow key name, which may be one of
+.Sq up ,
+.Sq down ,
+.Sq left
+or
+.Sq right .
+.It Fl l
+List all editor commands and a short description of each.
+.It Fl r
+Remove a key's binding.
+.It Fl s
+.Ar command
+is taken as a literal string and treated as terminal input when
+.Ar key
+is typed.
+Bound keys in
+.Ar command
+are themselves reinterpreted, and this continues for ten levels of
+interpretation.
+.El
+.Pp
+.Ar command
+may be one of the commands documented in
+.Sx "EDITOR COMMANDS"
+below, or another key.
+.Pp
+.Ar key
+and
+.Ar command
+can contain control characters of the form
+.Sm off
+.Sq No ^ Ar character
+.Sm on
+.Po
+e.g.
+.Sq ^A
+.Pc ,
+and the following backslashed escape sequences:
+.Pp
+.Bl -tag -compact -offset indent -width 4n
+.It Ic \ea
+Bell
+.It Ic \eb
+Backspace
+.It Ic \ee
+Escape
+.It Ic \ef
+Formfeed
+.It Ic \en
+Newline
+.It Ic \er
+Carriage return
+.It Ic \et
+Horizontal tab
+.It Ic \ev
+Vertical tab
+.Sm off
+.It Sy \e Ar nnn
+.Sm on
+The ASCII character corresponding to the octal number
+.Ar nnn .
+.El
+.Pp
+.Sq \e
+nullifies the special meaning of the following character,
+if it has any, notably
+.Sq \e
+and
+.Sq ^ .
+.It Ic echotc Oo Fl sv Oc Ar arg Ar ...
+Exercise terminal capabilities given in
+.Ar arg Ar ... .
+If
+.Ar arg
+is
+.Sq baud ,
+.Sq cols ,
+.Sq lines ,
+.Sq rows ,
+.Sq meta ,
+or
+.Sq tabs ,
+the value of that capability is printed, with
+.Dq yes
+or
+.Dq no
+indicating that the terminal does or does not have that capability.
+.Pp
+.Fl s
+returns an empty string for non-existent capabilities, rather than
+causing an error.
+.Fl v
+causes messages to be verbose.
+.It Ic edit Op Li on | Li off
+Enable or disable the
+.Nm editline
+functionality in a program.
+.It Ic history Ar list | Ar size Dv n | Ar unique Dv n
+The
+.Ar list
+command lists all entries in the history.
+The
+.Ar size
+command sets the history size to
+.Dv n
+entries.
+The
+.Ar unique
+command controls if history should keep duplicate entries.
+If
+.Dv n
+is non zero, only keep unique history entries.
+If
+.Dv n
+is zero, then keep all entries (the default).
+.It Ic telltc
+List the values of all the terminal capabilities (see
+.Xr termcap 5 ) .
+.It Ic settc Ar cap Ar val
+Set the terminal capability
+.Ar cap
+to
+.Ar val ,
+as defined in
+.Xr termcap 5 .
+No sanity checking is done.
+.It Ic setty Oo Fl a Oc Oo Fl d Oc Oo Fl q Oc Oo Fl x Oc Oo Ar +mode Oc \
+Oo Ar -mode Oc Oo Ar mode Oc Oo Ar char=c Oc
+Control which tty modes that
+.Nm
+won't allow the user to change.
+.Fl d ,
+.Fl q
+or
+.Fl x
+tells
+.Ic setty
+to act on the
+.Sq edit ,
+.Sq quote
+or
+.Sq execute
+set of tty modes respectively; defaulting to
+.Fl x .
+.Pp
+Without other arguments,
+.Ic setty
+lists the modes in the chosen set which are fixed on
+.Po
+.Sq +mode
+.Pc
+or off
+.Po
+.Sq -mode
+.Pc .
+.Fl a
+lists all tty modes in the chosen set regardless of the setting.
+With
+.Ar +mode ,
+.Ar -mode
+or
+.Ar mode ,
+fixes
+.Ar mode
+on or off or removes control of
+.Ar mode
+in the chosen set.
+.Pp
+.Ic Setty
+can also be used to set tty characters to particular values using
+.Ar char=value .
+If
+.Ar value
+is empty
+then the character is set to
+.Dv _POSIX_VDISABLE .
+.El
+.Sh EDITOR COMMANDS
+The following editor commands are available for use in key bindings:
+.\" Section automatically generated with makelist
+.Bl -tag -width 4n
+.It Ic vi-paste-next
+Vi paste previous deletion to the right of the cursor.
+.It Ic vi-paste-prev
+Vi paste previous deletion to the left of the cursor.
+.It Ic vi-prev-space-word
+Vi move to the previous space delimited word.
+.It Ic vi-prev-word
+Vi move to the previous word.
+.It Ic vi-next-space-word
+Vi move to the next space delimited word.
+.It Ic vi-next-word
+Vi move to the next word.
+.It Ic vi-change-case
+Vi change case of character under the cursor and advance one character.
+.It Ic vi-change-meta
+Vi change prefix command.
+.It Ic vi-insert-at-bol
+Vi enter insert mode at the beginning of line.
+.It Ic vi-replace-char
+Vi replace character under the cursor with the next character typed.
+.It Ic vi-replace-mode
+Vi enter replace mode.
+.It Ic vi-substitute-char
+Vi replace character under the cursor and enter insert mode.
+.It Ic vi-substitute-line
+Vi substitute entire line.
+.It Ic vi-change-to-eol
+Vi change to end of line.
+.It Ic vi-insert
+Vi enter insert mode.
+.It Ic vi-add
+Vi enter insert mode after the cursor.
+.It Ic vi-add-at-eol
+Vi enter insert mode at end of line.
+.It Ic vi-delete-meta
+Vi delete prefix command.
+.It Ic vi-end-word
+Vi move to the end of the current space delimited word.
+.It Ic vi-to-end-word
+Vi move to the end of the current word.
+.It Ic vi-undo
+Vi undo last change.
+.It Ic vi-command-mode
+Vi enter command mode (use alternative key bindings).
+.It Ic vi-zero
+Vi move to the beginning of line.
+.It Ic vi-delete-prev-char
+Vi move to previous character (backspace).
+.It Ic vi-list-or-eof
+Vi list choices for completion or indicate end of file if empty line.
+.It Ic vi-kill-line-prev
+Vi cut from beginning of line to cursor.
+.It Ic vi-search-prev
+Vi search history previous.
+.It Ic vi-search-next
+Vi search history next.
+.It Ic vi-repeat-search-next
+Vi repeat current search in the same search direction.
+.It Ic vi-repeat-search-prev
+Vi repeat current search in the opposite search direction.
+.It Ic vi-next-char
+Vi move to the character specified next.
+.It Ic vi-prev-char
+Vi move to the character specified previous.
+.It Ic vi-to-next-char
+Vi move up to the character specified next.
+.It Ic vi-to-prev-char
+Vi move up to the character specified previous.
+.It Ic vi-repeat-next-char
+Vi repeat current character search in the same search direction.
+.It Ic vi-repeat-prev-char
+Vi repeat current character search in the opposite search direction.
+.It Ic em-delete-or-list
+Delete character under cursor or list completions if at end of line.
+.It Ic em-delete-next-word
+Cut from cursor to end of current word.
+.It Ic em-yank
+Paste cut buffer at cursor position.
+.It Ic em-kill-line
+Cut the entire line and save in cut buffer.
+.It Ic em-kill-region
+Cut area between mark and cursor and save in cut buffer.
+.It Ic em-copy-region
+Copy area between mark and cursor to cut buffer.
+.It Ic em-gosmacs-transpose
+Exchange the two characters before the cursor.
+.It Ic em-next-word
+Move next to end of current word.
+.It Ic em-upper-case
+Uppercase the characters from cursor to end of current word.
+.It Ic em-capitol-case
+Capitalize the characters from cursor to end of current word.
+.It Ic em-lower-case
+Lowercase the characters from cursor to end of current word.
+.It Ic em-set-mark
+Set the mark at cursor.
+.It Ic em-exchange-mark
+Exchange the cursor and mark.
+.It Ic em-universal-argument
+Universal argument (argument times 4).
+.It Ic em-meta-next
+Add 8th bit to next character typed.
+.It Ic em-toggle-overwrite
+Switch from insert to overwrite mode or vice versa.
+.It Ic em-copy-prev-word
+Copy current word to cursor.
+.It Ic em-inc-search-next
+Emacs incremental next search.
+.It Ic em-inc-search-prev
+Emacs incremental reverse search.
+.It Ic ed-end-of-file
+Indicate end of file.
+.It Ic ed-insert
+Add character to the line.
+.It Ic ed-delete-prev-word
+Delete from beginning of current word to cursor.
+.It Ic ed-delete-next-char
+Delete character under cursor.
+.It Ic ed-kill-line
+Cut to the end of line.
+.It Ic ed-move-to-end
+Move cursor to the end of line.
+.It Ic ed-move-to-beg
+Move cursor to the beginning of line.
+.It Ic ed-transpose-chars
+Exchange the character to the left of the cursor with the one under it.
+.It Ic ed-next-char
+Move to the right one character.
+.It Ic ed-prev-word
+Move to the beginning of the current word.
+.It Ic ed-prev-char
+Move to the left one character.
+.It Ic ed-quoted-insert
+Add the next character typed verbatim.
+.It Ic ed-digit
+Adds to argument or enters a digit.
+.It Ic ed-argument-digit
+Digit that starts argument.
+.It Ic ed-unassigned
+Indicates unbound character.
+.It Ic ed-tty-sigint
+Tty interrupt character.
+.It Ic ed-tty-dsusp
+Tty delayed suspend character.
+.It Ic ed-tty-flush-output
+Tty flush output characters.
+.It Ic ed-tty-sigquit
+Tty quit character.
+.It Ic ed-tty-sigtstp
+Tty suspend character.
+.It Ic ed-tty-stop-output
+Tty disallow output characters.
+.It Ic ed-tty-start-output
+Tty allow output characters.
+.It Ic ed-newline
+Execute command.
+.It Ic ed-delete-prev-char
+Delete the character to the left of the cursor.
+.It Ic ed-clear-screen
+Clear screen leaving current line at the top.
+.It Ic ed-redisplay
+Redisplay everything.
+.It Ic ed-start-over
+Erase current line and start from scratch.
+.It Ic ed-sequence-lead-in
+First character in a bound sequence.
+.It Ic ed-prev-history
+Move to the previous history line.
+.It Ic ed-next-history
+Move to the next history line.
+.It Ic ed-search-prev-history
+Search previous in history for a line matching the current.
+.It Ic ed-search-next-history
+Search next in history for a line matching the current.
+.It Ic ed-prev-line
+Move up one line.
+.It Ic ed-next-line
+Move down one line.
+.It Ic ed-command
+Editline extended command.
+.El
+.\" End of section automatically generated with makelist
+.Sh SEE ALSO
+.Xr editline 3 ,
+.Xr regex 3 ,
+.Xr termcap 5
+.Sh AUTHORS
+The
+.Nm editline
+library was written by Christos Zoulas,
+and this manual was written by Luke Mewburn,
+with some sections inspired by
+.Xr tcsh 1 .
diff --git a/lib/libedit/el.c b/lib/libedit/el.c
new file mode 100644 (file)
index 0000000..d62790c
--- /dev/null
@@ -0,0 +1,617 @@
+/*     $NetBSD: el.c,v 1.71 2012/09/11 11:58:53 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)el.c       8.2 (Berkeley) 1/3/94";
+#else
+__RCSID("$NetBSD: el.c,v 1.71 2012/09/11 11:58:53 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * el.c: EditLine interface functions
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <locale.h>
+#include <langinfo.h>
+#include "el.h"
+
+/* el_init():
+ *     Initialize editline and set default parameters.
+ */
+public EditLine *
+el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
+{
+       EditLine *el = el_malloc(sizeof(*el));
+
+       if (el == NULL)
+               return NULL;
+
+       memset(el, 0, sizeof(EditLine));
+
+       el->el_infile = fin;
+       el->el_outfile = fout;
+       el->el_errfile = ferr;
+
+       el->el_infd = fileno(fin);
+       el->el_outfd = fileno(fout);
+       el->el_errfd = fileno(ferr);
+
+       el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
+       if (el->el_prog == NULL) {
+               el_free(el);
+               return NULL;
+       }
+
+       /*
+         * Initialize all the modules. Order is important!!!
+         */
+       el->el_flags = 0;
+#ifdef WIDECHAR
+       if (setlocale(LC_CTYPE, NULL) != NULL){
+               if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
+                       el->el_flags |= CHARSET_IS_UTF8;
+       }
+#endif
+
+       if (terminal_init(el) == -1) {
+               el_free(el->el_prog);
+               el_free(el);
+               return NULL;
+       }
+       (void) keymacro_init(el);
+       (void) map_init(el);
+       if (tty_init(el) == -1)
+               el->el_flags |= NO_TTY;
+       (void) ch_init(el);
+       (void) search_init(el);
+       (void) hist_init(el);
+       (void) prompt_init(el);
+       (void) sig_init(el);
+       (void) read_init(el);
+
+       return el;
+}
+
+
+/* el_end():
+ *     Clean up.
+ */
+public void
+el_end(EditLine *el)
+{
+
+       if (el == NULL)
+               return;
+
+       el_reset(el);
+
+       terminal_end(el);
+       keymacro_end(el);
+       map_end(el);
+       tty_end(el);
+       ch_end(el);
+       search_end(el);
+       hist_end(el);
+       prompt_end(el);
+       sig_end(el);
+
+       el_free(el->el_prog);
+#ifdef WIDECHAR
+       el_free(el->el_scratch.cbuff);
+       el_free(el->el_scratch.wbuff);
+       el_free(el->el_lgcyconv.cbuff);
+       el_free(el->el_lgcyconv.wbuff);
+#endif
+       el_free(el);
+}
+
+
+/* el_reset():
+ *     Reset the tty and the parser
+ */
+public void
+el_reset(EditLine *el)
+{
+
+       tty_cookedmode(el);
+       ch_reset(el, 0);                /* XXX: Do we want that? */
+}
+
+
+/* el_set():
+ *     set the editline parameters
+ */
+public int
+FUN(el,set)(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int rv = 0;
+
+       if (el == NULL)
+               return -1;
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:
+       case EL_RPROMPT: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+
+               rv = prompt_set(el, p, 0, op, 1);
+               break;
+       }
+
+       case EL_RESIZE: {
+               el_zfunc_t p = va_arg(ap, el_zfunc_t);
+               void *arg = va_arg(ap, void *);
+               rv = ch_resizefun(el, p, arg);
+               break;
+       }
+
+       case EL_PROMPT_ESC:
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+               int c = va_arg(ap, int);
+
+               rv = prompt_set(el, p, c, op, 1);
+               break;
+       }
+
+       case EL_TERMINAL:
+               rv = terminal_set(el, va_arg(ap, char *));
+               break;
+
+       case EL_EDITOR:
+               rv = map_set_editor(el, va_arg(ap, Char *));
+               break;
+
+       case EL_SIGNAL:
+               if (va_arg(ap, int))
+                       el->el_flags |= HANDLE_SIGNALS;
+               else
+                       el->el_flags &= ~HANDLE_SIGNALS;
+               break;
+
+       case EL_BIND:
+       case EL_TELLTC:
+       case EL_SETTC:
+       case EL_ECHOTC:
+       case EL_SETTY:
+       {
+               const Char *argv[20];
+               int i;
+
+               for (i = 1; i < (int)__arraycount(argv); i++)
+                       if ((argv[i] = va_arg(ap, Char *)) == NULL)
+                               break;
+
+               switch (op) {
+               case EL_BIND:
+                       argv[0] = STR("bind");
+                       rv = map_bind(el, i, argv);
+                       break;
+
+               case EL_TELLTC:
+                       argv[0] = STR("telltc");
+                       rv = terminal_telltc(el, i, argv);
+                       break;
+
+               case EL_SETTC:
+                       argv[0] = STR("settc");
+                       rv = terminal_settc(el, i, argv);
+                       break;
+
+               case EL_ECHOTC:
+                       argv[0] = STR("echotc");
+                       rv = terminal_echotc(el, i, argv);
+                       break;
+
+               case EL_SETTY:
+                       argv[0] = STR("setty");
+                       rv = tty_stty(el, i, argv);
+                       break;
+
+               default:
+                       rv = -1;
+                       EL_ABORT((el->el_errfile, "Bad op %d\n", op));
+                       break;
+               }
+               break;
+       }
+
+       case EL_ADDFN:
+       {
+               Char *name = va_arg(ap, Char *);
+               Char *help = va_arg(ap, Char *);
+               el_func_t func = va_arg(ap, el_func_t);
+
+               rv = map_addfunc(el, name, help, func);
+               break;
+       }
+
+       case EL_HIST:
+       {
+               hist_fun_t func = va_arg(ap, hist_fun_t);
+               void *ptr = va_arg(ap, void *);
+
+               rv = hist_set(el, func, ptr);
+               if (!(el->el_flags & CHARSET_IS_UTF8))
+                       el->el_flags &= ~NARROW_HISTORY;
+               break;
+       }
+
+       case EL_EDITMODE:
+               if (va_arg(ap, int))
+                       el->el_flags &= ~EDIT_DISABLED;
+               else
+                       el->el_flags |= EDIT_DISABLED;
+               rv = 0;
+               break;
+
+       case EL_GETCFN:
+       {
+               el_rfunc_t rc = va_arg(ap, el_rfunc_t);
+               rv = el_read_setfn(el, rc);
+               el->el_flags &= ~NARROW_READ;
+               break;
+       }
+
+       case EL_CLIENTDATA:
+               el->el_data = va_arg(ap, void *);
+               break;
+
+       case EL_UNBUFFERED:
+               rv = va_arg(ap, int);
+               if (rv && !(el->el_flags & UNBUFFERED)) {
+                       el->el_flags |= UNBUFFERED;
+                       read_prepare(el);
+               } else if (!rv && (el->el_flags & UNBUFFERED)) {
+                       el->el_flags &= ~UNBUFFERED;
+                       read_finish(el);
+               }
+               rv = 0;
+               break;
+
+       case EL_PREP_TERM:
+               rv = va_arg(ap, int);
+               if (rv)
+                       (void) tty_rawmode(el);
+               else
+                       (void) tty_cookedmode(el);
+               rv = 0;
+               break;
+
+       case EL_SETFP:
+       {
+               FILE *fp;
+               int what;
+
+               what = va_arg(ap, int);
+               fp = va_arg(ap, FILE *);
+
+               rv = 0;
+               switch (what) {
+               case 0:
+                       el->el_infile = fp;
+                       el->el_infd = fileno(fp);
+                       break;
+               case 1:
+                       el->el_outfile = fp;
+                       el->el_outfd = fileno(fp);
+                       break;
+               case 2:
+                       el->el_errfile = fp;
+                       el->el_errfd = fileno(fp);
+                       break;
+               default:
+                       rv = -1;
+                       break;
+               }
+               break;
+       }
+
+       case EL_REFRESH:
+               re_clear_display(el);
+               re_refresh(el);
+               terminal__flush(el);
+               break;
+
+       default:
+               rv = -1;
+               break;
+       }
+
+       va_end(ap);
+       return rv;
+}
+
+
+/* el_get():
+ *     retrieve the editline parameters
+ */
+public int
+FUN(el,get)(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int rv;
+
+       if (el == NULL)
+               return -1;
+
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:
+       case EL_RPROMPT: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               rv = prompt_get(el, p, 0, op);
+               break;
+       }
+       case EL_PROMPT_ESC:
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               Char *c = va_arg(ap, Char *);
+
+               rv = prompt_get(el, p, c, op);
+               break;
+       }
+
+       case EL_EDITOR:
+               rv = map_get_editor(el, va_arg(ap, const Char **));
+               break;
+
+       case EL_SIGNAL:
+               *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
+               rv = 0;
+               break;
+
+       case EL_EDITMODE:
+               *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
+               rv = 0;
+               break;
+
+       case EL_TERMINAL:
+               terminal_get(el, va_arg(ap, const char **));
+               rv = 0;
+               break;
+
+       case EL_GETTC:
+       {
+               static char name[] = "gettc";
+               char *argv[20];
+               int i;
+
+               for (i = 1; i < (int)__arraycount(argv); i++)
+                       if ((argv[i] = va_arg(ap, char *)) == NULL)
+                               break;
+
+               argv[0] = name;
+               rv = terminal_gettc(el, i, argv);
+               break;
+       }
+
+       case EL_GETCFN:
+               *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
+               rv = 0;
+               break;
+
+       case EL_CLIENTDATA:
+               *va_arg(ap, void **) = el->el_data;
+               rv = 0;
+               break;
+
+       case EL_UNBUFFERED:
+               *va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0;
+               rv = 0;
+               break;
+
+       case EL_GETFP:
+       {
+               int what;
+               FILE **fpp;
+
+               what = va_arg(ap, int);
+               fpp = va_arg(ap, FILE **);
+               rv = 0;
+               switch (what) {
+               case 0:
+                       *fpp = el->el_infile;
+                       break;
+               case 1:
+                       *fpp = el->el_outfile;
+                       break;
+               case 2:
+                       *fpp = el->el_errfile;
+                       break;
+               default:
+                       rv = -1;
+                       break;
+               }
+               break;
+       }
+       default:
+               rv = -1;
+               break;
+       }
+       va_end(ap);
+
+       return rv;
+}
+
+
+/* el_line():
+ *     Return editing info
+ */
+public const TYPE(LineInfo) *
+FUN(el,line)(EditLine *el)
+{
+
+       return (const TYPE(LineInfo) *)(void *)&el->el_line;
+}
+
+
+/* el_source():
+ *     Source a file
+ */
+public int
+el_source(EditLine *el, const char *fname)
+{
+       FILE *fp;
+       size_t len;
+       char *ptr;
+       char *path = NULL;
+       const Char *dptr;
+       int error = 0;
+
+       fp = NULL;
+       if (fname == NULL) {
+#ifdef HAVE_ISSETUGID
+               static const char elpath[] = "/.editrc";
+               size_t plen = sizeof(elpath);
+
+               if (issetugid())
+                       return -1;
+               if ((ptr = getenv("HOME")) == NULL)
+                       return -1;
+               plen += strlen(ptr);
+               if ((path = el_malloc(plen * sizeof(*path))) == NULL)
+                       return -1;
+               (void)snprintf(path, plen, "%s%s", ptr, elpath);
+               fname = path;
+#else
+               /*
+                * If issetugid() is missing, always return an error, in order
+                * to keep from inadvertently opening up the user to a security
+                * hole.
+                */
+               return -1;
+#endif
+       }
+       if (fp == NULL)
+               fp = fopen(fname, "r");
+       if (fp == NULL) {
+               el_free(path);
+               return -1;
+       }
+
+       while ((ptr = fgetln(fp, &len)) != NULL) {
+               if (*ptr == '\n')
+                       continue;       /* Empty line. */
+               dptr = ct_decode_string(ptr, &el->el_scratch);
+               if (!dptr)
+                       continue;
+               if (len > 0 && dptr[len - 1] == '\n')
+                       --len;
+
+               /* loop until first non-space char or EOL */
+               while (*dptr != '\0' && Isspace(*dptr))
+                       dptr++;
+               if (*dptr == '#')
+                       continue;   /* ignore, this is a comment line */
+               if ((error = parse_line(el, dptr)) == -1)
+                       break;
+       }
+
+       el_free(path);
+       (void) fclose(fp);
+       return error;
+}
+
+
+/* el_resize():
+ *     Called from program when terminal is resized
+ */
+public void
+el_resize(EditLine *el)
+{
+       int lins, cols;
+       sigset_t oset, nset;
+
+       (void) sigemptyset(&nset);
+       (void) sigaddset(&nset, SIGWINCH);
+       (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+       /* get the correct window size */
+       if (terminal_get_size(el, &lins, &cols))
+               terminal_change_size(el, lins, cols);
+
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+
+/* el_beep():
+ *     Called from the program to beep
+ */
+public void
+el_beep(EditLine *el)
+{
+
+       terminal_beep(el);
+}
+
+
+/* el_editmode()
+ *     Set the state of EDIT_DISABLED from the `edit' command.
+ */
+protected int
+/*ARGSUSED*/
+el_editmode(EditLine *el, int argc, const Char **argv)
+{
+       const Char *how;
+
+       if (argv == NULL || argc != 2 || argv[1] == NULL)
+               return -1;
+
+       how = argv[1];
+       if (Strcmp(how, STR("on")) == 0) {
+               el->el_flags &= ~EDIT_DISABLED;
+               tty_rawmode(el);
+       } else if (Strcmp(how, STR("off")) == 0) {
+               tty_cookedmode(el);
+               el->el_flags |= EDIT_DISABLED;
+       }
+       else {
+               (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n",
+                   how);
+               return -1;
+       }
+       return 0;
+}
diff --git a/lib/libedit/el.h b/lib/libedit/el.h
new file mode 100644 (file)
index 0000000..70c67b8
--- /dev/null
@@ -0,0 +1,163 @@
+/*     $NetBSD: el.h,v 1.25 2011/07/29 23:44:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)el.h        8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.h: Internal structures.
+ */
+#ifndef _h_el
+#define        _h_el
+/*
+ * Local defaults
+ */
+#define        KSHVI
+#define        VIDEFAULT
+#define        ANCHOR
+
+#include "histedit.h"
+#include "chartype.h"
+#include <stdio.h>
+#include <sys/types.h>
+
+#define        EL_BUFSIZ       ((size_t)1024)  /* Maximum line size            */
+
+#define        HANDLE_SIGNALS  0x01
+#define        NO_TTY          0x02
+#define        EDIT_DISABLED   0x04
+#define        UNBUFFERED      0x08
+#define        CHARSET_IS_UTF8 0x10
+#define        IGNORE_EXTCHARS 0x20            /* Ignore characters read > 0xff */
+#define        NARROW_HISTORY  0x40
+#define        NARROW_READ     0x80
+
+typedef int bool_t;                    /* True or not                  */
+
+typedef unsigned char el_action_t;     /* Index to command array       */
+
+typedef struct coord_t {               /* Position on the screen       */
+       int     h;
+       int     v;
+} coord_t;
+
+typedef struct el_line_t {
+       Char            *buffer;        /* Input line                   */
+       Char            *cursor;        /* Cursor position              */
+       Char            *lastchar;      /* Last character               */
+       const Char      *limit;         /* Max position                 */
+} el_line_t;
+
+/*
+ * Editor state
+ */
+typedef struct el_state_t {
+       int             inputmode;      /* What mode are we in?         */
+       int             doingarg;       /* Are we getting an argument?  */
+       int             argument;       /* Numeric argument             */
+       int             metanext;       /* Is the next char a meta char */
+       el_action_t     lastcmd;        /* Previous command             */
+       el_action_t     thiscmd;        /* this command                 */
+       Char            thisch;         /* char that generated it       */
+} el_state_t;
+
+/*
+ * Until we come up with something better...
+ */
+#define        el_malloc(a)    malloc(a)
+#define        el_realloc(a,b) realloc(a, b)
+#define        el_free(a)      free(a)
+
+#include "tty.h"
+#include "prompt.h"
+#include "keymacro.h"
+#include "terminal.h"
+#include "refresh.h"
+#include "chared.h"
+#include "common.h"
+#include "search.h"
+#include "hist.h"
+#include "map.h"
+#include "parse.h"
+#include "sig.h"
+#include "help.h"
+#include "read.h"
+
+struct editline {
+       Char             *el_prog;      /* the program name             */
+       FILE             *el_infile;    /* Stdio stuff                  */
+       FILE             *el_outfile;   /* Stdio stuff                  */
+       FILE             *el_errfile;   /* Stdio stuff                  */
+       int               el_infd;      /* Input file descriptor        */
+       int               el_outfd;     /* Output file descriptor       */
+       int               el_errfd;     /* Error file descriptor        */
+       int               el_flags;     /* Various flags.               */
+       int               el_errno;     /* Local copy of errno          */
+       coord_t           el_cursor;    /* Cursor location              */
+       Char            **el_display;   /* Real screen image = what is there */
+       Char            **el_vdisplay;  /* Virtual screen image = what we see */
+       void             *el_data;      /* Client data                  */
+       el_line_t         el_line;      /* The current line information */
+       el_state_t        el_state;     /* Current editor state         */
+       el_terminal_t     el_terminal;  /* Terminal dependent stuff     */
+       el_tty_t          el_tty;       /* Tty dependent stuff          */
+       el_refresh_t      el_refresh;   /* Refresh stuff                */
+       el_prompt_t       el_prompt;    /* Prompt stuff                 */
+       el_prompt_t       el_rprompt;   /* Prompt stuff                 */
+       el_chared_t       el_chared;    /* Characted editor stuff       */
+       el_map_t          el_map;       /* Key mapping stuff            */
+       el_keymacro_t     el_keymacro;  /* Key binding stuff            */
+       el_history_t      el_history;   /* History stuff                */
+       el_search_t       el_search;    /* Search stuff                 */
+       el_signal_t       el_signal;    /* Signal handling stuff        */
+       el_read_t         el_read;      /* Character reading stuff      */
+#ifdef WIDECHAR
+       ct_buffer_t       el_scratch;   /* Scratch conversion buffer    */
+       ct_buffer_t       el_lgcyconv;  /* Buffer for legacy wrappers   */
+       LineInfo          el_lgcylinfo; /* Legacy LineInfo buffer       */
+#endif
+};
+
+protected int  el_editmode(EditLine *, int, const Char **);
+
+#ifdef DEBUG
+#define        EL_ABORT(a)     do { \
+                               fprintf(el->el_errfile, "%s, %d: ", \
+                                        __FILE__, __LINE__); \
+                               fprintf a; \
+                               abort(); \
+                       } while( /*CONSTCOND*/0);
+#else
+#define EL_ABORT(a)    abort()
+#endif
+#endif /* _h_el */
diff --git a/lib/libedit/eln.c b/lib/libedit/eln.c
new file mode 100644 (file)
index 0000000..1b829c2
--- /dev/null
@@ -0,0 +1,371 @@
+/*     $NetBSD: eln.c,v 1.14 2012/03/11 21:15:25 christos Exp $        */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+__RCSID("$NetBSD: eln.c,v 1.14 2012/03/11 21:15:25 christos Exp $");
+#endif /* not lint && not SCCSID */
+
+#include "histedit.h"
+#include "el.h"
+#include "read.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+public int
+el_getc(EditLine *el, char *cp)
+{
+       int num_read;
+       wchar_t wc = 0;
+
+       if (!(el->el_flags & CHARSET_IS_UTF8))
+               el->el_flags |= IGNORE_EXTCHARS;
+       num_read = el_wgetc (el, &wc);
+       if (!(el->el_flags & CHARSET_IS_UTF8))
+               el->el_flags &= ~IGNORE_EXTCHARS;
+
+       if (num_read > 0)
+               *cp = (char)wc;
+       return num_read;
+}
+
+
+public void
+el_push(EditLine *el, const char *str)
+{
+       /* Using multibyte->wide string decoding works fine under single-byte
+        * character sets too, and Does The Right Thing. */
+       el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
+}
+
+
+public const char *
+el_gets(EditLine *el, int *nread)
+{
+       const wchar_t *tmp;
+
+       el->el_flags |= IGNORE_EXTCHARS;
+       tmp = el_wgets(el, nread);
+       el->el_flags &= ~IGNORE_EXTCHARS;
+       return ct_encode_string(tmp, &el->el_lgcyconv);
+}
+
+
+public int
+el_parse(EditLine *el, int argc, const char *argv[])
+{
+       int ret;
+       const wchar_t **wargv;
+
+       wargv = (const wchar_t **)
+           ct_decode_argv(argc, argv, &el->el_lgcyconv);
+       if (!wargv)
+               return -1;
+       ret = el_wparse(el, argc, wargv);
+       ct_free_argv(wargv);
+
+       return ret;
+}
+
+
+public int
+el_set(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int ret;
+
+       if (!el)
+               return -1;
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:         /* el_pfunc_t */
+       case EL_RPROMPT: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+               ret = prompt_set(el, p, 0, op, 0);
+               break;
+       }
+
+       case EL_RESIZE: {
+               el_zfunc_t p = va_arg(ap, el_zfunc_t);
+               void *arg = va_arg(ap, void *);
+               ret = ch_resizefun(el, p, arg);
+               break;
+       }
+
+       case EL_TERMINAL:       /* const char * */
+               ret = el_wset(el, op, va_arg(ap, char *));
+               break;
+
+       case EL_EDITOR:         /* const wchar_t * */
+               ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
+                   &el->el_lgcyconv));
+               break;
+
+       case EL_SIGNAL:         /* int */
+       case EL_EDITMODE:
+       case EL_UNBUFFERED:
+       case EL_PREP_TERM:
+               ret = el_wset(el, op, va_arg(ap, int));
+               break;
+
+       case EL_BIND:   /* const char * list -> const wchar_t * list */
+       case EL_TELLTC:
+       case EL_SETTC:
+       case EL_ECHOTC:
+       case EL_SETTY: {
+               const char *argv[20];
+               int i;
+               const wchar_t **wargv;
+               for (i = 1; i < (int)__arraycount(argv); ++i)
+                       if ((argv[i] = va_arg(ap, char *)) == NULL)
+                           break;
+               argv[0] = NULL;
+               wargv = (const wchar_t **)
+                   ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
+               if (!wargv) {
+                   ret = -1;
+                   goto out;
+               }
+               /*
+                * AFAIK we can't portably pass through our new wargv to
+                * el_wset(), so we have to reimplement the body of
+                * el_wset() for these ops.
+                */
+               switch (op) {
+               case EL_BIND:
+                       wargv[0] = STR("bind");
+                       ret = map_bind(el, i, wargv);
+                       break;
+               case EL_TELLTC:
+                       wargv[0] = STR("telltc");
+                       ret = terminal_telltc(el, i, wargv);
+                       break;
+               case EL_SETTC:
+                       wargv[0] = STR("settc");
+                       ret = terminal_settc(el, i, wargv);
+                       break;
+               case EL_ECHOTC:
+                       wargv[0] = STR("echotc");
+                       ret = terminal_echotc(el, i, wargv);
+                       break;
+               case EL_SETTY:
+                       wargv[0] = STR("setty");
+                       ret = tty_stty(el, i, wargv);
+                       break;
+               default:
+                       ret = -1;
+               }
+               ct_free_argv(wargv);
+               break;
+       }
+
+       /* XXX: do we need to change el_func_t too? */
+       case EL_ADDFN: {          /* const char *, const char *, el_func_t */
+               const char *args[2];
+               el_func_t func;
+               wchar_t **wargv;
+
+               args[0] = va_arg(ap, const char *);
+               args[1] = va_arg(ap, const char *);
+               func = va_arg(ap, el_func_t);
+
+               wargv = ct_decode_argv(2, args, &el->el_lgcyconv);
+               if (!wargv) {
+                   ret = -1;
+                   goto out;
+               }
+               // XXX: The two strdup's leak
+               ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
+                   func);
+               ct_free_argv(wargv);
+               break;
+       }
+       case EL_HIST: {           /* hist_fun_t, const char * */
+               hist_fun_t fun = va_arg(ap, hist_fun_t);
+               void *ptr = va_arg(ap, void *);
+               ret = hist_set(el, fun, ptr);
+               el->el_flags |= NARROW_HISTORY;
+               break;
+       }
+       /* XXX: do we need to change el_rfunc_t? */
+       case EL_GETCFN:         /* el_rfunc_t */
+               ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
+               el->el_flags |= NARROW_READ;
+               break;
+       case EL_CLIENTDATA:     /* void * */
+               ret = el_wset(el, op, va_arg(ap, void *));
+               break;
+       case EL_SETFP: {          /* int, FILE * */
+               int what = va_arg(ap, int);
+               FILE *fp = va_arg(ap, FILE *);
+               ret = el_wset(el, op, what, fp);
+               break;
+       }
+       case EL_PROMPT_ESC: /* el_pfunc_t, char */
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+               char c = (char)va_arg(ap, int);
+               ret = prompt_set(el, p, c, op, 0);
+               break;
+       }
+       default:
+               ret = -1;
+               break;
+       }
+
+out:
+       va_end(ap);
+       return ret;
+}
+
+
+public int
+el_get(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int ret;
+
+       if (!el)
+               return -1;
+
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:         /* el_pfunc_t * */
+       case EL_RPROMPT: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               ret = prompt_get(el, p, 0, op);
+               break;
+       }
+
+       case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               char *c = va_arg(ap, char *);
+               wchar_t wc = 0;
+               ret = prompt_get(el, p, &wc, op);
+               *c = (char)wc;
+               break;
+       }
+
+       case EL_EDITOR: {
+               const char **p = va_arg(ap, const char **);
+               const wchar_t *pw;
+               ret = el_wget(el, op, &pw);
+               *p = ct_encode_string(pw, &el->el_lgcyconv);
+               if (!el->el_lgcyconv.csize)
+                       ret = -1;
+               break;
+       }
+
+       case EL_TERMINAL:       /* const char ** */
+               ret = el_wget(el, op, va_arg(ap, const char **));
+               break;
+
+       case EL_SIGNAL:         /* int * */
+       case EL_EDITMODE:
+       case EL_UNBUFFERED:
+       case EL_PREP_TERM:
+               ret = el_wget(el, op, va_arg(ap, int *));
+               break;
+
+       case EL_GETTC: {
+               char *argv[20];
+               static char gettc[] = "gettc";
+               int i;
+               for (i = 1; i < (int)__arraycount(argv); ++i)
+                       if ((argv[i] = va_arg(ap, char *)) == NULL)
+                               break;
+               argv[0] = gettc;
+               ret = terminal_gettc(el, i, argv);
+               break;
+       }
+
+       /* XXX: do we need to change el_rfunc_t? */
+       case EL_GETCFN:         /* el_rfunc_t */
+               ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
+               break;
+
+       case EL_CLIENTDATA:     /* void ** */
+               ret = el_wget(el, op, va_arg(ap, void **));
+               break;
+
+       case EL_GETFP: {          /* int, FILE ** */
+               int what = va_arg(ap, int);
+               FILE **fpp = va_arg(ap, FILE **);
+               ret = el_wget(el, op, what, fpp);
+               break;
+       }
+
+       default:
+               ret = -1;
+               break;
+       }
+
+       va_end(ap);
+       return ret;
+}
+
+
+const LineInfo *
+el_line(EditLine *el)
+{
+       const LineInfoW *winfo = el_wline(el);
+       LineInfo *info = &el->el_lgcylinfo;
+       size_t offset;
+       const Char *p;
+
+       info->buffer   = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
+
+       offset = 0;
+       for (p = winfo->buffer; p < winfo->cursor; p++)
+               offset += ct_enc_width(*p);
+       info->cursor = info->buffer + offset;
+
+       offset = 0;
+       for (p = winfo->buffer; p < winfo->lastchar; p++)
+               offset += ct_enc_width(*p);
+       info->lastchar = info->buffer + offset;
+
+       return info;
+}
+
+
+int
+el_insertstr(EditLine *el, const char *str)
+{
+       return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
+}
diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c
new file mode 100644 (file)
index 0000000..ab1e2df
--- /dev/null
@@ -0,0 +1,508 @@
+/*     $NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)emacs.c    8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * emacs.c: Emacs functions
+ */
+#include "el.h"
+
+/* em_delete_or_list():
+ *     Delete character under cursor or list completions if at end of line
+ *     [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_or_list(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor == el->el_line.lastchar) {
+                                       /* if I'm at the end */
+               if (el->el_line.cursor == el->el_line.buffer) {
+                                       /* and the beginning */
+                       terminal_writec(el, c); /* then do an EOF */
+                       return CC_EOF;
+               } else {
+                       /*
+                        * Here we could list completions, but it is an
+                        * error right now
+                        */
+                       terminal_beep(el);
+                       return CC_ERROR;
+               }
+       } else {
+               if (el->el_state.doingarg)
+                       c_delafter(el, el->el_state.argument);
+               else
+                       c_delafter1(el);
+               if (el->el_line.cursor > el->el_line.lastchar)
+                       el->el_line.cursor = el->el_line.lastchar;
+                               /* bounds check */
+               return CC_REFRESH;
+       }
+}
+
+
+/* em_delete_next_word():
+ *     Cut from cursor to end of current word
+ *     [M-d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_next_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *p, *kp;
+
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return CC_ERROR;
+
+       cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
+                               /* save the text */
+               *kp++ = *p;
+       el->el_chared.c_kill.last = kp;
+
+       c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+                               /* bounds check */
+       return CC_REFRESH;
+}
+
+
+/* em_yank():
+ *     Paste cut buffer at cursor position
+ *     [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_yank(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
+               return CC_NORM;
+
+       if (el->el_line.lastchar +
+           (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
+           el->el_line.limit)
+               return CC_ERROR;
+
+       el->el_chared.c_kill.mark = el->el_line.cursor;
+       cp = el->el_line.cursor;
+
+       /* open the space, */
+       c_insert(el,
+           (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
+       /* copy the chars */
+       for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
+               *cp++ = *kp;
+
+       /* if an arg, cursor at beginning else cursor at end */
+       if (el->el_state.argument == 1)
+               el->el_line.cursor = cp;
+
+       return CC_REFRESH;
+}
+
+
+/* em_kill_line():
+ *     Cut the entire line and save in cut buffer
+ *     [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       cp = el->el_line.buffer;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.lastchar)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+                               /* zap! -- delete all of it */
+       el->el_line.lastchar = el->el_line.buffer;
+       el->el_line.cursor = el->el_line.buffer;
+       return CC_REFRESH;
+}
+
+
+/* em_kill_region():
+ *     Cut area between mark and cursor and save in cut buffer
+ *     [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_region(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       if (!el->el_chared.c_kill.mark)
+               return CC_ERROR;
+
+       if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+               cp = el->el_line.cursor;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_chared.c_kill.mark)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+               c_delafter(el, (int)(cp - el->el_line.cursor));
+       } else {                /* mark is before cursor */
+               cp = el->el_chared.c_kill.mark;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_line.cursor)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+               c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
+               el->el_line.cursor = el->el_chared.c_kill.mark;
+       }
+       return CC_REFRESH;
+}
+
+
+/* em_copy_region():
+ *     Copy area between mark and cursor to cut buffer
+ *     [M-W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_region(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       if (!el->el_chared.c_kill.mark)
+               return CC_ERROR;
+
+       if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+               cp = el->el_line.cursor;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_chared.c_kill.mark)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+       } else {
+               cp = el->el_chared.c_kill.mark;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_line.cursor)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+       }
+       return CC_NORM;
+}
+
+
+/* em_gosmacs_transpose():
+ *     Exchange the two characters before the cursor
+ *     Gosling emacs transpose chars [^T]
+ */
+protected el_action_t
+em_gosmacs_transpose(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor > &el->el_line.buffer[1]) {
+               /* must have at least two chars entered */
+               c = el->el_line.cursor[-2];
+               el->el_line.cursor[-2] = el->el_line.cursor[-1];
+               el->el_line.cursor[-1] = c;
+               return CC_REFRESH;
+       } else
+               return CC_ERROR;
+}
+
+
+/* em_next_word():
+ *     Move next to end of current word
+ *     [M-f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_next_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return CC_ERROR;
+
+       el->el_line.cursor = c__next_word(el->el_line.cursor,
+           el->el_line.lastchar,
+           el->el_state.argument,
+           ce__isword);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* em_upper_case():
+ *     Uppercase the characters from cursor to end of current word
+ *     [M-u]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_upper_case(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++)
+               if (Islower(*cp))
+                       *cp = Toupper(*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return CC_REFRESH;
+}
+
+
+/* em_capitol_case():
+ *     Capitalize the characters from cursor to end of current word
+ *     [M-c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_capitol_case(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++) {
+               if (Isalpha(*cp)) {
+                       if (Islower(*cp))
+                               *cp = Toupper(*cp);
+                       cp++;
+                       break;
+               }
+       }
+       for (; cp < ep; cp++)
+               if (Isupper(*cp))
+                       *cp = Tolower(*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return CC_REFRESH;
+}
+
+
+/* em_lower_case():
+ *     Lowercase the characters from cursor to end of current word
+ *     [M-l]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_lower_case(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++)
+               if (Isupper(*cp))
+                       *cp = Tolower(*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return CC_REFRESH;
+}
+
+
+/* em_set_mark():
+ *     Set the mark at cursor
+ *     [^@]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_set_mark(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_chared.c_kill.mark = el->el_line.cursor;
+       return CC_NORM;
+}
+
+
+/* em_exchange_mark():
+ *     Exchange the cursor and mark
+ *     [^X^X]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_exchange_mark(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp;
+
+       cp = el->el_line.cursor;
+       el->el_line.cursor = el->el_chared.c_kill.mark;
+       el->el_chared.c_kill.mark = cp;
+       return CC_CURSOR;
+}
+
+
+/* em_universal_argument():
+ *     Universal argument (argument times 4)
+ *     [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_universal_argument(EditLine *el, Int c __attribute__((__unused__)))
+{                              /* multiply current argument by 4 */
+
+       if (el->el_state.argument > 1000000)
+               return CC_ERROR;
+       el->el_state.doingarg = 1;
+       el->el_state.argument *= 4;
+       return CC_ARGHACK;
+}
+
+
+/* em_meta_next():
+ *     Add 8th bit to next character typed
+ *     [<ESC>]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_meta_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_state.metanext = 1;
+       return CC_ARGHACK;
+}
+
+
+/* em_toggle_overwrite():
+ *     Switch from insert to overwrite mode or vice versa
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_toggle_overwrite(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
+           MODE_REPLACE : MODE_INSERT;
+       return CC_NORM;
+}
+
+
+/* em_copy_prev_word():
+ *     Copy current word to cursor
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *oldc, *dp;
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       oldc = el->el_line.cursor;
+       /* does a bounds check */
+       cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+           el->el_state.argument, ce__isword);
+
+       c_insert(el, (int)(oldc - cp));
+       for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
+               *dp++ = *cp;
+
+       el->el_line.cursor = dp;/* put cursor at end */
+
+       return CC_REFRESH;
+}
+
+
+/* em_inc_search_next():
+ *     Emacs incremental next search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_search.patlen = 0;
+       return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
+}
+
+
+/* em_inc_search_prev():
+ *     Emacs incremental reverse search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_prev(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_search.patlen = 0;
+       return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
+}
+
+
+/* em_delete_prev_char():
+ *     Delete the character to the left of the cursor
+ *     [^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor <= el->el_line.buffer)
+               return CC_ERROR;
+
+       if (el->el_state.doingarg)
+               c_delbefore(el, el->el_state.argument);
+       else
+               c_delbefore1(el);
+       el->el_line.cursor -= el->el_state.argument;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+       return CC_REFRESH;
+}
diff --git a/lib/libedit/filecomplete.c b/lib/libedit/filecomplete.c
new file mode 100644 (file)
index 0000000..5e98cf5
--- /dev/null
@@ -0,0 +1,580 @@
+/*     $NetBSD: filecomplete.c,v 1.31 2011/09/16 16:13:16 plunky Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+__RCSID("$NetBSD: filecomplete.c,v 1.31 2011/09/16 16:13:16 plunky Exp $");
+#endif /* not lint && not SCCSID */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "el.h"
+#include "fcns.h"              /* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@',
+    '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
+
+
+/********************************/
+/* completion functions */
+
+/*
+ * does tilde expansion of strings of type ``~user/foo''
+ * if ``user'' isn't valid user name or ``txt'' doesn't start
+ * w/ '~', returns pointer to strdup()ed copy of ``txt''
+ *
+ * it's callers's responsibility to free() returned string
+ */
+char *
+fn_tilde_expand(const char *txt)
+{
+#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
+       struct passwd pwres;
+       char pwbuf[1024];
+#endif
+       struct passwd *pass;
+       char *temp;
+       size_t len = 0;
+
+       if (txt[0] != '~')
+               return strdup(txt);
+
+       temp = strchr(txt + 1, '/');
+       if (temp == NULL) {
+               temp = strdup(txt + 1);
+               if (temp == NULL)
+                       return NULL;
+       } else {
+               /* text until string after slash */
+               len = (size_t)(temp - txt + 1);
+               temp = el_malloc(len * sizeof(*temp));
+               if (temp == NULL)
+                       return NULL;
+               (void)strncpy(temp, txt + 1, len - 2);
+               temp[len - 2] = '\0';
+       }
+       if (temp[0] == 0) {
+#ifdef HAVE_GETPW_R_POSIX
+               if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
+                   &pass) != 0)
+                       pass = NULL;
+#elif HAVE_GETPW_R_DRAFT
+               pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf));
+#else
+               pass = getpwuid(getuid());
+#endif
+       } else {
+#ifdef HAVE_GETPW_R_POSIX
+               if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+                       pass = NULL;
+#elif HAVE_GETPW_R_DRAFT
+               pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf));
+#else
+               pass = getpwnam(temp);
+#endif
+       }
+       el_free(temp);          /* value no more needed */
+       if (pass == NULL)
+               return strdup(txt);
+
+       /* update pointer txt to point at string immedially following */
+       /* first slash */
+       txt += len;
+
+       len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
+       temp = el_malloc(len * sizeof(*temp));
+       if (temp == NULL)
+               return NULL;
+       (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt);
+
+       return temp;
+}
+
+
+/*
+ * return first found file name starting by the ``text'' or NULL if no
+ * such file can be found
+ * value of ``state'' is ignored
+ *
+ * it's caller's responsibility to free returned string
+ */
+char *
+fn_filename_completion_function(const char *text, int state)
+{
+       static DIR *dir = NULL;
+       static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
+       static size_t filename_len = 0;
+       struct dirent *entry;
+       char *temp;
+       size_t len;
+
+       if (state == 0 || dir == NULL) {
+               temp = strrchr(text, '/');
+               if (temp) {
+                       char *nptr;
+                       temp++;
+                       nptr = el_realloc(filename, (strlen(temp) + 1) *
+                           sizeof(*nptr));
+                       if (nptr == NULL) {
+                               el_free(filename);
+                               filename = NULL;
+                               return NULL;
+                       }
+                       filename = nptr;
+                       (void)strcpy(filename, temp);
+                       len = (size_t)(temp - text);    /* including last slash */
+
+                       nptr = el_realloc(dirname, (len + 1) *
+                           sizeof(*nptr));
+                       if (nptr == NULL) {
+                               el_free(dirname);
+                               dirname = NULL;
+                               return NULL;
+                       }
+                       dirname = nptr;
+                       (void)strncpy(dirname, text, len);
+                       dirname[len] = '\0';
+               } else {
+                       el_free(filename);
+                       if (*text == 0)
+                               filename = NULL;
+                       else {
+                               filename = strdup(text);
+                               if (filename == NULL)
+                                       return NULL;
+                       }
+                       el_free(dirname);
+                       dirname = NULL;
+               }
+
+               if (dir != NULL) {
+                       (void)closedir(dir);
+                       dir = NULL;
+               }
+
+               /* support for ``~user'' syntax */
+
+               el_free(dirpath);
+               dirpath = NULL;
+               if (dirname == NULL) {
+                       if ((dirname = strdup("")) == NULL)
+                               return NULL;
+                       dirpath = strdup("./");
+               } else if (*dirname == '~')
+                       dirpath = fn_tilde_expand(dirname);
+               else
+                       dirpath = strdup(dirname);
+
+               if (dirpath == NULL)
+                       return NULL;
+
+               dir = opendir(dirpath);
+               if (!dir)
+                       return NULL;    /* cannot open the directory */
+
+               /* will be used in cycle */
+               filename_len = filename ? strlen(filename) : 0;
+       }
+
+       /* find the match */
+       while ((entry = readdir(dir)) != NULL) {
+               /* skip . and .. */
+               if (entry->d_name[0] == '.' && (!entry->d_name[1]
+                   || (entry->d_name[1] == '.' && !entry->d_name[2])))
+                       continue;
+               if (filename_len == 0)
+                       break;
+               /* otherwise, get first entry where first */
+               /* filename_len characters are equal      */
+               if (entry->d_name[0] == filename[0]
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
+                   && entry->d_namlen >= filename_len
+#else
+                   && strlen(entry->d_name) >= filename_len
+#endif
+                   && strncmp(entry->d_name, filename,
+                       filename_len) == 0)
+                       break;
+       }
+
+       if (entry) {            /* match found */
+
+#if HAVE_STRUCT_DIRENT_D_NAMLEN
+               len = entry->d_namlen;
+#else
+               len = strlen(entry->d_name);
+#endif
+
+               len = strlen(dirname) + len + 1;
+               temp = el_malloc(len * sizeof(*temp));
+               if (temp == NULL)
+                       return NULL;
+               (void)snprintf(temp, len, "%s%s", dirname, entry->d_name);
+       } else {
+               (void)closedir(dir);
+               dir = NULL;
+               temp = NULL;
+       }
+
+       return temp;
+}
+
+
+static const char *
+append_char_function(const char *name)
+{
+       struct stat stbuf;
+       char *expname = *name == '~' ? fn_tilde_expand(name) : NULL;
+       const char *rs = " ";
+
+       if (stat(expname ? expname : name, &stbuf) == -1)
+               goto out;
+       if (S_ISDIR(stbuf.st_mode))
+               rs = "/";
+out:
+       if (expname)
+               el_free(expname);
+       return rs;
+}
+/*
+ * returns list of completions for text given
+ * non-static for readline.
+ */
+char ** completion_matches(const char *, char *(*)(const char *, int));
+char **
+completion_matches(const char *text, char *(*genfunc)(const char *, int))
+{
+       char **match_list = NULL, *retstr, *prevstr;
+       size_t match_list_len, max_equal, which, i;
+       size_t matches;
+
+       matches = 0;
+       match_list_len = 1;
+       while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
+               /* allow for list terminator here */
+               if (matches + 3 >= match_list_len) {
+                       char **nmatch_list;
+                       while (matches + 3 >= match_list_len)
+                               match_list_len <<= 1;
+                       nmatch_list = el_realloc(match_list,
+                           match_list_len * sizeof(*nmatch_list));
+                       if (nmatch_list == NULL) {
+                               el_free(match_list);
+                               return NULL;
+                       }
+                       match_list = nmatch_list;
+
+               }
+               match_list[++matches] = retstr;
+       }
+
+       if (!match_list)
+               return NULL;    /* nothing found */
+
+       /* find least denominator and insert it to match_list[0] */
+       which = 2;
+       prevstr = match_list[1];
+       max_equal = strlen(prevstr);
+       for (; which <= matches; which++) {
+               for (i = 0; i < max_equal &&
+                   prevstr[i] == match_list[which][i]; i++)
+                       continue;
+               max_equal = i;
+       }
+
+       retstr = el_malloc((max_equal + 1) * sizeof(*retstr));
+       if (retstr == NULL) {
+               el_free(match_list);
+               return NULL;
+       }
+       (void)strncpy(retstr, match_list[1], max_equal);
+       retstr[max_equal] = '\0';
+       match_list[0] = retstr;
+
+       /* add NULL as last pointer to the array */
+       match_list[matches + 1] = NULL;
+
+       return match_list;
+}
+
+/*
+ * Sort function for qsort(). Just wrapper around strcasecmp().
+ */
+static int
+_fn_qsort_string_compare(const void *i1, const void *i2)
+{
+       const char *s1 = ((const char * const *)i1)[0];
+       const char *s2 = ((const char * const *)i2)[0];
+
+       return strcasecmp(s1, s2);
+}
+
+/*
+ * Display list of strings in columnar format on readline's output stream.
+ * 'matches' is list of strings, 'num' is number of strings in 'matches',
+ * 'width' is maximum length of string in 'matches'.
+ *
+ * matches[0] is not one of the match strings, but it is counted in
+ * num, so the strings are matches[1] *through* matches[num-1].
+ */
+void
+fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width)
+{
+       size_t line, lines, col, cols, thisguy;
+       int screenwidth = el->el_terminal.t_size.h;
+
+       /* Ignore matches[0]. Avoid 1-based array logic below. */
+       matches++;
+       num--;
+
+       /*
+        * Find out how many entries can be put on one line; count
+        * with one space between strings the same way it's printed.
+        */
+       cols = (size_t)screenwidth / (width + 1);
+       if (cols == 0)
+               cols = 1;
+
+       /* how many lines of output, rounded up */
+       lines = (num + cols - 1) / cols;
+
+       /* Sort the items. */
+       qsort(matches, num, sizeof(char *), _fn_qsort_string_compare);
+
+       /*
+        * On the ith line print elements i, i+lines, i+lines*2, etc.
+        */
+       for (line = 0; line < lines; line++) {
+               for (col = 0; col < cols; col++) {
+                       thisguy = line + col * lines;
+                       if (thisguy >= num)
+                               break;
+                       (void)fprintf(el->el_outfile, "%s%-*s",
+                           col == 0 ? "" : " ", (int)width, matches[thisguy]);
+               }
+               (void)fprintf(el->el_outfile, "\n");
+       }
+}
+
+/*
+ * Complete the word at or before point,
+ * 'what_to_do' says what to do with the completion.
+ * \t   means do standard completion.
+ * `?' means list the possible completions.
+ * `*' means insert all of the possible completions.
+ * `!' means to do standard completion, and list all possible completions if
+ * there is more than one.
+ *
+ * Note: '*' support is not implemented
+ *       '!' could never be invoked
+ */
+int
+fn_complete(EditLine *el,
+       char *(*complet_func)(const char *, int),
+       char **(*attempted_completion_function)(const char *, int, int),
+       const Char *word_break, const Char *special_prefixes,
+       const char *(*app_func)(const char *), size_t query_items,
+       int *completion_type, int *over, int *point, int *end)
+{
+       const TYPE(LineInfo) *li;
+       Char *temp;
+        char **matches;
+       const Char *ctemp;
+       size_t len;
+       int what_to_do = '\t';
+       int retval = CC_NORM;
+
+       if (el->el_state.lastcmd == el->el_state.thiscmd)
+               what_to_do = '?';
+
+       /* readline's rl_complete() has to be told what we did... */
+       if (completion_type != NULL)
+               *completion_type = what_to_do;
+
+       if (!complet_func)
+               complet_func = fn_filename_completion_function;
+       if (!app_func)
+               app_func = append_char_function;
+
+       /* We now look backwards for the start of a filename/variable word */
+       li = FUN(el,line)(el);
+       ctemp = li->cursor;
+       while (ctemp > li->buffer
+           && !Strchr(word_break, ctemp[-1])
+           && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
+               ctemp--;
+
+       len = (size_t)(li->cursor - ctemp);
+       temp = el_malloc((len + 1) * sizeof(*temp));
+       (void)Strncpy(temp, ctemp, len);
+       temp[len] = '\0';
+
+       /* these can be used by function called in completion_matches() */
+       /* or (*attempted_completion_function)() */
+       if (point != 0)
+               *point = (int)(li->cursor - li->buffer);
+       if (end != NULL)
+               *end = (int)(li->lastchar - li->buffer);
+
+       if (attempted_completion_function) {
+               int cur_off = (int)(li->cursor - li->buffer);
+               matches = (*attempted_completion_function)(
+                   ct_encode_string(temp, &el->el_scratch),
+                   cur_off - (int)len, cur_off);
+       } else
+               matches = 0;
+       if (!attempted_completion_function || 
+           (over != NULL && !*over && !matches))
+               matches = completion_matches(
+                   ct_encode_string(temp, &el->el_scratch), complet_func);
+
+       if (over != NULL)
+               *over = 0;
+
+       if (matches) {
+               int i;
+               size_t matches_num, maxlen, match_len, match_display=1;
+
+               retval = CC_REFRESH;
+               /*
+                * Only replace the completed string with common part of
+                * possible matches if there is possible completion.
+                */
+               if (matches[0][0] != '\0') {
+                       el_deletestr(el, (int) len);
+                       FUN(el,insertstr)(el,
+                           ct_decode_string(matches[0], &el->el_scratch));
+               }
+
+               if (what_to_do == '?')
+                       goto display_matches;
+
+               if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+                       /*
+                        * We found exact match. Add a space after
+                        * it, unless we do filename completion and the
+                        * object is a directory.
+                        */
+                       FUN(el,insertstr)(el,
+                           ct_decode_string((*app_func)(matches[0]),
+                           &el->el_scratch));
+               } else if (what_to_do == '!') {
+    display_matches:
+                       /*
+                        * More than one match and requested to list possible
+                        * matches.
+                        */
+
+                       for(i = 1, maxlen = 0; matches[i]; i++) {
+                               match_len = strlen(matches[i]);
+                               if (match_len > maxlen)
+                                       maxlen = match_len;
+                       }
+                       /* matches[1] through matches[i-1] are available */
+                       matches_num = (size_t)(i - 1);
+                               
+                       /* newline to get on next line from command line */
+                       (void)fprintf(el->el_outfile, "\n");
+
+                       /*
+                        * If there are too many items, ask user for display
+                        * confirmation.
+                        */
+                       if (matches_num > query_items) {
+                               (void)fprintf(el->el_outfile,
+                                   "Display all %zu possibilities? (y or n) ",
+                                   matches_num);
+                               (void)fflush(el->el_outfile);
+                               if (getc(stdin) != 'y')
+                                       match_display = 0;
+                               (void)fprintf(el->el_outfile, "\n");
+                       }
+
+                       if (match_display) {
+                               /*
+                                * Interface of this function requires the
+                                * strings be matches[1..num-1] for compat.
+                                * We have matches_num strings not counting
+                                * the prefix in matches[0], so we need to
+                                * add 1 to matches_num for the call.
+                                */
+                               fn_display_match_list(el, matches,
+                                   matches_num+1, maxlen);
+                       }
+                       retval = CC_REDISPLAY;
+               } else if (matches[0][0]) {
+                       /*
+                        * There was some common match, but the name was
+                        * not complete enough. Next tab will print possible
+                        * completions.
+                        */
+                       el_beep(el);
+               } else {
+                       /* lcd is not a valid object - further specification */
+                       /* is needed */
+                       el_beep(el);
+                       retval = CC_NORM;
+               }
+
+               /* free elements of array and the array itself */
+               for (i = 0; matches[i]; i++)
+                       el_free(matches[i]);
+               el_free(matches);
+               matches = NULL;
+       }
+       el_free(temp);
+       return retval;
+}
+
+/*
+ * el-compatible wrapper around rl_complete; needed for key binding
+ */
+/* ARGSUSED */
+unsigned char
+_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
+{
+       return (unsigned char)fn_complete(el, NULL, NULL,
+           break_chars, NULL, NULL, (size_t)100,
+           NULL, NULL, NULL, NULL);
+}
diff --git a/lib/libedit/filecomplete.h b/lib/libedit/filecomplete.h
new file mode 100644 (file)
index 0000000..971e6e0
--- /dev/null
@@ -0,0 +1,44 @@
+/*     $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $        */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _FILECOMPLETE_H_
+#define _FILECOMPLETE_H_
+
+int fn_complete(EditLine *,
+    char *(*)(const char *, int),
+    char **(*)(const char *, int, int),
+    const Char *, const Char *, const char *(*)(const char *), size_t,
+    int *, int *, int *, int *);
+
+void fn_display_match_list(EditLine *, char **, size_t, size_t);
+char *fn_tilde_expand(const char *);
+char *fn_filename_completion_function(const char *, int);
+
+#endif
diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c
new file mode 100644 (file)
index 0000000..77dbaab
--- /dev/null
@@ -0,0 +1,223 @@
+/*     $NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)hist.c     8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * hist.c: History access functions
+ */
+#include <stdlib.h>
+#include "el.h"
+
+/* hist_init():
+ *     Initialization function.
+ */
+protected int
+hist_init(EditLine *el)
+{
+
+       el->el_history.fun = NULL;
+       el->el_history.ref = NULL;
+       el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf));
+       el->el_history.sz  = EL_BUFSIZ;
+       if (el->el_history.buf == NULL)
+               return -1;
+       el->el_history.last = el->el_history.buf;
+       return 0;
+}
+
+
+/* hist_end():
+ *     clean up history;
+ */
+protected void
+hist_end(EditLine *el)
+{
+
+       el_free(el->el_history.buf);
+       el->el_history.buf = NULL;
+}
+
+
+/* hist_set():
+ *     Set new history interface
+ */
+protected int
+hist_set(EditLine *el, hist_fun_t fun, void *ptr)
+{
+
+       el->el_history.ref = ptr;
+       el->el_history.fun = fun;
+       return 0;
+}
+
+
+/* hist_get():
+ *     Get a history line and update it in the buffer.
+ *     eventno tells us the event to get.
+ */
+protected el_action_t
+hist_get(EditLine *el)
+{
+       const Char *hp;
+       int h;
+
+       if (el->el_history.eventno == 0) {      /* if really the current line */
+               (void) Strncpy(el->el_line.buffer, el->el_history.buf,
+                   el->el_history.sz);
+               el->el_line.lastchar = el->el_line.buffer +
+                   (el->el_history.last - el->el_history.buf);
+
+#ifdef KSHVI
+               if (el->el_map.type == MAP_VI)
+                       el->el_line.cursor = el->el_line.buffer;
+               else
+#endif /* KSHVI */
+                       el->el_line.cursor = el->el_line.lastchar;
+
+               return CC_REFRESH;
+       }
+       if (el->el_history.ref == NULL)
+               return CC_ERROR;
+
+       hp = HIST_FIRST(el);
+
+       if (hp == NULL)
+               return CC_ERROR;
+
+       for (h = 1; h < el->el_history.eventno; h++)
+               if ((hp = HIST_NEXT(el)) == NULL) {
+                       el->el_history.eventno = h;
+                       return CC_ERROR;
+               }
+       (void) Strncpy(el->el_line.buffer, hp,
+                       (size_t)(el->el_line.limit - el->el_line.buffer));
+       el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0';
+       el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer);
+
+       if (el->el_line.lastchar > el->el_line.buffer
+           && el->el_line.lastchar[-1] == '\n')
+               el->el_line.lastchar--;
+       if (el->el_line.lastchar > el->el_line.buffer
+           && el->el_line.lastchar[-1] == ' ')
+               el->el_line.lastchar--;
+#ifdef KSHVI
+       if (el->el_map.type == MAP_VI)
+               el->el_line.cursor = el->el_line.buffer;
+       else
+#endif /* KSHVI */
+               el->el_line.cursor = el->el_line.lastchar;
+
+       return CC_REFRESH;
+}
+
+
+/* hist_command()
+ *     process a history command
+ */
+protected int
+hist_command(EditLine *el, int argc, const Char **argv)
+{
+       const Char *str;
+       int num;
+       TYPE(HistEvent) ev;
+
+       if (el->el_history.ref == NULL)
+               return -1;
+
+       if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) {
+                /* List history entries */
+
+               for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
+                       (void) fprintf(el->el_outfile, "%d %s",
+                           el->el_history.ev.num, ct_encode_string(str, &el->el_scratch));
+               return 0;
+       }
+
+       if (argc != 3)
+               return -1;
+
+       num = (int)Strtol(argv[2], NULL, 0);
+
+       if (Strcmp(argv[1], STR("size")) == 0)
+               return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num);
+
+       if (Strcmp(argv[1], STR("unique")) == 0)
+               return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num);
+
+       return -1;
+}
+
+/* hist_enlargebuf()
+ *     Enlarge history buffer to specified value. Called from el_enlargebufs().
+ *     Return 0 for failure, 1 for success.
+ */
+protected int
+/*ARGSUSED*/
+hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
+{
+       Char *newbuf;
+
+       newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
+       if (!newbuf)
+               return 0;
+
+       (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf));
+
+       el->el_history.last = newbuf +
+                               (el->el_history.last - el->el_history.buf);
+       el->el_history.buf = newbuf;
+       el->el_history.sz  = newsz;
+
+       return 1;
+}
+
+#ifdef WIDECHAR
+protected wchar_t *
+hist_convert(EditLine *el, int fn, void *arg)
+{
+       HistEventW ev;
+       if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1)
+               return NULL;
+       return ct_decode_string((const char *)(const void *)ev.str,
+           &el->el_scratch);
+}
+#endif
diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h
new file mode 100644 (file)
index 0000000..a63be49
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD: hist.h,v 1.13 2011/07/28 20:50:55 christos Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)hist.h      8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.hist.c: History functions
+ */
+#ifndef _h_el_hist
+#define        _h_el_hist
+
+#include "histedit.h"
+
+typedef int (*hist_fun_t)(void *, TYPE(HistEvent) *, int, ...);
+
+typedef struct el_history_t {
+       Char            *buf;           /* The history buffer           */
+       size_t          sz;             /* Size of history buffer       */
+       Char            *last;          /* The last character           */
+       int              eventno;       /* Event we are looking for     */
+       void *           ref;           /* Argument for history fcns    */
+       hist_fun_t       fun;           /* Event access                 */
+       TYPE(HistEvent)  ev;            /* Event cookie                 */
+} el_history_t;
+
+#define        HIST_FUN_INTERNAL(el, fn, arg)  \
+    ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
+       fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
+#ifdef WIDECHAR
+#define HIST_FUN(el, fn, arg) \
+    (((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \
+       HIST_FUN_INTERNAL(el, fn, arg))
+#else
+#define HIST_FUN(el, fn, arg) HIST_FUN_INTERNAL(el, fn, arg)
+#endif
+
+
+#define        HIST_NEXT(el)           HIST_FUN(el, H_NEXT, NULL)
+#define        HIST_FIRST(el)          HIST_FUN(el, H_FIRST, NULL)
+#define        HIST_LAST(el)           HIST_FUN(el, H_LAST, NULL)
+#define        HIST_PREV(el)           HIST_FUN(el, H_PREV, NULL)
+#define        HIST_SET(el, num)       HIST_FUN(el, H_SET, num)
+#define        HIST_LOAD(el, fname)    HIST_FUN(el, H_LOAD fname)
+#define        HIST_SAVE(el, fname)    HIST_FUN(el, H_SAVE fname)
+
+protected int          hist_init(EditLine *);
+protected void         hist_end(EditLine *);
+protected el_action_t  hist_get(EditLine *);
+protected int          hist_set(EditLine *, hist_fun_t, void *);
+protected int          hist_command(EditLine *, int, const Char **);
+protected int          hist_enlargebuf(EditLine *, size_t, size_t);
+#ifdef WIDECHAR
+protected wchar_t      *hist_convert(EditLine *, int, void *);
+#endif
+
+#endif /* _h_el_hist */
diff --git a/lib/libedit/histedit.h b/lib/libedit/histedit.h
new file mode 100644 (file)
index 0000000..61f9875
--- /dev/null
@@ -0,0 +1,317 @@
+/*     $NetBSD: histedit.h,v 1.49 2012/05/31 13:16:39 christos Exp $   */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)histedit.h  8.2 (Berkeley) 1/3/94
+ */
+
+/*
+ * histedit.h: Line editor and history interface.
+ */
+#ifndef _HISTEDIT_H_
+#define        _HISTEDIT_H_
+
+#define        LIBEDIT_MAJOR 2
+#define        LIBEDIT_MINOR 11
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ==== Editing ====
+ */
+
+typedef struct editline EditLine;
+
+/*
+ * For user-defined function interface
+ */
+typedef struct lineinfo {
+       const char      *buffer;
+       const char      *cursor;
+       const char      *lastchar;
+} LineInfo;
+
+/*
+ * EditLine editor function return codes.
+ * For user-defined function interface
+ */
+#define        CC_NORM         0
+#define        CC_NEWLINE      1
+#define        CC_EOF          2
+#define        CC_ARGHACK      3
+#define        CC_REFRESH      4
+#define        CC_CURSOR       5
+#define        CC_ERROR        6
+#define        CC_FATAL        7
+#define        CC_REDISPLAY    8
+#define        CC_REFRESH_BEEP 9
+
+/*
+ * Initialization, cleanup, and resetting
+ */
+EditLine       *el_init(const char *, FILE *, FILE *, FILE *);
+void            el_end(EditLine *);
+void            el_reset(EditLine *);
+
+/*
+ * Get a line, a character or push a string back in the input queue
+ */
+const char     *el_gets(EditLine *, int *);
+int             el_getc(EditLine *, char *);
+void            el_push(EditLine *, const char *);
+
+/*
+ * Beep!
+ */
+void            el_beep(EditLine *);
+
+/*
+ * High level function internals control
+ * Parses argc, argv array and executes builtin editline commands
+ */
+int             el_parse(EditLine *, int, const char **);
+
+/*
+ * Low level editline access functions
+ */
+int             el_set(EditLine *, int, ...);
+int             el_get(EditLine *, int, ...);
+unsigned char  _el_fn_complete(EditLine *, int);
+
+/*
+ * el_set/el_get parameters
+ *
+ * When using el_wset/el_wget (as opposed to el_set/el_get):
+ *   Char is wchar_t, otherwise it is char.
+ *   prompt_func is el_wpfunc_t, otherwise it is el_pfunc_t .
+
+ * Prompt function prototypes are:
+ *   typedef char    *(*el_pfunct_t)  (EditLine *);
+ *   typedef wchar_t *(*el_wpfunct_t) (EditLine *);
+ *
+ * For operations that support set or set/get, the argument types listed are for
+ * the "set" operation. For "get", each listed type must be a pointer.
+ * E.g. EL_EDITMODE takes an int when set, but an int* when get.
+ * 
+ * Operations that only support "get" have the correct argument types listed.
+ */
+#define        EL_PROMPT       0       /* , prompt_func);                    set/get */
+#define        EL_TERMINAL     1       /* , const char *);                   set/get */
+#define        EL_EDITOR       2       /* , const Char *);                   set/get */
+#define        EL_SIGNAL       3       /* , int);                            set/get */
+#define        EL_BIND         4       /* , const Char *, ..., NULL);        set     */
+#define        EL_TELLTC       5       /* , const Char *, ..., NULL);        set     */
+#define        EL_SETTC        6       /* , const Char *, ..., NULL);        set     */
+#define        EL_ECHOTC       7       /* , const Char *, ..., NULL);        set     */
+#define        EL_SETTY        8       /* , const Char *, ..., NULL);        set     */
+#define        EL_ADDFN        9       /* , const Char *, const Char,        set     */
+                               /*   el_func_t);                              */
+#define        EL_HIST         10      /* , hist_fun_t, const void *);       set     */
+#define        EL_EDITMODE     11      /* , int);                            set/get */
+#define        EL_RPROMPT      12      /* , prompt_func);                    set/get */
+#define        EL_GETCFN       13      /* , el_rfunc_t);                     set/get */
+#define        EL_CLIENTDATA   14      /* , void *);                         set/get */
+#define        EL_UNBUFFERED   15      /* , int);                            set/get */
+#define        EL_PREP_TERM    16      /* , int);                            set     */
+#define        EL_GETTC        17      /* , const Char *, ..., NULL);            get */
+#define        EL_GETFP        18      /* , int, FILE **);                       get */
+#define        EL_SETFP        19      /* , int, FILE *);                    set     */
+#define        EL_REFRESH      20      /* , void);                           set     */
+#define        EL_PROMPT_ESC   21      /* , prompt_func, Char);              set/get */
+#define        EL_RPROMPT_ESC  22      /* , prompt_func, Char);              set/get */
+#define        EL_RESIZE       23      /* , el_zfunc_t, void *);             set     */
+
+#define        EL_BUILTIN_GETCFN       (NULL)
+
+/*
+ * Source named file or $PWD/.editrc or $HOME/.editrc
+ */
+int            el_source(EditLine *, const char *);
+
+/*
+ * Must be called when the terminal changes size; If EL_SIGNAL
+ * is set this is done automatically otherwise it is the responsibility
+ * of the application
+ */
+void            el_resize(EditLine *);
+
+/*
+ * User-defined function interface.
+ */
+const LineInfo *el_line(EditLine *);
+int             el_insertstr(EditLine *, const char *);
+void            el_deletestr(EditLine *, int);
+
+
+/*
+ * ==== History ====
+ */
+
+typedef struct history History;
+
+typedef struct HistEvent {
+       int              num;
+       const char      *str;
+} HistEvent;
+
+/*
+ * History access functions.
+ */
+History *      history_init(void);
+void           history_end(History *);
+
+int            history(History *, HistEvent *, int, ...);
+
+#define        H_FUNC           0      /* , UTSL               */
+#define        H_SETSIZE        1      /* , const int);        */
+#define        H_GETSIZE        2      /* , void);             */
+#define        H_FIRST          3      /* , void);             */
+#define        H_LAST           4      /* , void);             */
+#define        H_PREV           5      /* , void);             */
+#define        H_NEXT           6      /* , void);             */
+#define        H_CURR           8      /* , const int);        */
+#define        H_SET            7      /* , int);              */
+#define        H_ADD            9      /* , const wchar_t *);  */
+#define        H_ENTER         10      /* , const wchar_t *);  */
+#define        H_APPEND        11      /* , const wchar_t *);  */
+#define        H_END           12      /* , void);             */
+#define        H_NEXT_STR      13      /* , const wchar_t *);  */
+#define        H_PREV_STR      14      /* , const wchar_t *);  */
+#define        H_NEXT_EVENT    15      /* , const int);        */
+#define        H_PREV_EVENT    16      /* , const int);        */
+#define        H_LOAD          17      /* , const char *);     */
+#define        H_SAVE          18      /* , const char *);     */
+#define        H_CLEAR         19      /* , void);             */
+#define        H_SETUNIQUE     20      /* , int);              */
+#define        H_GETUNIQUE     21      /* , void);             */
+#define        H_DEL           22      /* , int);              */
+#define        H_NEXT_EVDATA   23      /* , const int, histdata_t *);  */
+#define        H_DELDATA       24      /* , int, histdata_t *);*/
+#define        H_REPLACE       25      /* , const char *, histdata_t); */
+
+
+
+/*
+ * ==== Tokenization ====
+ */
+
+typedef struct tokenizer Tokenizer;
+
+/*
+ * String tokenization functions, using simplified sh(1) quoting rules
+ */
+Tokenizer      *tok_init(const char *);
+void            tok_end(Tokenizer *);
+void            tok_reset(Tokenizer *);
+int             tok_line(Tokenizer *, const LineInfo *,
+                   int *, const char ***, int *, int *);
+int             tok_str(Tokenizer *, const char *,
+                   int *, const char ***);
+
+/*
+ * Begin Wide Character Support
+ */
+#ifdef __linux__
+/* Apparently we need _GNU_SOURCE defined to get access to wcsdup on Linux */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#endif
+
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Wide character versions
+ */
+
+/*
+ * ==== Editing ====
+ */
+typedef struct lineinfow {
+       const wchar_t   *buffer;
+       const wchar_t   *cursor;
+       const wchar_t   *lastchar;
+} LineInfoW;
+
+const wchar_t  *el_wgets(EditLine *, int *);
+int             el_wgetc(EditLine *, wchar_t *);
+void            el_wpush(EditLine *, const wchar_t *);
+
+int             el_wparse(EditLine *, int, const wchar_t **);
+
+int             el_wset(EditLine *, int, ...);
+int             el_wget(EditLine *, int, ...);
+
+const LineInfoW        *el_wline(EditLine *);
+int             el_winsertstr(EditLine *, const wchar_t *);
+#define          el_wdeletestr  el_deletestr
+
+/*
+ * ==== History ====
+ */
+typedef struct histeventW {
+       int              num;
+       const wchar_t   *str;
+} HistEventW;
+
+typedef struct historyW HistoryW;
+
+HistoryW *     history_winit(void);
+void           history_wend(HistoryW *);
+
+int            history_w(HistoryW *, HistEventW *, int, ...);
+
+/*
+ * ==== Tokenization ====
+ */
+typedef struct tokenizerW TokenizerW;
+
+/* Wide character tokenizer support */
+TokenizerW     *tok_winit(const wchar_t *);
+void            tok_wend(TokenizerW *);
+void            tok_wreset(TokenizerW *);
+int             tok_wline(TokenizerW *, const LineInfoW *,
+                   int *, const wchar_t ***, int *, int *);
+int             tok_wstr(TokenizerW *, const wchar_t *,
+                   int *, const wchar_t ***);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HISTEDIT_H_ */
diff --git a/lib/libedit/history.c b/lib/libedit/history.c
new file mode 100644 (file)
index 0000000..7e8f520
--- /dev/null
@@ -0,0 +1,1100 @@
+/*     $NetBSD: history.c,v 1.46 2011/11/18 20:39:18 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)history.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: history.c,v 1.46 2011/11/18 20:39:18 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * hist.c: TYPE(History) access functions
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <vis.h>
+#include <sys/stat.h>
+
+static const char hist_cookie[] = "_HiStOrY_V2_\n";
+
+#include "histedit.h"
+#include "chartype.h"
+
+typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
+typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
+typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
+typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
+
+struct TYPE(history) {
+       void *h_ref;            /* Argument for history fcns     */
+       int h_ent;              /* Last entry point for history  */
+       history_gfun_t h_first; /* Get the first element         */
+       history_gfun_t h_next;  /* Get the next element          */
+       history_gfun_t h_last;  /* Get the last element          */
+       history_gfun_t h_prev;  /* Get the previous element      */
+       history_gfun_t h_curr;  /* Get the current element       */
+       history_sfun_t h_set;   /* Set the current element       */
+       history_sfun_t h_del;   /* Set the given element         */
+       history_vfun_t h_clear; /* Clear the history list        */
+       history_efun_t h_enter; /* Add an element                */
+       history_efun_t h_add;   /* Append to an element          */
+};
+
+#define        HNEXT(h, ev)            (*(h)->h_next)((h)->h_ref, ev)
+#define        HFIRST(h, ev)           (*(h)->h_first)((h)->h_ref, ev)
+#define        HPREV(h, ev)            (*(h)->h_prev)((h)->h_ref, ev)
+#define        HLAST(h, ev)            (*(h)->h_last)((h)->h_ref, ev)
+#define        HCURR(h, ev)            (*(h)->h_curr)((h)->h_ref, ev)
+#define        HSET(h, ev, n)          (*(h)->h_set)((h)->h_ref, ev, n)
+#define        HCLEAR(h, ev)           (*(h)->h_clear)((h)->h_ref, ev)
+#define        HENTER(h, ev, str)      (*(h)->h_enter)((h)->h_ref, ev, str)
+#define        HADD(h, ev, str)        (*(h)->h_add)((h)->h_ref, ev, str)
+#define        HDEL(h, ev, n)          (*(h)->h_del)((h)->h_ref, ev, n)
+
+#define        h_strdup(a)     Strdup(a)
+#define        h_malloc(a)     malloc(a)
+#define        h_realloc(a, b) realloc((a), (b))
+#define        h_free(a)       free(a)
+
+typedef struct {
+    int                num;
+    Char       *str;
+} HistEventPrivate;
+
+
+
+private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
+private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
+private int history_set_fun(TYPE(History) *, TYPE(History) *);
+private int history_load(TYPE(History) *, const char *);
+private int history_save(TYPE(History) *, const char *);
+private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
+private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
+
+
+/***********************************************************************/
+
+/*
+ * Builtin- history implementation
+ */
+typedef struct hentry_t {
+       TYPE(HistEvent) ev;             /* What we return                */
+       void *data;             /* data                          */
+       struct hentry_t *next;  /* Next entry                    */
+       struct hentry_t *prev;  /* Previous entry                */
+} hentry_t;
+
+typedef struct history_t {
+       hentry_t list;          /* Fake list header element     */
+       hentry_t *cursor;       /* Current element in the list  */
+       int max;                /* Maximum number of events     */
+       int cur;                /* Current number of events     */
+       int eventid;            /* For generation of unique event id     */
+       int flags;              /* TYPE(History) flags          */
+#define H_UNIQUE       1       /* Store only unique elements   */
+} history_t;
+
+private int history_def_next(void *, TYPE(HistEvent) *);
+private int history_def_first(void *, TYPE(HistEvent) *);
+private int history_def_prev(void *, TYPE(HistEvent) *);
+private int history_def_last(void *, TYPE(HistEvent) *);
+private int history_def_curr(void *, TYPE(HistEvent) *);
+private int history_def_set(void *, TYPE(HistEvent) *, const int);
+private void history_def_clear(void *, TYPE(HistEvent) *);
+private int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
+private int history_def_add(void *, TYPE(HistEvent) *, const Char *);
+private int history_def_del(void *, TYPE(HistEvent) *, const int);
+
+private int history_def_init(void **, TYPE(HistEvent) *, int);
+private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
+private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
+
+private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
+private int history_set_nth(void *, TYPE(HistEvent) *, int);
+
+#define        history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
+#define        history_def_getsize(p)  (((history_t *)p)->cur)
+#define        history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
+#define        history_def_setunique(p, uni) \
+    if (uni) \
+       (((history_t *)p)->flags) |= H_UNIQUE; \
+    else \
+       (((history_t *)p)->flags) &= ~H_UNIQUE
+
+#define        he_strerror(code)       he_errlist[code]
+#define        he_seterrev(evp, code)  {\
+                                   evp->num = code;\
+                                   evp->str = he_strerror(code);\
+                               }
+
+/* error messages */
+static const Char *const he_errlist[] = {
+       STR("OK"),
+       STR("unknown error"),
+       STR("malloc() failed"),
+       STR("first event not found"),
+       STR("last event not found"),
+       STR("empty list"),
+       STR("no next event"),
+       STR("no previous event"),
+       STR("current event is invalid"),
+       STR("event not found"),
+       STR("can't read history from file"),
+       STR("can't write history"),
+       STR("required parameter(s) not supplied"),
+       STR("history size negative"),
+       STR("function not allowed with other history-functions-set the default"),
+       STR("bad parameters")
+};
+/* error codes */
+#define        _HE_OK                   0
+#define        _HE_UNKNOWN              1
+#define        _HE_MALLOC_FAILED        2
+#define        _HE_FIRST_NOTFOUND       3
+#define        _HE_LAST_NOTFOUND        4
+#define        _HE_EMPTY_LIST           5
+#define        _HE_END_REACHED          6
+#define        _HE_START_REACHED        7
+#define        _HE_CURR_INVALID         8
+#define        _HE_NOT_FOUND            9
+#define        _HE_HIST_READ           10
+#define        _HE_HIST_WRITE          11
+#define        _HE_PARAM_MISSING       12
+#define        _HE_SIZE_NEGATIVE       13
+#define        _HE_NOT_ALLOWED         14
+#define        _HE_BAD_PARAM           15
+
+/* history_def_first():
+ *     Default function to return the first event in the history.
+ */
+private int
+history_def_first(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       h->cursor = h->list.next;
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev, _HE_FIRST_NOTFOUND);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* history_def_last():
+ *     Default function to return the last event in the history.
+ */
+private int
+history_def_last(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       h->cursor = h->list.prev;
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev, _HE_LAST_NOTFOUND);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* history_def_next():
+ *     Default function to return the next event in the history.
+ */
+private int
+history_def_next(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return -1;
+       }
+
+       if (h->cursor->next == &h->list) {
+               he_seterrev(ev, _HE_END_REACHED);
+               return -1;
+       }
+
+        h->cursor = h->cursor->next;
+        *ev = h->cursor->ev;
+
+       return 0;
+}
+
+
+/* history_def_prev():
+ *     Default function to return the previous event in the history.
+ */
+private int
+history_def_prev(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cursor == &h->list) {
+               he_seterrev(ev,
+                   (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
+               return -1;
+       }
+
+       if (h->cursor->prev == &h->list) {
+               he_seterrev(ev, _HE_START_REACHED);
+               return -1;
+       }
+
+        h->cursor = h->cursor->prev;
+        *ev = h->cursor->ev;
+
+       return 0;
+}
+
+
+/* history_def_curr():
+ *     Default function to return the current event in the history.
+ */
+private int
+history_def_curr(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev,
+                   (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* history_def_set():
+ *     Default function to set the current event in the history to the
+ *     given one.
+ */
+private int
+history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cur == 0) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return -1;
+       }
+       if (h->cursor == &h->list || h->cursor->ev.num != n) {
+               for (h->cursor = h->list.next; h->cursor != &h->list;
+                   h->cursor = h->cursor->next)
+                       if (h->cursor->ev.num == n)
+                               break;
+       }
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_NOT_FOUND);
+               return -1;
+       }
+       return 0;
+}
+
+
+/* history_set_nth():
+ *     Default function to set the current event in the history to the
+ *     n-th one.
+ */
+private int
+history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cur == 0) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return -1;
+       }
+       for (h->cursor = h->list.prev; h->cursor != &h->list;
+           h->cursor = h->cursor->prev)
+               if (n-- <= 0)
+                       break;
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_NOT_FOUND);
+               return -1;
+       }
+       return 0;
+}
+
+
+/* history_def_add():
+ *     Append string to element
+ */
+private int
+history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
+{
+       history_t *h = (history_t *) p;
+       size_t len;
+       Char *s;
+       HistEventPrivate *evp = (void *)&h->cursor->ev;
+
+       if (h->cursor == &h->list)
+               return history_def_enter(p, ev, str);
+       len = Strlen(evp->str) + Strlen(str) + 1;
+       s = h_malloc(len * sizeof(*s));
+       if (s == NULL) {
+               he_seterrev(ev, _HE_MALLOC_FAILED);
+               return -1;
+       }
+       (void) Strncpy(s, h->cursor->ev.str, len);
+        s[len - 1] = '\0';
+       (void) Strncat(s, str, len - Strlen(s) - 1);
+       h_free(evp->str);
+       evp->str = s;
+       *ev = h->cursor->ev;
+       return 0;
+}
+
+
+private int
+history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
+    int num, void **data)
+{
+       if (history_set_nth(h, ev, num) != 0)
+               return -1;
+       /* magic value to skip delete (just set to n-th history) */
+       if (data == (void **)-1)
+               return 0;
+       ev->str = Strdup(h->cursor->ev.str);
+       ev->num = h->cursor->ev.num;
+       if (data)
+               *data = h->cursor->data;
+       history_def_delete(h, ev, h->cursor);
+       return 0;
+}
+
+
+/* history_def_del():
+ *     Delete element hp of the h list
+ */
+/* ARGSUSED */
+private int
+history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
+    const int num)
+{
+       history_t *h = (history_t *) p;
+       if (history_def_set(h, ev, num) != 0)
+               return -1;
+       ev->str = Strdup(h->cursor->ev.str);
+       ev->num = h->cursor->ev.num;
+       history_def_delete(h, ev, h->cursor);
+       return 0;
+}
+
+
+/* history_def_delete():
+ *     Delete element hp of the h list
+ */
+/* ARGSUSED */
+private void
+history_def_delete(history_t *h, 
+                  TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
+{
+       HistEventPrivate *evp = (void *)&hp->ev;
+       if (hp == &h->list)
+               abort();
+       if (h->cursor == hp) {
+               h->cursor = hp->prev;
+               if (h->cursor == &h->list)
+                       h->cursor = hp->next;
+       }
+       hp->prev->next = hp->next;
+       hp->next->prev = hp->prev;
+       h_free(evp->str);
+       h_free(hp);
+       h->cur--;
+}
+
+
+/* history_def_insert():
+ *     Insert element with string str in the h list
+ */
+private int
+history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
+{
+       hentry_t *c;
+
+       c = h_malloc(sizeof(*c));
+       if (c == NULL)
+               goto oomem;
+       if ((c->ev.str = h_strdup(str)) == NULL) {
+               h_free(c);
+               goto oomem;
+       }
+       c->data = NULL;
+       c->ev.num = ++h->eventid;
+       c->next = h->list.next;
+       c->prev = &h->list;
+       h->list.next->prev = c;
+       h->list.next = c;
+       h->cur++;
+       h->cursor = c;
+
+       *ev = c->ev;
+       return 0;
+oomem:
+       he_seterrev(ev, _HE_MALLOC_FAILED);
+       return -1;
+}
+
+
+/* history_def_enter():
+ *     Default function to enter an item in the history
+ */
+private int
+history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
+{
+       history_t *h = (history_t *) p;
+
+       if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
+           Strcmp(h->list.next->ev.str, str) == 0)
+           return 0;
+
+       if (history_def_insert(h, ev, str) == -1)
+               return -1;      /* error, keep error message */
+
+       /*
+         * Always keep at least one entry.
+         * This way we don't have to check for the empty list.
+         */
+       while (h->cur > h->max && h->cur > 0)
+               history_def_delete(h, ev, h->list.prev);
+
+       return 1;
+}
+
+
+/* history_def_init():
+ *     Default history initialization function
+ */
+/* ARGSUSED */
+private int
+history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
+{
+       history_t *h = (history_t *) h_malloc(sizeof(*h));
+       if (h == NULL)
+               return -1;
+
+       if (n <= 0)
+               n = 0;
+       h->eventid = 0;
+       h->cur = 0;
+       h->max = n;
+       h->list.next = h->list.prev = &h->list;
+       h->list.ev.str = NULL;
+       h->list.ev.num = 0;
+       h->cursor = &h->list;
+       h->flags = 0;
+       *p = h;
+       return 0;
+}
+
+
+/* history_def_clear():
+ *     Default history cleanup function
+ */
+private void
+history_def_clear(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       while (h->list.prev != &h->list)
+               history_def_delete(h, ev, h->list.prev);
+       h->cursor = &h->list;
+       h->eventid = 0;
+       h->cur = 0;
+}
+
+
+
+
+/************************************************************************/
+
+/* history_init():
+ *     Initialization function.
+ */
+public TYPE(History) *
+FUN(history,init)(void)
+{
+       TYPE(HistEvent) ev;
+       TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
+       if (h == NULL)
+               return NULL;
+
+       if (history_def_init(&h->h_ref, &ev, 0) == -1) {
+               h_free(h);
+               return NULL;
+       }
+       h->h_ent = -1;
+       h->h_next = history_def_next;
+       h->h_first = history_def_first;
+       h->h_last = history_def_last;
+       h->h_prev = history_def_prev;
+       h->h_curr = history_def_curr;
+       h->h_set = history_def_set;
+       h->h_clear = history_def_clear;
+       h->h_enter = history_def_enter;
+       h->h_add = history_def_add;
+       h->h_del = history_def_del;
+
+       return h;
+}
+
+
+/* history_end():
+ *     clean up history;
+ */
+public void
+FUN(history,end)(TYPE(History) *h)
+{
+       TYPE(HistEvent) ev;
+
+       if (h->h_next == history_def_next)
+               history_def_clear(h->h_ref, &ev);
+       h_free(h->h_ref);
+       h_free(h);
+}
+
+
+
+/* history_setsize():
+ *     Set history number of events
+ */
+private int
+history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
+{
+
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return -1;
+       }
+       if (num < 0) {
+               he_seterrev(ev, _HE_BAD_PARAM);
+               return -1;
+       }
+       history_def_setsize(h->h_ref, num);
+       return 0;
+}
+
+
+/* history_getsize():
+ *      Get number of events currently in history
+ */
+private int
+history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
+{
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return -1;
+       }
+       ev->num = history_def_getsize(h->h_ref);
+       if (ev->num < -1) {
+               he_seterrev(ev, _HE_SIZE_NEGATIVE);
+               return -1;
+       }
+       return 0;
+}
+
+
+/* history_setunique():
+ *     Set if adjacent equal events should not be entered in history.
+ */
+private int
+history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
+{
+
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return -1;
+       }
+       history_def_setunique(h->h_ref, uni);
+       return 0;
+}
+
+
+/* history_getunique():
+ *     Get if adjacent equal events should not be entered in history.
+ */
+private int
+history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
+{
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return -1;
+       }
+       ev->num = history_def_getunique(h->h_ref);
+       return 0;
+}
+
+
+/* history_set_fun():
+ *     Set history functions
+ */
+private int
+history_set_fun(TYPE(History) *h, TYPE(History) *nh)
+{
+       TYPE(HistEvent) ev;
+
+       if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
+           nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
+           nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
+           nh->h_del == NULL || nh->h_ref == NULL) {
+               if (h->h_next != history_def_next) {
+                       if (history_def_init(&h->h_ref, &ev, 0) == -1)
+                               return -1;
+                       h->h_first = history_def_first;
+                       h->h_next = history_def_next;
+                       h->h_last = history_def_last;
+                       h->h_prev = history_def_prev;
+                       h->h_curr = history_def_curr;
+                       h->h_set = history_def_set;
+                       h->h_clear = history_def_clear;
+                       h->h_enter = history_def_enter;
+                       h->h_add = history_def_add;
+                       h->h_del = history_def_del;
+               }
+               return -1;
+       }
+       if (h->h_next == history_def_next)
+               history_def_clear(h->h_ref, &ev);
+
+       h->h_ent = -1;
+       h->h_first = nh->h_first;
+       h->h_next = nh->h_next;
+       h->h_last = nh->h_last;
+       h->h_prev = nh->h_prev;
+       h->h_curr = nh->h_curr;
+       h->h_set = nh->h_set;
+       h->h_clear = nh->h_clear;
+       h->h_enter = nh->h_enter;
+       h->h_add = nh->h_add;
+       h->h_del = nh->h_del;
+
+       return 0;
+}
+
+
+/* history_load():
+ *     TYPE(History) load function
+ */
+private int
+history_load(TYPE(History) *h, const char *fname)
+{
+       FILE *fp;
+       char *line;
+       size_t sz, max_size;
+       char *ptr;
+       int i = -1;
+       TYPE(HistEvent) ev;
+#ifdef WIDECHAR
+       static ct_buffer_t conv;
+#endif
+
+       if ((fp = fopen(fname, "r")) == NULL)
+               return i;
+
+       if ((line = fgetln(fp, &sz)) == NULL)
+               goto done;
+
+       if (strncmp(line, hist_cookie, sz) != 0)
+               goto done;
+
+       ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
+       if (ptr == NULL)
+               goto done;
+       for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
+               char c = line[sz];
+
+               if (sz != 0 && line[sz - 1] == '\n')
+                       line[--sz] = '\0';
+               else
+                       line[sz] = '\0';
+
+               if (max_size < sz) {
+                       char *nptr;
+                       max_size = (sz + 1024) & (size_t)~1023;
+                       nptr = h_realloc(ptr, max_size * sizeof(*ptr));
+                       if (nptr == NULL) {
+                               i = -1;
+                               goto oomem;
+                       }
+                       ptr = nptr;
+               }
+               (void) strunvis(ptr, line);
+               line[sz] = c;
+               if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
+                       i = -1;
+                       goto oomem;
+               }
+       }
+oomem:
+       h_free(ptr);
+done:
+       (void) fclose(fp);
+       return i;
+}
+
+
+/* history_save():
+ *     TYPE(History) save function
+ */
+private int
+history_save(TYPE(History) *h, const char *fname)
+{
+       FILE *fp;
+       TYPE(HistEvent) ev;
+       int i = -1, retval;
+       size_t len, max_size;
+       char *ptr;
+       const char *str;
+#ifdef WIDECHAR
+       static ct_buffer_t conv;
+#endif
+
+       if ((fp = fopen(fname, "w")) == NULL)
+               return -1;
+
+       if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
+               goto done;
+       if (fputs(hist_cookie, fp) == EOF)
+               goto done;
+       ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
+       if (ptr == NULL)
+               goto done;
+       for (i = 0, retval = HLAST(h, &ev);
+           retval != -1;
+           retval = HPREV(h, &ev), i++) {
+               str = ct_encode_string(ev.str, &conv);
+               len = strlen(str) * 4;
+               if (len >= max_size) {
+                       char *nptr;
+                       max_size = (len + 1024) & (size_t)~1023;
+                       nptr = h_realloc(ptr, max_size * sizeof(*ptr));
+                       if (nptr == NULL) {
+                               i = -1;
+                               goto oomem;
+                       }
+                       ptr = nptr;
+               }
+               (void) strvis(ptr, str, VIS_WHITE);
+               (void) fprintf(fp, "%s\n", ptr);
+       }
+oomem:
+       h_free(ptr);
+done:
+       (void) fclose(fp);
+       return i;
+}
+
+
+/* history_prev_event():
+ *     Find the previous event, with number given
+ */
+private int
+history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
+{
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (ev->num == num)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+private int
+history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
+{
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (ev->num == num) {
+                       if (d)
+                               *d = ((history_t *)h->h_ref)->cursor->data;
+                       return 0;
+               }
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history_next_event():
+ *     Find the next event, with number given
+ */
+private int
+history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
+{
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+               if (ev->num == num)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history_prev_string():
+ *     Find the previous event beginning with string
+ */
+private int
+history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
+{
+       size_t len = Strlen(str);
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+               if (Strncmp(str, ev->str, len) == 0)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history_next_string():
+ *     Find the next event beginning with string
+ */
+private int
+history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
+{
+       size_t len = Strlen(str);
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (Strncmp(str, ev->str, len) == 0)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history():
+ *     User interface to history functions.
+ */
+int
+FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
+{
+       va_list va;
+       const Char *str;
+       int retval;
+
+       va_start(va, fun);
+
+       he_seterrev(ev, _HE_OK);
+
+       switch (fun) {
+       case H_GETSIZE:
+               retval = history_getsize(h, ev);
+               break;
+
+       case H_SETSIZE:
+               retval = history_setsize(h, ev, va_arg(va, int));
+               break;
+
+       case H_GETUNIQUE:
+               retval = history_getunique(h, ev);
+               break;
+
+       case H_SETUNIQUE:
+               retval = history_setunique(h, ev, va_arg(va, int));
+               break;
+
+       case H_ADD:
+               str = va_arg(va, const Char *);
+               retval = HADD(h, ev, str);
+               break;
+
+       case H_DEL:
+               retval = HDEL(h, ev, va_arg(va, const int));
+               break;
+
+       case H_ENTER:
+               str = va_arg(va, const Char *);
+               if ((retval = HENTER(h, ev, str)) != -1)
+                       h->h_ent = ev->num;
+               break;
+
+       case H_APPEND:
+               str = va_arg(va, const Char *);
+               if ((retval = HSET(h, ev, h->h_ent)) != -1)
+                       retval = HADD(h, ev, str);
+               break;
+
+       case H_FIRST:
+               retval = HFIRST(h, ev);
+               break;
+
+       case H_NEXT:
+               retval = HNEXT(h, ev);
+               break;
+
+       case H_LAST:
+               retval = HLAST(h, ev);
+               break;
+
+       case H_PREV:
+               retval = HPREV(h, ev);
+               break;
+
+       case H_CURR:
+               retval = HCURR(h, ev);
+               break;
+
+       case H_SET:
+               retval = HSET(h, ev, va_arg(va, const int));
+               break;
+
+       case H_CLEAR:
+               HCLEAR(h, ev);
+               retval = 0;
+               break;
+
+       case H_LOAD:
+               retval = history_load(h, va_arg(va, const char *));
+               if (retval == -1)
+                       he_seterrev(ev, _HE_HIST_READ);
+               break;
+
+       case H_SAVE:
+               retval = history_save(h, va_arg(va, const char *));
+               if (retval == -1)
+                       he_seterrev(ev, _HE_HIST_WRITE);
+               break;
+
+       case H_PREV_EVENT:
+               retval = history_prev_event(h, ev, va_arg(va, int));
+               break;
+
+       case H_NEXT_EVENT:
+               retval = history_next_event(h, ev, va_arg(va, int));
+               break;
+
+       case H_PREV_STR:
+               retval = history_prev_string(h, ev, va_arg(va, const Char *));
+               break;
+
+       case H_NEXT_STR:
+               retval = history_next_string(h, ev, va_arg(va, const Char *));
+               break;
+
+       case H_FUNC:
+       {
+               TYPE(History) hf;
+
+               hf.h_ref = va_arg(va, void *);
+               h->h_ent = -1;
+               hf.h_first = va_arg(va, history_gfun_t);
+               hf.h_next = va_arg(va, history_gfun_t);
+               hf.h_last = va_arg(va, history_gfun_t);
+               hf.h_prev = va_arg(va, history_gfun_t);
+               hf.h_curr = va_arg(va, history_gfun_t);
+               hf.h_set = va_arg(va, history_sfun_t);
+               hf.h_clear = va_arg(va, history_vfun_t);
+               hf.h_enter = va_arg(va, history_efun_t);
+               hf.h_add = va_arg(va, history_efun_t);
+               hf.h_del = va_arg(va, history_sfun_t);
+
+               if ((retval = history_set_fun(h, &hf)) == -1)
+                       he_seterrev(ev, _HE_PARAM_MISSING);
+               break;
+       }
+
+       case H_END:
+               FUN(history,end)(h);
+               retval = 0;
+               break;
+
+       case H_NEXT_EVDATA:
+       {
+               int num = va_arg(va, int);
+               void **d = va_arg(va, void **);
+               retval = history_next_evdata(h, ev, num, d);
+               break;
+       }
+
+       case H_DELDATA:
+       {
+               int num = va_arg(va, int);
+               void **d = va_arg(va, void **);
+               retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
+               break;
+       }
+
+       case H_REPLACE: /* only use after H_NEXT_EVDATA */
+       {
+               const Char *line = va_arg(va, const Char *);
+               void *d = va_arg(va, void *);
+               const Char *s;
+               if(!line || !(s = Strdup(line))) {
+                       retval = -1;
+                       break;
+               }
+               ((history_t *)h->h_ref)->cursor->ev.str = s;
+               ((history_t *)h->h_ref)->cursor->data = d;
+               retval = 0;
+               break;
+       }
+
+       default:
+               retval = -1;
+               he_seterrev(ev, _HE_UNKNOWN);
+               break;
+       }
+       va_end(va);
+       return retval;
+}
diff --git a/lib/libedit/keymacro.c b/lib/libedit/keymacro.c
new file mode 100644 (file)
index 0000000..1cab508
--- /dev/null
@@ -0,0 +1,671 @@
+/*     $NetBSD: keymacro.c,v 1.7 2011/08/16 16:25:15 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)key.c      8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: keymacro.c,v 1.7 2011/08/16 16:25:15 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * keymacro.c: This module contains the procedures for maintaining
+ *            the extended-key map.
+ *
+ *      An extended-key (key) is a sequence of keystrokes introduced
+ *     with a sequence introducer and consisting of an arbitrary
+ *     number of characters.  This module maintains a map (the
+ *     el->el_keymacro.map)
+ *     to convert these extended-key sequences into input strs
+ *     (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
+ *
+ *      Warning:
+ *       If key is a substr of some other keys, then the longer
+ *       keys are lost!!  That is, if the keys "abcd" and "abcef"
+ *       are in el->el_keymacro.map, adding the key "abc" will cause
+ *       the first two definitions to be lost.
+ *
+ *      Restrictions:
+ *      -------------
+ *      1) It is not possible to have one key that is a
+ *        substr of another.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "el.h"
+
+/*
+ * The Nodes of the el->el_keymacro.map.  The el->el_keymacro.map is a
+ * linked list of these node elements
+ */
+struct keymacro_node_t {
+       Char             ch;            /* single character of key       */
+       int              type;          /* node type                     */
+       keymacro_value_t val;           /* command code or pointer to str,  */
+                                       /* if this is a leaf             */
+       struct keymacro_node_t *next;   /* ptr to next char of this key  */
+       struct keymacro_node_t *sibling;/* ptr to another key with same prefix*/
+};
+
+private int             node_trav(EditLine *, keymacro_node_t *, Char *,
+    keymacro_value_t *);
+private int             node__try(EditLine *, keymacro_node_t *, const Char *,
+    keymacro_value_t *, int);
+private keymacro_node_t        *node__get(Int);
+private void            node__free(keymacro_node_t *);
+private void            node__put(EditLine *, keymacro_node_t *);
+private int             node__delete(EditLine *, keymacro_node_t **,
+    const Char *);
+private int             node_lookup(EditLine *, const Char *,
+    keymacro_node_t *, size_t);
+private int             node_enum(EditLine *, keymacro_node_t *, size_t);
+
+#define        KEY_BUFSIZ      EL_BUFSIZ
+
+
+/* keymacro_init():
+ *     Initialize the key maps
+ */
+protected int
+keymacro_init(EditLine *el)
+{
+
+       el->el_keymacro.buf = el_malloc(KEY_BUFSIZ *
+           sizeof(*el->el_keymacro.buf));
+       if (el->el_keymacro.buf == NULL)
+               return -1;
+       el->el_keymacro.map = NULL;
+       keymacro_reset(el);
+       return 0;
+}
+
+/* keymacro_end():
+ *     Free the key maps
+ */
+protected void
+keymacro_end(EditLine *el)
+{
+
+       el_free(el->el_keymacro.buf);
+       el->el_keymacro.buf = NULL;
+       node__free(el->el_keymacro.map);
+}
+
+
+/* keymacro_map_cmd():
+ *     Associate cmd with a key value
+ */
+protected keymacro_value_t *
+keymacro_map_cmd(EditLine *el, int cmd)
+{
+
+       el->el_keymacro.val.cmd = (el_action_t) cmd;
+       return &el->el_keymacro.val;
+}
+
+
+/* keymacro_map_str():
+ *     Associate str with a key value
+ */
+protected keymacro_value_t *
+keymacro_map_str(EditLine *el, Char *str)
+{
+
+       el->el_keymacro.val.str = str;
+       return &el->el_keymacro.val;
+}
+
+
+/* keymacro_reset():
+ *     Takes all nodes on el->el_keymacro.map and puts them on free list.
+ *     Then initializes el->el_keymacro.map with arrow keys
+ *     [Always bind the ansi arrow keys?]
+ */
+protected void
+keymacro_reset(EditLine *el)
+{
+
+       node__put(el, el->el_keymacro.map);
+       el->el_keymacro.map = NULL;
+       return;
+}
+
+
+/* keymacro_get():
+ *     Calls the recursive function with entry point el->el_keymacro.map
+ *      Looks up *ch in map and then reads characters until a
+ *      complete match is found or a mismatch occurs. Returns the
+ *      type of the match found (XK_STR, XK_CMD, or XK_EXE).
+ *      Returns NULL in val.str and XK_STR for no match.
+ *      The last character read is returned in *ch.
+ */
+protected int
+keymacro_get(EditLine *el, Char *ch, keymacro_value_t *val)
+{
+
+       return node_trav(el, el->el_keymacro.map, ch, val);
+}
+
+
+/* keymacro_add():
+ *      Adds key to the el->el_keymacro.map and associates the value in
+ *     val with it. If key is already is in el->el_keymacro.map, the new
+ *     code is applied to the existing key. Ntype specifies if code is a
+ *     command, an out str or a unix command.
+ */
+protected void
+keymacro_add(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
+{
+
+       if (key[0] == '\0') {
+               (void) fprintf(el->el_errfile,
+                   "keymacro_add: Null extended-key not allowed.\n");
+               return;
+       }
+       if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) {
+               (void) fprintf(el->el_errfile,
+                   "keymacro_add: sequence-lead-in command not allowed\n");
+               return;
+       }
+       if (el->el_keymacro.map == NULL)
+               /* tree is initially empty.  Set up new node to match key[0] */
+               el->el_keymacro.map = node__get(key[0]);
+                       /* it is properly initialized */
+
+       /* Now recurse through el->el_keymacro.map */
+       (void) node__try(el, el->el_keymacro.map, key, val, ntype);
+       return;
+}
+
+
+/* keymacro_clear():
+ *
+ */
+protected void
+keymacro_clear(EditLine *el, el_action_t *map, const Char *in)
+{
+#ifdef WIDECHAR
+        if (*in > N_KEYS) /* can't be in the map */
+                return;
+#endif
+       if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) &&
+           ((map == el->el_map.key &&
+           el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) ||
+           (map == el->el_map.alt &&
+           el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN)))
+               (void) keymacro_delete(el, in);
+}
+
+
+/* keymacro_delete():
+ *      Delete the key and all longer keys staring with key, if
+ *      they exists.
+ */
+protected int
+keymacro_delete(EditLine *el, const Char *key)
+{
+
+       if (key[0] == '\0') {
+               (void) fprintf(el->el_errfile,
+                   "keymacro_delete: Null extended-key not allowed.\n");
+               return -1;
+       }
+       if (el->el_keymacro.map == NULL)
+               return 0;
+
+       (void) node__delete(el, &el->el_keymacro.map, key);
+       return 0;
+}
+
+
+/* keymacro_print():
+ *     Print the binding associated with key key.
+ *     Print entire el->el_keymacro.map if null
+ */
+protected void
+keymacro_print(EditLine *el, const Char *key)
+{
+
+       /* do nothing if el->el_keymacro.map is empty and null key specified */
+       if (el->el_keymacro.map == NULL && *key == 0)
+               return;
+
+       el->el_keymacro.buf[0] = '"';
+       if (node_lookup(el, key, el->el_keymacro.map, (size_t)1) <= -1)
+               /* key is not bound */
+               (void) fprintf(el->el_errfile, "Unbound extended key \"" FSTR
+                   "\"\n", key);
+       return;
+}
+
+
+/* node_trav():
+ *     recursively traverses node in tree until match or mismatch is
+ *     found.  May read in more characters.
+ */
+private int
+node_trav(EditLine *el, keymacro_node_t *ptr, Char *ch, keymacro_value_t *val)
+{
+
+       if (ptr->ch == *ch) {
+               /* match found */
+               if (ptr->next) {
+                       /* key not complete so get next char */
+                       if (FUN(el,getc)(el, ch) != 1) {/* if EOF or error */
+                               val->cmd = ED_END_OF_FILE;
+                               return XK_CMD;
+                               /* PWP: Pretend we just read an end-of-file */
+                       }
+                       return node_trav(el, ptr->next, ch, val);
+               } else {
+                       *val = ptr->val;
+                       if (ptr->type != XK_CMD)
+                               *ch = '\0';
+                       return ptr->type;
+               }
+       } else {
+               /* no match found here */
+               if (ptr->sibling) {
+                       /* try next sibling */
+                       return node_trav(el, ptr->sibling, ch, val);
+               } else {
+                       /* no next sibling -- mismatch */
+                       val->str = NULL;
+                       return XK_STR;
+               }
+       }
+}
+
+
+/* node__try():
+ *     Find a node that matches *str or allocate a new one
+ */
+private int
+node__try(EditLine *el, keymacro_node_t *ptr, const Char *str,
+    keymacro_value_t *val, int ntype)
+{
+
+       if (ptr->ch != *str) {
+               keymacro_node_t *xm;
+
+               for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+                       if (xm->sibling->ch == *str)
+                               break;
+               if (xm->sibling == NULL)
+                       xm->sibling = node__get(*str);  /* setup new node */
+               ptr = xm->sibling;
+       }
+       if (*++str == '\0') {
+               /* we're there */
+               if (ptr->next != NULL) {
+                       node__put(el, ptr->next);
+                               /* lose longer keys with this prefix */
+                       ptr->next = NULL;
+               }
+               switch (ptr->type) {
+               case XK_CMD:
+               case XK_NOD:
+                       break;
+               case XK_STR:
+               case XK_EXE:
+                       if (ptr->val.str)
+                               el_free(ptr->val.str);
+                       break;
+               default:
+                       EL_ABORT((el->el_errfile, "Bad XK_ type %d\n",
+                           ptr->type));
+                       break;
+               }
+
+               switch (ptr->type = ntype) {
+               case XK_CMD:
+                       ptr->val = *val;
+                       break;
+               case XK_STR:
+               case XK_EXE:
+                       if ((ptr->val.str = Strdup(val->str)) == NULL)
+                               return -1;
+                       break;
+               default:
+                       EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+                       break;
+               }
+       } else {
+               /* still more chars to go */
+               if (ptr->next == NULL)
+                       ptr->next = node__get(*str);    /* setup new node */
+               (void) node__try(el, ptr->next, str, val, ntype);
+       }
+       return 0;
+}
+
+
+/* node__delete():
+ *     Delete node that matches str
+ */
+private int
+node__delete(EditLine *el, keymacro_node_t **inptr, const Char *str)
+{
+       keymacro_node_t *ptr;
+       keymacro_node_t *prev_ptr = NULL;
+
+       ptr = *inptr;
+
+       if (ptr->ch != *str) {
+               keymacro_node_t *xm;
+
+               for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+                       if (xm->sibling->ch == *str)
+                               break;
+               if (xm->sibling == NULL)
+                       return 0;
+               prev_ptr = xm;
+               ptr = xm->sibling;
+       }
+       if (*++str == '\0') {
+               /* we're there */
+               if (prev_ptr == NULL)
+                       *inptr = ptr->sibling;
+               else
+                       prev_ptr->sibling = ptr->sibling;
+               ptr->sibling = NULL;
+               node__put(el, ptr);
+               return 1;
+       } else if (ptr->next != NULL &&
+           node__delete(el, &ptr->next, str) == 1) {
+               if (ptr->next != NULL)
+                       return 0;
+               if (prev_ptr == NULL)
+                       *inptr = ptr->sibling;
+               else
+                       prev_ptr->sibling = ptr->sibling;
+               ptr->sibling = NULL;
+               node__put(el, ptr);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+
+/* node__put():
+ *     Puts a tree of nodes onto free list using free(3).
+ */
+private void
+node__put(EditLine *el, keymacro_node_t *ptr)
+{
+       if (ptr == NULL)
+               return;
+
+       if (ptr->next != NULL) {
+               node__put(el, ptr->next);
+               ptr->next = NULL;
+       }
+       node__put(el, ptr->sibling);
+
+       switch (ptr->type) {
+       case XK_CMD:
+       case XK_NOD:
+               break;
+       case XK_EXE:
+       case XK_STR:
+               if (ptr->val.str != NULL)
+                       el_free(ptr->val.str);
+               break;
+       default:
+               EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type));
+               break;
+       }
+       el_free(ptr);
+}
+
+
+/* node__get():
+ *     Returns pointer to a keymacro_node_t for ch.
+ */
+private keymacro_node_t *
+node__get(Int ch)
+{
+       keymacro_node_t *ptr;
+
+       ptr = el_malloc(sizeof(*ptr));
+       if (ptr == NULL)
+               return NULL;
+       ptr->ch = ch;
+       ptr->type = XK_NOD;
+       ptr->val.str = NULL;
+       ptr->next = NULL;
+       ptr->sibling = NULL;
+       return ptr;
+}
+
+private void
+node__free(keymacro_node_t *k)
+{
+       if (k == NULL)
+               return;
+       node__free(k->sibling);
+       node__free(k->next);
+       el_free(k);
+}
+
+/* node_lookup():
+ *     look for the str starting at node ptr.
+ *     Print if last node
+ */
+private int
+node_lookup(EditLine *el, const Char *str, keymacro_node_t *ptr, size_t cnt)
+{
+       ssize_t used;
+
+       if (ptr == NULL)
+               return -1;      /* cannot have null ptr */
+
+       if (!str || *str == 0) {
+               /* no more chars in str.  node_enum from here. */
+               (void) node_enum(el, ptr, cnt);
+               return 0;
+       } else {
+               /* If match put this char into el->el_keymacro.buf.  Recurse */
+               if (ptr->ch == *str) {
+                       /* match found */
+                       used = ct_visual_char(el->el_keymacro.buf + cnt,
+                           KEY_BUFSIZ - cnt, ptr->ch);
+                       if (used == -1)
+                               return -1; /* ran out of buffer space */
+                       if (ptr->next != NULL)
+                               /* not yet at leaf */
+                               return (node_lookup(el, str + 1, ptr->next,
+                                   (size_t)used + cnt));
+                       else {
+                           /* next node is null so key should be complete */
+                               if (str[1] == 0) {
+                                       size_t px = cnt + (size_t)used;
+                                       el->el_keymacro.buf[px] = '"';
+                                       el->el_keymacro.buf[px + 1] = '\0';
+                                       keymacro_kprint(el, el->el_keymacro.buf,
+                                           &ptr->val, ptr->type);
+                                       return 0;
+                               } else
+                                       return -1;
+                                       /* mismatch -- str still has chars */
+                       }
+               } else {
+                       /* no match found try sibling */
+                       if (ptr->sibling)
+                               return (node_lookup(el, str, ptr->sibling,
+                                   cnt));
+                       else
+                               return -1;
+               }
+       }
+}
+
+
+/* node_enum():
+ *     Traverse the node printing the characters it is bound in buffer
+ */
+private int
+node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt)
+{
+        ssize_t used;
+
+       if (cnt >= KEY_BUFSIZ - 5) {    /* buffer too small */
+               el->el_keymacro.buf[++cnt] = '"';
+               el->el_keymacro.buf[++cnt] = '\0';
+               (void) fprintf(el->el_errfile,
+                   "Some extended keys too long for internal print buffer");
+               (void) fprintf(el->el_errfile, " \"" FSTR "...\"\n",
+                   el->el_keymacro.buf);
+               return 0;
+       }
+       if (ptr == NULL) {
+#ifdef DEBUG_EDIT
+               (void) fprintf(el->el_errfile,
+                   "node_enum: BUG!! Null ptr passed\n!");
+#endif
+               return -1;
+       }
+       /* put this char at end of str */
+        used = ct_visual_char(el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt,
+           ptr->ch);
+       if (ptr->next == NULL) {
+               /* print this key and function */
+               el->el_keymacro.buf[cnt + (size_t)used   ] = '"';
+               el->el_keymacro.buf[cnt + (size_t)used + 1] = '\0';
+               keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type);
+       } else
+               (void) node_enum(el, ptr->next, cnt + (size_t)used);
+
+       /* go to sibling if there is one */
+       if (ptr->sibling)
+               (void) node_enum(el, ptr->sibling, cnt);
+       return 0;
+}
+
+
+/* keymacro_kprint():
+ *     Print the specified key and its associated
+ *     function specified by val
+ */
+protected void
+keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
+{
+       el_bindings_t *fp;
+       char unparsbuf[EL_BUFSIZ];
+       static const char fmt[] = "%-15s->  %s\n";
+
+       if (val != NULL)
+               switch (ntype) {
+               case XK_STR:
+               case XK_EXE:
+                       (void) keymacro__decode_str(val->str, unparsbuf,
+                           sizeof(unparsbuf), 
+                           ntype == XK_STR ? "\"\"" : "[]");
+                       (void) fprintf(el->el_outfile, fmt,
+                           ct_encode_string(key, &el->el_scratch), unparsbuf);
+                       break;
+               case XK_CMD:
+                       for (fp = el->el_map.help; fp->name; fp++)
+                               if (val->cmd == fp->func) {
+                    ct_wcstombs(unparsbuf, fp->name, sizeof(unparsbuf));
+                    unparsbuf[sizeof(unparsbuf) -1] = '\0';
+                                       (void) fprintf(el->el_outfile, fmt,
+                        ct_encode_string(key, &el->el_scratch), unparsbuf);
+                                       break;
+                               }
+#ifdef DEBUG_KEY
+                       if (fp->name == NULL)
+                               (void) fprintf(el->el_outfile,
+                                   "BUG! Command not found.\n");
+#endif
+
+                       break;
+               default:
+                       EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+                       break;
+               }
+       else
+               (void) fprintf(el->el_outfile, fmt, ct_encode_string(key,
+                   &el->el_scratch), "no input");
+}
+
+
+#define ADDC(c) \
+       if (b < eb) \
+               *b++ = c; \
+       else \
+               b++
+/* keymacro__decode_str():
+ *     Make a printable version of the ey
+ */
+protected size_t
+keymacro__decode_str(const Char *str, char *buf, size_t len, const char *sep)
+{
+       char *b = buf, *eb = b + len;
+       const Char *p;
+
+       b = buf;
+       if (sep[0] != '\0') {
+               ADDC(sep[0]);
+       }
+       if (*str == '\0') {
+               ADDC('^');
+               ADDC('@');
+               goto add_endsep;
+       }
+       for (p = str; *p != 0; p++) {
+               Char dbuf[VISUAL_WIDTH_MAX];
+               Char *p2 = dbuf;
+               ssize_t l = ct_visual_char(dbuf, VISUAL_WIDTH_MAX, *p);
+               while (l-- > 0) {
+                       ssize_t n = ct_encode_char(b, (size_t)(eb - b), *p2++);
+                       if (n == -1) /* ran out of space */
+                               goto add_endsep;
+                       else
+                               b += n;
+               }
+       }
+add_endsep:
+       if (sep[0] != '\0' && sep[1] != '\0') {
+               ADDC(sep[1]);
+       }
+       ADDC('\0');
+       if ((size_t)(b - buf) >= len)
+           buf[len - 1] = '\0';
+       return (size_t)(b - buf);
+}
diff --git a/lib/libedit/keymacro.h b/lib/libedit/keymacro.h
new file mode 100644 (file)
index 0000000..2445de5
--- /dev/null
@@ -0,0 +1,76 @@
+/*     $NetBSD: keymacro.h,v 1.2 2011/07/28 03:44:36 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)key.h       8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.keymacro.h: Key macro header
+ */
+#ifndef _h_el_keymacro
+#define        _h_el_keymacro
+
+typedef union keymacro_value_t {
+       el_action_t      cmd;   /* If it is a command the #     */
+       Char            *str;   /* If it is a string...         */
+} keymacro_value_t;
+
+typedef struct keymacro_node_t keymacro_node_t;
+
+typedef struct el_keymacromacro_t {
+       Char            *buf;   /* Key print buffer             */
+       keymacro_node_t *map;   /* Key map                      */
+       keymacro_value_t val;   /* Local conversion buffer      */
+} el_keymacro_t;
+
+#define        XK_CMD  0
+#define        XK_STR  1
+#define        XK_NOD  2
+#define        XK_EXE  3
+
+protected int keymacro_init(EditLine *);
+protected void keymacro_end(EditLine *);
+protected keymacro_value_t *keymacro_map_cmd(EditLine *, int);
+protected keymacro_value_t *keymacro_map_str(EditLine *, Char *);
+protected void keymacro_reset(EditLine *);
+protected int keymacro_get(EditLine *, Char *, keymacro_value_t *);
+protected void keymacro_add(EditLine *, const Char *, keymacro_value_t *, int);
+protected void keymacro_clear(EditLine *, el_action_t *, const Char *);
+protected int keymacro_delete(EditLine *, const Char *);
+protected void keymacro_print(EditLine *, const Char *);
+protected void keymacro_kprint(EditLine *, const Char *, keymacro_value_t *,
+    int);
+protected size_t keymacro__decode_str(const Char *, char *, size_t,
+    const char *);
+
+#endif /* _h_el_keymacro */
diff --git a/lib/libedit/makelist b/lib/libedit/makelist
new file mode 100644 (file)
index 0000000..588397b
--- /dev/null
@@ -0,0 +1,259 @@
+#!/bin/sh -
+#      $NetBSD: makelist,v 1.18 2012/03/21 05:34:54 matt Exp $
+#
+# Copyright (c) 1992, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Christos Zoulas of Cornell University.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#      @(#)makelist    5.3 (Berkeley) 6/4/93
+
+# makelist.sh: Automatically generate header files...
+
+AWK=awk
+USAGE="Usage: $0 -n|-h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
+
+if [ "x$1" = "x" ]
+then
+    echo $USAGE 1>&2
+    exit 1
+fi
+
+FLAG="$1"
+shift
+
+FILES="$@"
+
+case $FLAG in
+
+#      generate foo.h file from foo.c
+#
+-n)
+    cat << _EOF
+#include "config.h"
+#undef WIDECHAR
+#define NARROWCHAR
+#include "${FILES}"
+_EOF
+    ;;
+    
+-h)
+    set - `echo $FILES | sed -e 's/\\./_/g'`
+    hdr="_h_`basename $1`"
+    cat $FILES | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
+       }
+       /\(\):/ {
+           pr = substr($2, 1, 2);
+           if (pr == "vi" || pr == "em" || pr == "ed") {
+               name = substr($2, 1, length($2) - 3);
+#
+# XXX: need a space between name and prototype so that -fc and -fh
+#      parsing is much easier
+#
+               printf("protected el_action_t\t%s (EditLine *, Int);\n", name);
+           }
+       }
+       END {
+           printf("#endif /* %s */\n", "'$hdr'");
+       }'
+       ;;
+
+#      generate help.c from various .c files
+#
+-bc)
+    cat $FILES | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#include \"config.h\"\n#include \"el.h\"\n");
+           printf("#include \"chartype.h\"\n");
+           printf("private const struct el_bindings_t el_func_help[] = {\n");
+           low = "abcdefghijklmnopqrstuvwxyz_";
+           high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
+           for (i = 1; i <= length(low); i++)
+               tr[substr(low, i, 1)] = substr(high, i, 1);
+       }
+       /\(\):/ {
+           pr = substr($2, 1, 2);
+           if (pr == "vi" || pr == "em" || pr == "ed") {
+               name = substr($2, 1, length($2) - 3);
+               uname = "";
+               fname = "";
+               for (i = 1; i <= length(name); i++) {
+                   s = substr(name, i, 1);
+                   uname = uname tr[s];
+                   if (s == "_")
+                       s = "-";
+                   fname = fname s;
+               }
+
+               printf("    { %-30.30s %-30.30s\n","STR(\"" fname "\"),", uname ",");
+               ok = 1;
+           }
+       }
+       /^ \*/ {
+           if (ok) {
+               printf("      STR(\"");
+               for (i = 2; i < NF; i++)
+                   printf("%s ", $i);
+               printf("%s\") },\n", $i);
+               ok = 0;
+           }
+       }
+       END {
+           printf("};\n");
+           printf("\nprotected const el_bindings_t* help__get(void)");
+           printf("{ return el_func_help; }\n");
+       }'
+       ;;
+
+#      generate help.h from various .c files
+#
+-bh)
+    $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#ifndef _h_help_c\n#define _h_help_c\n");
+           printf("protected const el_bindings_t *help__get(void);\n");
+           printf("#endif /* _h_help_c */\n");
+       }' /dev/null
+       ;;
+
+#      generate fcns.h from various .h files
+#
+-fh)
+    cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
+    sort | tr '[:lower:]' '[:upper:]' | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
+           count = 0;
+       }
+       {
+           printf("#define\t%-30.30s\t%3d\n", $1, count++);
+       }
+       END {
+           printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
+
+           printf("typedef el_action_t (*el_func_t)(EditLine *, Int);");
+           printf("\nprotected const el_func_t* func__get(void);\n");
+           printf("#endif /* _h_fcns_c */\n");
+       }'
+       ;;
+
+#      generate fcns.c from various .h files
+#
+-fc)
+    cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#include \"config.h\"\n#include \"el.h\"\n");
+           printf("private const el_func_t el_func[] = {");
+           maxlen = 80;
+           needn = 1;
+           len = 0;
+       }
+       {
+           clen = 25 + 2;
+           len += clen;
+           if (len >= maxlen)
+               needn = 1;
+           if (needn) {
+               printf("\n    ");
+               needn = 0;
+               len = 4 + clen;
+           }
+           s = $1 ",";
+           printf("%-26.26s ", s);
+       }
+       END {
+           printf("\n};\n");
+           printf("\nprotected const el_func_t* func__get(void) { return el_func; }\n");
+       }'
+       ;;
+
+#      generate editline.c from various .c files
+#
+-e)
+       echo "$FILES" | tr ' ' '\012' | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#define protected static\n");
+           printf("#define SCCSID\n");
+       }
+       {
+           printf("#include \"%s\"\n", $1);
+       }'
+       ;;
+
+#      generate man page fragment from various .c files
+#
+-m)
+    cat $FILES | $AWK '
+       BEGIN {
+           printf(".\\\" Section automatically generated with makelist\n");
+           printf(".Bl -tag -width 4n\n");
+       }
+       /\(\):/ {
+           pr = substr($2, 1, 2);
+           if (pr == "vi" || pr == "em" || pr == "ed") {
+               name = substr($2, 1, length($2) - 3);
+               fname = "";
+               for (i = 1; i <= length(name); i++) {
+                   s = substr(name, i, 1);
+                   if (s == "_")
+                       s = "-";
+                   fname = fname s;
+               }
+
+               printf(".It Ic %s\n", fname);
+               ok = 1;
+           }
+       }
+       /^ \*/ {
+           if (ok) {
+               for (i = 2; i < NF; i++)
+                   printf("%s ", $i);
+               printf("%s.\n", $i);
+               ok = 0;
+           }
+       }
+       END {
+           printf(".El\n");
+           printf(".\\\" End of section automatically generated with makelist\n");
+       }'
+       ;;
+
+*)
+    echo $USAGE 1>&2
+    exit 1
+    ;;
+
+esac
diff --git a/lib/libedit/map.c b/lib/libedit/map.c
new file mode 100644 (file)
index 0000000..802c371
--- /dev/null
@@ -0,0 +1,1422 @@
+/*     $NetBSD: map.c,v 1.31 2011/11/18 20:39:18 christos Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)map.c      8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: map.c,v 1.31 2011/11/18 20:39:18 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * map.c: Editor function definitions
+ */
+#include <stdlib.h>
+#include "el.h"
+
+private void   map_print_key(EditLine *, el_action_t *, const Char *);
+private void   map_print_some_keys(EditLine *, el_action_t *, Int, Int);
+private void   map_print_all_keys(EditLine *);
+private void   map_init_nls(EditLine *);
+private void   map_init_meta(EditLine *);
+
+/* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */
+
+
+private const el_action_t  el_map_emacs[] = {
+       /*   0 */       EM_SET_MARK,            /* ^@ */
+       /*   1 */       ED_MOVE_TO_BEG,         /* ^A */
+       /*   2 */       ED_PREV_CHAR,           /* ^B */
+       /*   3 */       ED_TTY_SIGINT,          /* ^C */
+       /*   4 */       EM_DELETE_OR_LIST,      /* ^D */
+       /*   5 */       ED_MOVE_TO_END,         /* ^E */
+       /*   6 */       ED_NEXT_CHAR,           /* ^F */
+       /*   7 */       ED_UNASSIGNED,          /* ^G */
+       /*   8 */       EM_DELETE_PREV_CHAR,    /* ^H */
+       /*   9 */       ED_UNASSIGNED,          /* ^I */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_KILL_LINE,           /* ^K */
+       /*  12 */       ED_CLEAR_SCREEN,        /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_NEXT_HISTORY,        /* ^N */
+       /*  15 */       ED_TTY_FLUSH_OUTPUT,    /* ^O */
+       /*  16 */       ED_PREV_HISTORY,        /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_REDISPLAY,           /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_TRANSPOSE_CHARS,     /* ^T */
+       /*  21 */       EM_KILL_LINE,           /* ^U */
+       /*  22 */       ED_QUOTED_INSERT,       /* ^V */
+       /*  23 */       EM_KILL_REGION,         /* ^W */
+       /*  24 */       ED_SEQUENCE_LEAD_IN,    /* ^X */
+       /*  25 */       EM_YANK,                /* ^Y */
+       /*  26 */       ED_TTY_SIGTSTP,         /* ^Z */
+       /*  27 */       EM_META_NEXT,           /* ^[ */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_TTY_DSUSP,           /* ^] */
+       /*  30 */       ED_UNASSIGNED,          /* ^^ */
+       /*  31 */       ED_UNASSIGNED,          /* ^_ */
+       /*  32 */       ED_INSERT,              /* SPACE */
+       /*  33 */       ED_INSERT,              /* ! */
+       /*  34 */       ED_INSERT,              /* " */
+       /*  35 */       ED_INSERT,              /* # */
+       /*  36 */       ED_INSERT,              /* $ */
+       /*  37 */       ED_INSERT,              /* % */
+       /*  38 */       ED_INSERT,              /* & */
+       /*  39 */       ED_INSERT,              /* ' */
+       /*  40 */       ED_INSERT,              /* ( */
+       /*  41 */       ED_INSERT,              /* ) */
+       /*  42 */       ED_INSERT,              /* * */
+       /*  43 */       ED_INSERT,              /* + */
+       /*  44 */       ED_INSERT,              /* , */
+       /*  45 */       ED_INSERT,              /* - */
+       /*  46 */       ED_INSERT,              /* . */
+       /*  47 */       ED_INSERT,              /* / */
+       /*  48 */       ED_DIGIT,               /* 0 */
+       /*  49 */       ED_DIGIT,               /* 1 */
+       /*  50 */       ED_DIGIT,               /* 2 */
+       /*  51 */       ED_DIGIT,               /* 3 */
+       /*  52 */       ED_DIGIT,               /* 4 */
+       /*  53 */       ED_DIGIT,               /* 5 */
+       /*  54 */       ED_DIGIT,               /* 6 */
+       /*  55 */       ED_DIGIT,               /* 7 */
+       /*  56 */       ED_DIGIT,               /* 8 */
+       /*  57 */       ED_DIGIT,               /* 9 */
+       /*  58 */       ED_INSERT,              /* : */
+       /*  59 */       ED_INSERT,              /* ; */
+       /*  60 */       ED_INSERT,              /* < */
+       /*  61 */       ED_INSERT,              /* = */
+       /*  62 */       ED_INSERT,              /* > */
+       /*  63 */       ED_INSERT,              /* ? */
+       /*  64 */       ED_INSERT,              /* @ */
+       /*  65 */       ED_INSERT,              /* A */
+       /*  66 */       ED_INSERT,              /* B */
+       /*  67 */       ED_INSERT,              /* C */
+       /*  68 */       ED_INSERT,              /* D */
+       /*  69 */       ED_INSERT,              /* E */
+       /*  70 */       ED_INSERT,              /* F */
+       /*  71 */       ED_INSERT,              /* G */
+       /*  72 */       ED_INSERT,              /* H */
+       /*  73 */       ED_INSERT,              /* I */
+       /*  74 */       ED_INSERT,              /* J */
+       /*  75 */       ED_INSERT,              /* K */
+       /*  76 */       ED_INSERT,              /* L */
+       /*  77 */       ED_INSERT,              /* M */
+       /*  78 */       ED_INSERT,              /* N */
+       /*  79 */       ED_INSERT,              /* O */
+       /*  80 */       ED_INSERT,              /* P */
+       /*  81 */       ED_INSERT,              /* Q */
+       /*  82 */       ED_INSERT,              /* R */
+       /*  83 */       ED_INSERT,              /* S */
+       /*  84 */       ED_INSERT,              /* T */
+       /*  85 */       ED_INSERT,              /* U */
+       /*  86 */       ED_INSERT,              /* V */
+       /*  87 */       ED_INSERT,              /* W */
+       /*  88 */       ED_INSERT,              /* X */
+       /*  89 */       ED_INSERT,              /* Y */
+       /*  90 */       ED_INSERT,              /* Z */
+       /*  91 */       ED_INSERT,              /* [ */
+       /*  92 */       ED_INSERT,              /* \ */
+       /*  93 */       ED_INSERT,              /* ] */
+       /*  94 */       ED_INSERT,              /* ^ */
+       /*  95 */       ED_INSERT,              /* _ */
+       /*  96 */       ED_INSERT,              /* ` */
+       /*  97 */       ED_INSERT,              /* a */
+       /*  98 */       ED_INSERT,              /* b */
+       /*  99 */       ED_INSERT,              /* c */
+       /* 100 */       ED_INSERT,              /* d */
+       /* 101 */       ED_INSERT,              /* e */
+       /* 102 */       ED_INSERT,              /* f */
+       /* 103 */       ED_INSERT,              /* g */
+       /* 104 */       ED_INSERT,              /* h */
+       /* 105 */       ED_INSERT,              /* i */
+       /* 106 */       ED_INSERT,              /* j */
+       /* 107 */       ED_INSERT,              /* k */
+       /* 108 */       ED_INSERT,              /* l */
+       /* 109 */       ED_INSERT,              /* m */
+       /* 110 */       ED_INSERT,              /* n */
+       /* 111 */       ED_INSERT,              /* o */
+       /* 112 */       ED_INSERT,              /* p */
+       /* 113 */       ED_INSERT,              /* q */
+       /* 114 */       ED_INSERT,              /* r */
+       /* 115 */       ED_INSERT,              /* s */
+       /* 116 */       ED_INSERT,              /* t */
+       /* 117 */       ED_INSERT,              /* u */
+       /* 118 */       ED_INSERT,              /* v */
+       /* 119 */       ED_INSERT,              /* w */
+       /* 120 */       ED_INSERT,              /* x */
+       /* 121 */       ED_INSERT,              /* y */
+       /* 122 */       ED_INSERT,              /* z */
+       /* 123 */       ED_INSERT,              /* { */
+       /* 124 */       ED_INSERT,              /* | */
+       /* 125 */       ED_INSERT,              /* } */
+       /* 126 */       ED_INSERT,              /* ~ */
+       /* 127 */       EM_DELETE_PREV_CHAR,    /* ^? */
+       /* 128 */       ED_UNASSIGNED,          /* M-^@ */
+       /* 129 */       ED_UNASSIGNED,          /* M-^A */
+       /* 130 */       ED_UNASSIGNED,          /* M-^B */
+       /* 131 */       ED_UNASSIGNED,          /* M-^C */
+       /* 132 */       ED_UNASSIGNED,          /* M-^D */
+       /* 133 */       ED_UNASSIGNED,          /* M-^E */
+       /* 134 */       ED_UNASSIGNED,          /* M-^F */
+       /* 135 */       ED_UNASSIGNED,          /* M-^G */
+       /* 136 */       ED_DELETE_PREV_WORD,    /* M-^H */
+       /* 137 */       ED_UNASSIGNED,          /* M-^I */
+       /* 138 */       ED_UNASSIGNED,          /* M-^J */
+       /* 139 */       ED_UNASSIGNED,          /* M-^K */
+       /* 140 */       ED_CLEAR_SCREEN,        /* M-^L */
+       /* 141 */       ED_UNASSIGNED,          /* M-^M */
+       /* 142 */       ED_UNASSIGNED,          /* M-^N */
+       /* 143 */       ED_UNASSIGNED,          /* M-^O */
+       /* 144 */       ED_UNASSIGNED,          /* M-^P */
+       /* 145 */       ED_UNASSIGNED,          /* M-^Q */
+       /* 146 */       ED_UNASSIGNED,          /* M-^R */
+       /* 147 */       ED_UNASSIGNED,          /* M-^S */
+       /* 148 */       ED_UNASSIGNED,          /* M-^T */
+       /* 149 */       ED_UNASSIGNED,          /* M-^U */
+       /* 150 */       ED_UNASSIGNED,          /* M-^V */
+       /* 151 */       ED_UNASSIGNED,          /* M-^W */
+       /* 152 */       ED_UNASSIGNED,          /* M-^X */
+       /* 153 */       ED_UNASSIGNED,          /* M-^Y */
+       /* 154 */       ED_UNASSIGNED,          /* M-^Z */
+       /* 155 */       ED_UNASSIGNED,          /* M-^[ */
+       /* 156 */       ED_UNASSIGNED,          /* M-^\ */
+       /* 157 */       ED_UNASSIGNED,          /* M-^] */
+       /* 158 */       ED_UNASSIGNED,          /* M-^^ */
+       /* 159 */       EM_COPY_PREV_WORD,      /* M-^_ */
+       /* 160 */       ED_UNASSIGNED,          /* M-SPACE */
+       /* 161 */       ED_UNASSIGNED,          /* M-! */
+       /* 162 */       ED_UNASSIGNED,          /* M-" */
+       /* 163 */       ED_UNASSIGNED,          /* M-# */
+       /* 164 */       ED_UNASSIGNED,          /* M-$ */
+       /* 165 */       ED_UNASSIGNED,          /* M-% */
+       /* 166 */       ED_UNASSIGNED,          /* M-& */
+       /* 167 */       ED_UNASSIGNED,          /* M-' */
+       /* 168 */       ED_UNASSIGNED,          /* M-( */
+       /* 169 */       ED_UNASSIGNED,          /* M-) */
+       /* 170 */       ED_UNASSIGNED,          /* M-* */
+       /* 171 */       ED_UNASSIGNED,          /* M-+ */
+       /* 172 */       ED_UNASSIGNED,          /* M-, */
+       /* 173 */       ED_UNASSIGNED,          /* M-- */
+       /* 174 */       ED_UNASSIGNED,          /* M-. */
+       /* 175 */       ED_UNASSIGNED,          /* M-/ */
+       /* 176 */       ED_ARGUMENT_DIGIT,      /* M-0 */
+       /* 177 */       ED_ARGUMENT_DIGIT,      /* M-1 */
+       /* 178 */       ED_ARGUMENT_DIGIT,      /* M-2 */
+       /* 179 */       ED_ARGUMENT_DIGIT,      /* M-3 */
+       /* 180 */       ED_ARGUMENT_DIGIT,      /* M-4 */
+       /* 181 */       ED_ARGUMENT_DIGIT,      /* M-5 */
+       /* 182 */       ED_ARGUMENT_DIGIT,      /* M-6 */
+       /* 183 */       ED_ARGUMENT_DIGIT,      /* M-7 */
+       /* 184 */       ED_ARGUMENT_DIGIT,      /* M-8 */
+       /* 185 */       ED_ARGUMENT_DIGIT,      /* M-9 */
+       /* 186 */       ED_UNASSIGNED,          /* M-: */
+       /* 187 */       ED_UNASSIGNED,          /* M-; */
+       /* 188 */       ED_UNASSIGNED,          /* M-< */
+       /* 189 */       ED_UNASSIGNED,          /* M-= */
+       /* 190 */       ED_UNASSIGNED,          /* M-> */
+       /* 191 */       ED_UNASSIGNED,          /* M-? */
+       /* 192 */       ED_UNASSIGNED,          /* M-@ */
+       /* 193 */       ED_UNASSIGNED,          /* M-A */
+       /* 194 */       ED_PREV_WORD,           /* M-B */
+       /* 195 */       EM_CAPITOL_CASE,        /* M-C */
+       /* 196 */       EM_DELETE_NEXT_WORD,    /* M-D */
+       /* 197 */       ED_UNASSIGNED,          /* M-E */
+       /* 198 */       EM_NEXT_WORD,           /* M-F */
+       /* 199 */       ED_UNASSIGNED,          /* M-G */
+       /* 200 */       ED_UNASSIGNED,          /* M-H */
+       /* 201 */       ED_UNASSIGNED,          /* M-I */
+       /* 202 */       ED_UNASSIGNED,          /* M-J */
+       /* 203 */       ED_UNASSIGNED,          /* M-K */
+       /* 204 */       EM_LOWER_CASE,          /* M-L */
+       /* 205 */       ED_UNASSIGNED,          /* M-M */
+       /* 206 */       ED_SEARCH_NEXT_HISTORY, /* M-N */
+       /* 207 */       ED_SEQUENCE_LEAD_IN,    /* M-O */
+       /* 208 */       ED_SEARCH_PREV_HISTORY, /* M-P */
+       /* 209 */       ED_UNASSIGNED,          /* M-Q */
+       /* 210 */       ED_UNASSIGNED,          /* M-R */
+       /* 211 */       ED_UNASSIGNED,          /* M-S */
+       /* 212 */       ED_UNASSIGNED,          /* M-T */
+       /* 213 */       EM_UPPER_CASE,          /* M-U */
+       /* 214 */       ED_UNASSIGNED,          /* M-V */
+       /* 215 */       EM_COPY_REGION,         /* M-W */
+       /* 216 */       ED_COMMAND,             /* M-X */
+       /* 217 */       ED_UNASSIGNED,          /* M-Y */
+       /* 218 */       ED_UNASSIGNED,          /* M-Z */
+       /* 219 */       ED_SEQUENCE_LEAD_IN,    /* M-[ */
+       /* 220 */       ED_UNASSIGNED,          /* M-\ */
+       /* 221 */       ED_UNASSIGNED,          /* M-] */
+       /* 222 */       ED_UNASSIGNED,          /* M-^ */
+       /* 223 */       ED_UNASSIGNED,          /* M-_ */
+       /* 223 */       ED_UNASSIGNED,          /* M-` */
+       /* 224 */       ED_UNASSIGNED,          /* M-a */
+       /* 225 */       ED_PREV_WORD,           /* M-b */
+       /* 226 */       EM_CAPITOL_CASE,        /* M-c */
+       /* 227 */       EM_DELETE_NEXT_WORD,    /* M-d */
+       /* 228 */       ED_UNASSIGNED,          /* M-e */
+       /* 229 */       EM_NEXT_WORD,           /* M-f */
+       /* 230 */       ED_UNASSIGNED,          /* M-g */
+       /* 231 */       ED_UNASSIGNED,          /* M-h */
+       /* 232 */       ED_UNASSIGNED,          /* M-i */
+       /* 233 */       ED_UNASSIGNED,          /* M-j */
+       /* 234 */       ED_UNASSIGNED,          /* M-k */
+       /* 235 */       EM_LOWER_CASE,          /* M-l */
+       /* 236 */       ED_UNASSIGNED,          /* M-m */
+       /* 237 */       ED_SEARCH_NEXT_HISTORY, /* M-n */
+       /* 238 */       ED_UNASSIGNED,          /* M-o */
+       /* 239 */       ED_SEARCH_PREV_HISTORY, /* M-p */
+       /* 240 */       ED_UNASSIGNED,          /* M-q */
+       /* 241 */       ED_UNASSIGNED,          /* M-r */
+       /* 242 */       ED_UNASSIGNED,          /* M-s */
+       /* 243 */       ED_UNASSIGNED,          /* M-t */
+       /* 244 */       EM_UPPER_CASE,          /* M-u */
+       /* 245 */       ED_UNASSIGNED,          /* M-v */
+       /* 246 */       EM_COPY_REGION,         /* M-w */
+       /* 247 */       ED_COMMAND,             /* M-x */
+       /* 248 */       ED_UNASSIGNED,          /* M-y */
+       /* 249 */       ED_UNASSIGNED,          /* M-z */
+       /* 250 */       ED_UNASSIGNED,          /* M-{ */
+       /* 251 */       ED_UNASSIGNED,          /* M-| */
+       /* 252 */       ED_UNASSIGNED,          /* M-} */
+       /* 253 */       ED_UNASSIGNED,          /* M-~ */
+       /* 254 */       ED_DELETE_PREV_WORD     /* M-^? */
+       /* 255 */
+};
+
+
+/*
+ * keymap table for vi.  Each index into above tbl; should be
+ * N_KEYS entries long.  Vi mode uses a sticky-extend to do command mode:
+ * insert mode characters are in the normal keymap, and command mode
+ * in the extended keymap.
+ */
+private const el_action_t  el_map_vi_insert[] = {
+#ifdef KSHVI
+       /*   0 */       ED_UNASSIGNED,          /* ^@ */
+       /*   1 */       ED_INSERT,              /* ^A */
+       /*   2 */       ED_INSERT,              /* ^B */
+       /*   3 */       ED_INSERT,              /* ^C */
+       /*   4 */       VI_LIST_OR_EOF,         /* ^D */
+       /*   5 */       ED_INSERT,              /* ^E */
+       /*   6 */       ED_INSERT,              /* ^F */
+       /*   7 */       ED_INSERT,              /* ^G */
+       /*   8 */       VI_DELETE_PREV_CHAR,    /* ^H */   /* BackSpace key */
+       /*   9 */       ED_INSERT,              /* ^I */   /* Tab Key  */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_INSERT,              /* ^K */
+       /*  12 */       ED_INSERT,              /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_INSERT,              /* ^N */
+       /*  15 */       ED_INSERT,              /* ^O */
+       /*  16 */       ED_INSERT,              /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_INSERT,              /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_INSERT,              /* ^T */
+       /*  21 */       VI_KILL_LINE_PREV,      /* ^U */
+       /*  22 */       ED_QUOTED_INSERT,       /* ^V */
+       /*  23 */       ED_DELETE_PREV_WORD,    /* ^W */
+               /* ED_DELETE_PREV_WORD: Only until strt edit pos */
+       /*  24 */       ED_INSERT,              /* ^X */
+       /*  25 */       ED_INSERT,              /* ^Y */
+       /*  26 */       ED_INSERT,              /* ^Z */
+       /*  27 */       VI_COMMAND_MODE,        /* ^[ */  /* [ Esc ] key */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_INSERT,              /* ^] */
+       /*  30 */       ED_INSERT,              /* ^^ */
+       /*  31 */       ED_INSERT,              /* ^_ */
+#else /* !KSHVI */
+                               /*
+                                * NOTE: These mappings do NOT Correspond well
+                                * to the KSH VI editing assignments.
+                                * On the other and they are convenient and
+                                * many people have have gotten used to them.
+                                */
+       /*   0 */       ED_UNASSIGNED,          /* ^@ */
+       /*   1 */       ED_MOVE_TO_BEG,         /* ^A */
+       /*   2 */       ED_PREV_CHAR,           /* ^B */
+       /*   3 */       ED_TTY_SIGINT,          /* ^C */
+       /*   4 */       VI_LIST_OR_EOF,         /* ^D */
+       /*   5 */       ED_MOVE_TO_END,         /* ^E */
+       /*   6 */       ED_NEXT_CHAR,           /* ^F */
+       /*   7 */       ED_UNASSIGNED,          /* ^G */
+       /*   8 */       VI_DELETE_PREV_CHAR,    /* ^H */   /* BackSpace key */
+       /*   9 */       ED_UNASSIGNED,          /* ^I */   /* Tab Key */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_KILL_LINE,           /* ^K */
+       /*  12 */       ED_CLEAR_SCREEN,        /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_NEXT_HISTORY,        /* ^N */
+       /*  15 */       ED_TTY_FLUSH_OUTPUT,    /* ^O */
+       /*  16 */       ED_PREV_HISTORY,        /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_REDISPLAY,           /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_TRANSPOSE_CHARS,     /* ^T */
+       /*  21 */       VI_KILL_LINE_PREV,      /* ^U */
+       /*  22 */       ED_QUOTED_INSERT,       /* ^V */
+       /*  23 */       ED_DELETE_PREV_WORD,    /* ^W */
+       /*  24 */       ED_UNASSIGNED,          /* ^X */
+       /*  25 */       ED_TTY_DSUSP,           /* ^Y */
+       /*  26 */       ED_TTY_SIGTSTP,         /* ^Z */
+       /*  27 */       VI_COMMAND_MODE,        /* ^[ */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_UNASSIGNED,          /* ^] */
+       /*  30 */       ED_UNASSIGNED,          /* ^^ */
+       /*  31 */       ED_UNASSIGNED,          /* ^_ */
+#endif  /* KSHVI */
+       /*  32 */       ED_INSERT,              /* SPACE */
+       /*  33 */       ED_INSERT,              /* ! */
+       /*  34 */       ED_INSERT,              /* " */
+       /*  35 */       ED_INSERT,              /* # */
+       /*  36 */       ED_INSERT,              /* $ */
+       /*  37 */       ED_INSERT,              /* % */
+       /*  38 */       ED_INSERT,              /* & */
+       /*  39 */       ED_INSERT,              /* ' */
+       /*  40 */       ED_INSERT,              /* ( */
+       /*  41 */       ED_INSERT,              /* ) */
+       /*  42 */       ED_INSERT,              /* * */
+       /*  43 */       ED_INSERT,              /* + */
+       /*  44 */       ED_INSERT,              /* , */
+       /*  45 */       ED_INSERT,              /* - */
+       /*  46 */       ED_INSERT,              /* . */
+       /*  47 */       ED_INSERT,              /* / */
+       /*  48 */       ED_INSERT,              /* 0 */
+       /*  49 */       ED_INSERT,              /* 1 */
+       /*  50 */       ED_INSERT,              /* 2 */
+       /*  51 */       ED_INSERT,              /* 3 */
+       /*  52 */       ED_INSERT,              /* 4 */
+       /*  53 */       ED_INSERT,              /* 5 */
+       /*  54 */       ED_INSERT,              /* 6 */
+       /*  55 */       ED_INSERT,              /* 7 */
+       /*  56 */       ED_INSERT,              /* 8 */
+       /*  57 */       ED_INSERT,              /* 9 */
+       /*  58 */       ED_INSERT,              /* : */
+       /*  59 */       ED_INSERT,              /* ; */
+       /*  60 */       ED_INSERT,              /* < */
+       /*  61 */       ED_INSERT,              /* = */
+       /*  62 */       ED_INSERT,              /* > */
+       /*  63 */       ED_INSERT,              /* ? */
+       /*  64 */       ED_INSERT,              /* @ */
+       /*  65 */       ED_INSERT,              /* A */
+       /*  66 */       ED_INSERT,              /* B */
+       /*  67 */       ED_INSERT,              /* C */
+       /*  68 */       ED_INSERT,              /* D */
+       /*  69 */       ED_INSERT,              /* E */
+       /*  70 */       ED_INSERT,              /* F */
+       /*  71 */       ED_INSERT,              /* G */
+       /*  72 */       ED_INSERT,              /* H */
+       /*  73 */       ED_INSERT,              /* I */
+       /*  74 */       ED_INSERT,              /* J */
+       /*  75 */       ED_INSERT,              /* K */
+       /*  76 */       ED_INSERT,              /* L */
+       /*  77 */       ED_INSERT,              /* M */
+       /*  78 */       ED_INSERT,              /* N */
+       /*  79 */       ED_INSERT,              /* O */
+       /*  80 */       ED_INSERT,              /* P */
+       /*  81 */       ED_INSERT,              /* Q */
+       /*  82 */       ED_INSERT,              /* R */
+       /*  83 */       ED_INSERT,              /* S */
+       /*  84 */       ED_INSERT,              /* T */
+       /*  85 */       ED_INSERT,              /* U */
+       /*  86 */       ED_INSERT,              /* V */
+       /*  87 */       ED_INSERT,              /* W */
+       /*  88 */       ED_INSERT,              /* X */
+       /*  89 */       ED_INSERT,              /* Y */
+       /*  90 */       ED_INSERT,              /* Z */
+       /*  91 */       ED_INSERT,              /* [ */
+       /*  92 */       ED_INSERT,              /* \ */
+       /*  93 */       ED_INSERT,              /* ] */
+       /*  94 */       ED_INSERT,              /* ^ */
+       /*  95 */       ED_INSERT,              /* _ */
+       /*  96 */       ED_INSERT,              /* ` */
+       /*  97 */       ED_INSERT,              /* a */
+       /*  98 */       ED_INSERT,              /* b */
+       /*  99 */       ED_INSERT,              /* c */
+       /* 100 */       ED_INSERT,              /* d */
+       /* 101 */       ED_INSERT,              /* e */
+       /* 102 */       ED_INSERT,              /* f */
+       /* 103 */       ED_INSERT,              /* g */
+       /* 104 */       ED_INSERT,              /* h */
+       /* 105 */       ED_INSERT,              /* i */
+       /* 106 */       ED_INSERT,              /* j */
+       /* 107 */       ED_INSERT,              /* k */
+       /* 108 */       ED_INSERT,              /* l */
+       /* 109 */       ED_INSERT,              /* m */
+       /* 110 */       ED_INSERT,              /* n */
+       /* 111 */       ED_INSERT,              /* o */
+       /* 112 */       ED_INSERT,              /* p */
+       /* 113 */       ED_INSERT,              /* q */
+       /* 114 */       ED_INSERT,              /* r */
+       /* 115 */       ED_INSERT,              /* s */
+       /* 116 */       ED_INSERT,              /* t */
+       /* 117 */       ED_INSERT,              /* u */
+       /* 118 */       ED_INSERT,              /* v */
+       /* 119 */       ED_INSERT,              /* w */
+       /* 120 */       ED_INSERT,              /* x */
+       /* 121 */       ED_INSERT,              /* y */
+       /* 122 */       ED_INSERT,              /* z */
+       /* 123 */       ED_INSERT,              /* { */
+       /* 124 */       ED_INSERT,              /* | */
+       /* 125 */       ED_INSERT,              /* } */
+       /* 126 */       ED_INSERT,              /* ~ */
+       /* 127 */       VI_DELETE_PREV_CHAR,    /* ^? */
+       /* 128 */       ED_INSERT,              /* M-^@ */
+       /* 129 */       ED_INSERT,              /* M-^A */
+       /* 130 */       ED_INSERT,              /* M-^B */
+       /* 131 */       ED_INSERT,              /* M-^C */
+       /* 132 */       ED_INSERT,              /* M-^D */
+       /* 133 */       ED_INSERT,              /* M-^E */
+       /* 134 */       ED_INSERT,              /* M-^F */
+       /* 135 */       ED_INSERT,              /* M-^G */
+       /* 136 */       ED_INSERT,              /* M-^H */
+       /* 137 */       ED_INSERT,              /* M-^I */
+       /* 138 */       ED_INSERT,              /* M-^J */
+       /* 139 */       ED_INSERT,              /* M-^K */
+       /* 140 */       ED_INSERT,              /* M-^L */
+       /* 141 */       ED_INSERT,              /* M-^M */
+       /* 142 */       ED_INSERT,              /* M-^N */
+       /* 143 */       ED_INSERT,              /* M-^O */
+       /* 144 */       ED_INSERT,              /* M-^P */
+       /* 145 */       ED_INSERT,              /* M-^Q */
+       /* 146 */       ED_INSERT,              /* M-^R */
+       /* 147 */       ED_INSERT,              /* M-^S */
+       /* 148 */       ED_INSERT,              /* M-^T */
+       /* 149 */       ED_INSERT,              /* M-^U */
+       /* 150 */       ED_INSERT,              /* M-^V */
+       /* 151 */       ED_INSERT,              /* M-^W */
+       /* 152 */       ED_INSERT,              /* M-^X */
+       /* 153 */       ED_INSERT,              /* M-^Y */
+       /* 154 */       ED_INSERT,              /* M-^Z */
+       /* 155 */       ED_INSERT,              /* M-^[ */
+       /* 156 */       ED_INSERT,              /* M-^\ */
+       /* 157 */       ED_INSERT,              /* M-^] */
+       /* 158 */       ED_INSERT,              /* M-^^ */
+       /* 159 */       ED_INSERT,              /* M-^_ */
+       /* 160 */       ED_INSERT,              /* M-SPACE */
+       /* 161 */       ED_INSERT,              /* M-! */
+       /* 162 */       ED_INSERT,              /* M-" */
+       /* 163 */       ED_INSERT,              /* M-# */
+       /* 164 */       ED_INSERT,              /* M-$ */
+       /* 165 */       ED_INSERT,              /* M-% */
+       /* 166 */       ED_INSERT,              /* M-& */
+       /* 167 */       ED_INSERT,              /* M-' */
+       /* 168 */       ED_INSERT,              /* M-( */
+       /* 169 */       ED_INSERT,              /* M-) */
+       /* 170 */       ED_INSERT,              /* M-* */
+       /* 171 */       ED_INSERT,              /* M-+ */
+       /* 172 */       ED_INSERT,              /* M-, */
+       /* 173 */       ED_INSERT,              /* M-- */
+       /* 174 */       ED_INSERT,              /* M-. */
+       /* 175 */       ED_INSERT,              /* M-/ */
+       /* 176 */       ED_INSERT,              /* M-0 */
+       /* 177 */       ED_INSERT,              /* M-1 */
+       /* 178 */       ED_INSERT,              /* M-2 */
+       /* 179 */       ED_INSERT,              /* M-3 */
+       /* 180 */       ED_INSERT,              /* M-4 */
+       /* 181 */       ED_INSERT,              /* M-5 */
+       /* 182 */       ED_INSERT,              /* M-6 */
+       /* 183 */       ED_INSERT,              /* M-7 */
+       /* 184 */       ED_INSERT,              /* M-8 */
+       /* 185 */       ED_INSERT,              /* M-9 */
+       /* 186 */       ED_INSERT,              /* M-: */
+       /* 187 */       ED_INSERT,              /* M-; */
+       /* 188 */       ED_INSERT,              /* M-< */
+       /* 189 */       ED_INSERT,              /* M-= */
+       /* 190 */       ED_INSERT,              /* M-> */
+       /* 191 */       ED_INSERT,              /* M-? */
+       /* 192 */       ED_INSERT,              /* M-@ */
+       /* 193 */       ED_INSERT,              /* M-A */
+       /* 194 */       ED_INSERT,              /* M-B */
+       /* 195 */       ED_INSERT,              /* M-C */
+       /* 196 */       ED_INSERT,              /* M-D */
+       /* 197 */       ED_INSERT,              /* M-E */
+       /* 198 */       ED_INSERT,              /* M-F */
+       /* 199 */       ED_INSERT,              /* M-G */
+       /* 200 */       ED_INSERT,              /* M-H */
+       /* 201 */       ED_INSERT,              /* M-I */
+       /* 202 */       ED_INSERT,              /* M-J */
+       /* 203 */       ED_INSERT,              /* M-K */
+       /* 204 */       ED_INSERT,              /* M-L */
+       /* 205 */       ED_INSERT,              /* M-M */
+       /* 206 */       ED_INSERT,              /* M-N */
+       /* 207 */       ED_INSERT,              /* M-O */
+       /* 208 */       ED_INSERT,              /* M-P */
+       /* 209 */       ED_INSERT,              /* M-Q */
+       /* 210 */       ED_INSERT,              /* M-R */
+       /* 211 */       ED_INSERT,              /* M-S */
+       /* 212 */       ED_INSERT,              /* M-T */
+       /* 213 */       ED_INSERT,              /* M-U */
+       /* 214 */       ED_INSERT,              /* M-V */
+       /* 215 */       ED_INSERT,              /* M-W */
+       /* 216 */       ED_INSERT,              /* M-X */
+       /* 217 */       ED_INSERT,              /* M-Y */
+       /* 218 */       ED_INSERT,              /* M-Z */
+       /* 219 */       ED_INSERT,              /* M-[ */
+       /* 220 */       ED_INSERT,              /* M-\ */
+       /* 221 */       ED_INSERT,              /* M-] */
+       /* 222 */       ED_INSERT,              /* M-^ */
+       /* 223 */       ED_INSERT,              /* M-_ */
+       /* 224 */       ED_INSERT,              /* M-` */
+       /* 225 */       ED_INSERT,              /* M-a */
+       /* 226 */       ED_INSERT,              /* M-b */
+       /* 227 */       ED_INSERT,              /* M-c */
+       /* 228 */       ED_INSERT,              /* M-d */
+       /* 229 */       ED_INSERT,              /* M-e */
+       /* 230 */       ED_INSERT,              /* M-f */
+       /* 231 */       ED_INSERT,              /* M-g */
+       /* 232 */       ED_INSERT,              /* M-h */
+       /* 233 */       ED_INSERT,              /* M-i */
+       /* 234 */       ED_INSERT,              /* M-j */
+       /* 235 */       ED_INSERT,              /* M-k */
+       /* 236 */       ED_INSERT,              /* M-l */
+       /* 237 */       ED_INSERT,              /* M-m */
+       /* 238 */       ED_INSERT,              /* M-n */
+       /* 239 */       ED_INSERT,              /* M-o */
+       /* 240 */       ED_INSERT,              /* M-p */
+       /* 241 */       ED_INSERT,              /* M-q */
+       /* 242 */       ED_INSERT,              /* M-r */
+       /* 243 */       ED_INSERT,              /* M-s */
+       /* 244 */       ED_INSERT,              /* M-t */
+       /* 245 */       ED_INSERT,              /* M-u */
+       /* 246 */       ED_INSERT,              /* M-v */
+       /* 247 */       ED_INSERT,              /* M-w */
+       /* 248 */       ED_INSERT,              /* M-x */
+       /* 249 */       ED_INSERT,              /* M-y */
+       /* 250 */       ED_INSERT,              /* M-z */
+       /* 251 */       ED_INSERT,              /* M-{ */
+       /* 252 */       ED_INSERT,              /* M-| */
+       /* 253 */       ED_INSERT,              /* M-} */
+       /* 254 */       ED_INSERT,              /* M-~ */
+       /* 255 */       ED_INSERT               /* M-^? */
+};
+
+private const el_action_t el_map_vi_command[] = {
+       /*   0 */       ED_UNASSIGNED,          /* ^@ */
+       /*   1 */       ED_MOVE_TO_BEG,         /* ^A */
+       /*   2 */       ED_UNASSIGNED,          /* ^B */
+       /*   3 */       ED_TTY_SIGINT,          /* ^C */
+       /*   4 */       ED_UNASSIGNED,          /* ^D */
+       /*   5 */       ED_MOVE_TO_END,         /* ^E */
+       /*   6 */       ED_UNASSIGNED,          /* ^F */
+       /*   7 */       ED_UNASSIGNED,          /* ^G */
+       /*   8 */       ED_DELETE_PREV_CHAR,    /* ^H */
+       /*   9 */       ED_UNASSIGNED,          /* ^I */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_KILL_LINE,           /* ^K */
+       /*  12 */       ED_CLEAR_SCREEN,        /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_NEXT_HISTORY,        /* ^N */
+       /*  15 */       ED_TTY_FLUSH_OUTPUT,    /* ^O */
+       /*  16 */       ED_PREV_HISTORY,        /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_REDISPLAY,           /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_UNASSIGNED,          /* ^T */
+       /*  21 */       VI_KILL_LINE_PREV,      /* ^U */
+       /*  22 */       ED_UNASSIGNED,          /* ^V */
+       /*  23 */       ED_DELETE_PREV_WORD,    /* ^W */
+       /*  24 */       ED_UNASSIGNED,          /* ^X */
+       /*  25 */       ED_UNASSIGNED,          /* ^Y */
+       /*  26 */       ED_UNASSIGNED,          /* ^Z */
+       /*  27 */       EM_META_NEXT,           /* ^[ */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_UNASSIGNED,          /* ^] */
+       /*  30 */       ED_UNASSIGNED,          /* ^^ */
+       /*  31 */       ED_UNASSIGNED,          /* ^_ */
+       /*  32 */       ED_NEXT_CHAR,           /* SPACE */
+       /*  33 */       ED_UNASSIGNED,          /* ! */
+       /*  34 */       ED_UNASSIGNED,          /* " */
+       /*  35 */       VI_COMMENT_OUT,         /* # */
+       /*  36 */       ED_MOVE_TO_END,         /* $ */
+       /*  37 */       VI_MATCH,               /* % */
+       /*  38 */       ED_UNASSIGNED,          /* & */
+       /*  39 */       ED_UNASSIGNED,          /* ' */
+       /*  40 */       ED_UNASSIGNED,          /* ( */
+       /*  41 */       ED_UNASSIGNED,          /* ) */
+       /*  42 */       ED_UNASSIGNED,          /* * */
+       /*  43 */       ED_NEXT_HISTORY,        /* + */
+       /*  44 */       VI_REPEAT_PREV_CHAR,    /* , */
+       /*  45 */       ED_PREV_HISTORY,        /* - */
+       /*  46 */       VI_REDO,                /* . */
+       /*  47 */       VI_SEARCH_PREV,         /* / */
+       /*  48 */       VI_ZERO,                /* 0 */
+       /*  49 */       ED_ARGUMENT_DIGIT,      /* 1 */
+       /*  50 */       ED_ARGUMENT_DIGIT,      /* 2 */
+       /*  51 */       ED_ARGUMENT_DIGIT,      /* 3 */
+       /*  52 */       ED_ARGUMENT_DIGIT,      /* 4 */
+       /*  53 */       ED_ARGUMENT_DIGIT,      /* 5 */
+       /*  54 */       ED_ARGUMENT_DIGIT,      /* 6 */
+       /*  55 */       ED_ARGUMENT_DIGIT,      /* 7 */
+       /*  56 */       ED_ARGUMENT_DIGIT,      /* 8 */
+       /*  57 */       ED_ARGUMENT_DIGIT,      /* 9 */
+       /*  58 */       ED_COMMAND,             /* : */
+       /*  59 */       VI_REPEAT_NEXT_CHAR,    /* ; */
+       /*  60 */       ED_UNASSIGNED,          /* < */
+       /*  61 */       ED_UNASSIGNED,          /* = */
+       /*  62 */       ED_UNASSIGNED,          /* > */
+       /*  63 */       VI_SEARCH_NEXT,         /* ? */
+       /*  64 */       VI_ALIAS,               /* @ */
+       /*  65 */       VI_ADD_AT_EOL,          /* A */
+       /*  66 */       VI_PREV_BIG_WORD,       /* B */
+       /*  67 */       VI_CHANGE_TO_EOL,       /* C */
+       /*  68 */       ED_KILL_LINE,           /* D */
+       /*  69 */       VI_END_BIG_WORD,        /* E */
+       /*  70 */       VI_PREV_CHAR,           /* F */
+       /*  71 */       VI_TO_HISTORY_LINE,     /* G */
+       /*  72 */       ED_UNASSIGNED,          /* H */
+       /*  73 */       VI_INSERT_AT_BOL,       /* I */
+       /*  74 */       ED_SEARCH_NEXT_HISTORY, /* J */
+       /*  75 */       ED_SEARCH_PREV_HISTORY, /* K */
+       /*  76 */       ED_UNASSIGNED,          /* L */
+       /*  77 */       ED_UNASSIGNED,          /* M */
+       /*  78 */       VI_REPEAT_SEARCH_PREV,  /* N */
+       /*  79 */       ED_SEQUENCE_LEAD_IN,    /* O */
+       /*  80 */       VI_PASTE_PREV,          /* P */
+       /*  81 */       ED_UNASSIGNED,          /* Q */
+       /*  82 */       VI_REPLACE_MODE,        /* R */
+       /*  83 */       VI_SUBSTITUTE_LINE,     /* S */
+       /*  84 */       VI_TO_PREV_CHAR,        /* T */
+       /*  85 */       VI_UNDO_LINE,           /* U */
+       /*  86 */       ED_UNASSIGNED,          /* V */
+       /*  87 */       VI_NEXT_BIG_WORD,       /* W */
+       /*  88 */       ED_DELETE_PREV_CHAR,    /* X */
+       /*  89 */       VI_YANK_END,            /* Y */
+       /*  90 */       ED_UNASSIGNED,          /* Z */
+       /*  91 */       ED_SEQUENCE_LEAD_IN,    /* [ */
+       /*  92 */       ED_UNASSIGNED,          /* \ */
+       /*  93 */       ED_UNASSIGNED,          /* ] */
+       /*  94 */       ED_MOVE_TO_BEG,         /* ^ */
+       /*  95 */       VI_HISTORY_WORD,        /* _ */
+       /*  96 */       ED_UNASSIGNED,          /* ` */
+       /*  97 */       VI_ADD,                 /* a */
+       /*  98 */       VI_PREV_WORD,           /* b */
+       /*  99 */       VI_CHANGE_META,         /* c */
+       /* 100 */       VI_DELETE_META,         /* d */
+       /* 101 */       VI_END_WORD,            /* e */
+       /* 102 */       VI_NEXT_CHAR,           /* f */
+       /* 103 */       ED_UNASSIGNED,          /* g */
+       /* 104 */       ED_PREV_CHAR,           /* h */
+       /* 105 */       VI_INSERT,              /* i */
+       /* 106 */       ED_NEXT_HISTORY,        /* j */
+       /* 107 */       ED_PREV_HISTORY,        /* k */
+       /* 108 */       ED_NEXT_CHAR,           /* l */
+       /* 109 */       ED_UNASSIGNED,          /* m */
+       /* 110 */       VI_REPEAT_SEARCH_NEXT,  /* n */
+       /* 111 */       ED_UNASSIGNED,          /* o */
+       /* 112 */       VI_PASTE_NEXT,          /* p */
+       /* 113 */       ED_UNASSIGNED,          /* q */
+       /* 114 */       VI_REPLACE_CHAR,        /* r */
+       /* 115 */       VI_SUBSTITUTE_CHAR,     /* s */
+       /* 116 */       VI_TO_NEXT_CHAR,        /* t */
+       /* 117 */       VI_UNDO,                /* u */
+       /* 118 */       VI_HISTEDIT,            /* v */
+       /* 119 */       VI_NEXT_WORD,           /* w */
+       /* 120 */       ED_DELETE_NEXT_CHAR,    /* x */
+       /* 121 */       VI_YANK,                /* y */
+       /* 122 */       ED_UNASSIGNED,          /* z */
+       /* 123 */       ED_UNASSIGNED,          /* { */
+       /* 124 */       VI_TO_COLUMN,           /* | */
+       /* 125 */       ED_UNASSIGNED,          /* } */
+       /* 126 */       VI_CHANGE_CASE,         /* ~ */
+       /* 127 */       ED_DELETE_PREV_CHAR,    /* ^? */
+       /* 128 */       ED_UNASSIGNED,          /* M-^@ */
+       /* 129 */       ED_UNASSIGNED,          /* M-^A */
+       /* 130 */       ED_UNASSIGNED,          /* M-^B */
+       /* 131 */       ED_UNASSIGNED,          /* M-^C */
+       /* 132 */       ED_UNASSIGNED,          /* M-^D */
+       /* 133 */       ED_UNASSIGNED,          /* M-^E */
+       /* 134 */       ED_UNASSIGNED,          /* M-^F */
+       /* 135 */       ED_UNASSIGNED,          /* M-^G */
+       /* 136 */       ED_UNASSIGNED,          /* M-^H */
+       /* 137 */       ED_UNASSIGNED,          /* M-^I */
+       /* 138 */       ED_UNASSIGNED,          /* M-^J */
+       /* 139 */       ED_UNASSIGNED,          /* M-^K */
+       /* 140 */       ED_UNASSIGNED,          /* M-^L */
+       /* 141 */       ED_UNASSIGNED,          /* M-^M */
+       /* 142 */       ED_UNASSIGNED,          /* M-^N */
+       /* 143 */       ED_UNASSIGNED,          /* M-^O */
+       /* 144 */       ED_UNASSIGNED,          /* M-^P */
+       /* 145 */       ED_UNASSIGNED,          /* M-^Q */
+       /* 146 */       ED_UNASSIGNED,          /* M-^R */
+       /* 147 */       ED_UNASSIGNED,          /* M-^S */
+       /* 148 */       ED_UNASSIGNED,          /* M-^T */
+       /* 149 */       ED_UNASSIGNED,          /* M-^U */
+       /* 150 */       ED_UNASSIGNED,          /* M-^V */
+       /* 151 */       ED_UNASSIGNED,          /* M-^W */
+       /* 152 */       ED_UNASSIGNED,          /* M-^X */
+       /* 153 */       ED_UNASSIGNED,          /* M-^Y */
+       /* 154 */       ED_UNASSIGNED,          /* M-^Z */
+       /* 155 */       ED_UNASSIGNED,          /* M-^[ */
+       /* 156 */       ED_UNASSIGNED,          /* M-^\ */
+       /* 157 */       ED_UNASSIGNED,          /* M-^] */
+       /* 158 */       ED_UNASSIGNED,          /* M-^^ */
+       /* 159 */       ED_UNASSIGNED,          /* M-^_ */
+       /* 160 */       ED_UNASSIGNED,          /* M-SPACE */
+       /* 161 */       ED_UNASSIGNED,          /* M-! */
+       /* 162 */       ED_UNASSIGNED,          /* M-" */
+       /* 163 */       ED_UNASSIGNED,          /* M-# */
+       /* 164 */       ED_UNASSIGNED,          /* M-$ */
+       /* 165 */       ED_UNASSIGNED,          /* M-% */
+       /* 166 */       ED_UNASSIGNED,          /* M-& */
+       /* 167 */       ED_UNASSIGNED,          /* M-' */
+       /* 168 */       ED_UNASSIGNED,          /* M-( */
+       /* 169 */       ED_UNASSIGNED,          /* M-) */
+       /* 170 */       ED_UNASSIGNED,          /* M-* */
+       /* 171 */       ED_UNASSIGNED,          /* M-+ */
+       /* 172 */       ED_UNASSIGNED,          /* M-, */
+       /* 173 */       ED_UNASSIGNED,          /* M-- */
+       /* 174 */       ED_UNASSIGNED,          /* M-. */
+       /* 175 */       ED_UNASSIGNED,          /* M-/ */
+       /* 176 */       ED_UNASSIGNED,          /* M-0 */
+       /* 177 */       ED_UNASSIGNED,          /* M-1 */
+       /* 178 */       ED_UNASSIGNED,          /* M-2 */
+       /* 179 */       ED_UNASSIGNED,          /* M-3 */
+       /* 180 */       ED_UNASSIGNED,          /* M-4 */
+       /* 181 */       ED_UNASSIGNED,          /* M-5 */
+       /* 182 */       ED_UNASSIGNED,          /* M-6 */
+       /* 183 */       ED_UNASSIGNED,          /* M-7 */
+       /* 184 */       ED_UNASSIGNED,          /* M-8 */
+       /* 185 */       ED_UNASSIGNED,          /* M-9 */
+       /* 186 */       ED_UNASSIGNED,          /* M-: */
+       /* 187 */       ED_UNASSIGNED,          /* M-; */
+       /* 188 */       ED_UNASSIGNED,          /* M-< */
+       /* 189 */       ED_UNASSIGNED,          /* M-= */
+       /* 190 */       ED_UNASSIGNED,          /* M-> */
+       /* 191 */       ED_UNASSIGNED,          /* M-? */
+       /* 192 */       ED_UNASSIGNED,          /* M-@ */
+       /* 193 */       ED_UNASSIGNED,          /* M-A */
+       /* 194 */       ED_UNASSIGNED,          /* M-B */
+       /* 195 */       ED_UNASSIGNED,          /* M-C */
+       /* 196 */       ED_UNASSIGNED,          /* M-D */
+       /* 197 */       ED_UNASSIGNED,          /* M-E */
+       /* 198 */       ED_UNASSIGNED,          /* M-F */
+       /* 199 */       ED_UNASSIGNED,          /* M-G */
+       /* 200 */       ED_UNASSIGNED,          /* M-H */
+       /* 201 */       ED_UNASSIGNED,          /* M-I */
+       /* 202 */       ED_UNASSIGNED,          /* M-J */
+       /* 203 */       ED_UNASSIGNED,          /* M-K */
+       /* 204 */       ED_UNASSIGNED,          /* M-L */
+       /* 205 */       ED_UNASSIGNED,          /* M-M */
+       /* 206 */       ED_UNASSIGNED,          /* M-N */
+       /* 207 */       ED_SEQUENCE_LEAD_IN,    /* M-O */
+       /* 208 */       ED_UNASSIGNED,          /* M-P */
+       /* 209 */       ED_UNASSIGNED,          /* M-Q */
+       /* 210 */       ED_UNASSIGNED,          /* M-R */
+       /* 211 */       ED_UNASSIGNED,          /* M-S */
+       /* 212 */       ED_UNASSIGNED,          /* M-T */
+       /* 213 */       ED_UNASSIGNED,          /* M-U */
+       /* 214 */       ED_UNASSIGNED,          /* M-V */
+       /* 215 */       ED_UNASSIGNED,          /* M-W */
+       /* 216 */       ED_UNASSIGNED,          /* M-X */
+       /* 217 */       ED_UNASSIGNED,          /* M-Y */
+       /* 218 */       ED_UNASSIGNED,          /* M-Z */
+       /* 219 */       ED_SEQUENCE_LEAD_IN,    /* M-[ */
+       /* 220 */       ED_UNASSIGNED,          /* M-\ */
+       /* 221 */       ED_UNASSIGNED,          /* M-] */
+       /* 222 */       ED_UNASSIGNED,          /* M-^ */
+       /* 223 */       ED_UNASSIGNED,          /* M-_ */
+       /* 224 */       ED_UNASSIGNED,          /* M-` */
+       /* 225 */       ED_UNASSIGNED,          /* M-a */
+       /* 226 */       ED_UNASSIGNED,          /* M-b */
+       /* 227 */       ED_UNASSIGNED,          /* M-c */
+       /* 228 */       ED_UNASSIGNED,          /* M-d */
+       /* 229 */       ED_UNASSIGNED,          /* M-e */
+       /* 230 */       ED_UNASSIGNED,          /* M-f */
+       /* 231 */       ED_UNASSIGNED,          /* M-g */
+       /* 232 */       ED_UNASSIGNED,          /* M-h */
+       /* 233 */       ED_UNASSIGNED,          /* M-i */
+       /* 234 */       ED_UNASSIGNED,          /* M-j */
+       /* 235 */       ED_UNASSIGNED,          /* M-k */
+       /* 236 */       ED_UNASSIGNED,          /* M-l */
+       /* 237 */       ED_UNASSIGNED,          /* M-m */
+       /* 238 */       ED_UNASSIGNED,          /* M-n */
+       /* 239 */       ED_UNASSIGNED,          /* M-o */
+       /* 240 */       ED_UNASSIGNED,          /* M-p */
+       /* 241 */       ED_UNASSIGNED,          /* M-q */
+       /* 242 */       ED_UNASSIGNED,          /* M-r */
+       /* 243 */       ED_UNASSIGNED,          /* M-s */
+       /* 244 */       ED_UNASSIGNED,          /* M-t */
+       /* 245 */       ED_UNASSIGNED,          /* M-u */
+       /* 246 */       ED_UNASSIGNED,          /* M-v */
+       /* 247 */       ED_UNASSIGNED,          /* M-w */
+       /* 248 */       ED_UNASSIGNED,          /* M-x */
+       /* 249 */       ED_UNASSIGNED,          /* M-y */
+       /* 250 */       ED_UNASSIGNED,          /* M-z */
+       /* 251 */       ED_UNASSIGNED,          /* M-{ */
+       /* 252 */       ED_UNASSIGNED,          /* M-| */
+       /* 253 */       ED_UNASSIGNED,          /* M-} */
+       /* 254 */       ED_UNASSIGNED,          /* M-~ */
+       /* 255 */       ED_UNASSIGNED           /* M-^? */
+};
+
+
+/* map_init():
+ *     Initialize and allocate the maps
+ */
+protected int
+map_init(EditLine *el)
+{
+
+       /*
+         * Make sure those are correct before starting.
+         */
+#ifdef MAP_DEBUG
+       if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t))
+               EL_ABORT((el->errfile, "Emacs map incorrect\n"));
+       if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t))
+               EL_ABORT((el->errfile, "Vi command map incorrect\n"));
+       if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t))
+               EL_ABORT((el->errfile, "Vi insert map incorrect\n"));
+#endif
+
+       el->el_map.alt = el_malloc(sizeof(*el->el_map.alt) * N_KEYS);
+       if (el->el_map.alt == NULL)
+               return -1;
+       el->el_map.key = el_malloc(sizeof(*el->el_map.key) * N_KEYS);
+       if (el->el_map.key == NULL)
+               return -1;
+       el->el_map.emacs = el_map_emacs;
+       el->el_map.vic = el_map_vi_command;
+       el->el_map.vii = el_map_vi_insert;
+       el->el_map.help = el_malloc(sizeof(*el->el_map.help) * EL_NUM_FCNS);
+       if (el->el_map.help == NULL)
+               return -1;
+       (void) memcpy(el->el_map.help, help__get(),
+           sizeof(*el->el_map.help) * EL_NUM_FCNS);
+       el->el_map.func = el_malloc(sizeof(*el->el_map.func) * EL_NUM_FCNS);
+       if (el->el_map.func == NULL)
+               return -1;
+       memcpy(el->el_map.func, func__get(), sizeof(*el->el_map.func)
+           * EL_NUM_FCNS);
+       el->el_map.nfunc = EL_NUM_FCNS;
+
+#ifdef VIDEFAULT
+       map_init_vi(el);
+#else
+       map_init_emacs(el);
+#endif /* VIDEFAULT */
+       return 0;
+}
+
+
+/* map_end():
+ *     Free the space taken by the editor maps
+ */
+protected void
+map_end(EditLine *el)
+{
+
+       el_free(el->el_map.alt);
+       el->el_map.alt = NULL;
+       el_free(el->el_map.key);
+       el->el_map.key = NULL;
+       el->el_map.emacs = NULL;
+       el->el_map.vic = NULL;
+       el->el_map.vii = NULL;
+       el_free(el->el_map.help);
+       el->el_map.help = NULL;
+       el_free(el->el_map.func);
+       el->el_map.func = NULL;
+}
+
+
+/* map_init_nls():
+ *     Find all the printable keys and bind them to self insert
+ */
+private void
+map_init_nls(EditLine *el)
+{
+       int i;
+
+       el_action_t *map = el->el_map.key;
+
+       for (i = 0200; i <= 0377; i++)
+               if (Isprint(i))
+                       map[i] = ED_INSERT;
+}
+
+
+/* map_init_meta():
+ *     Bind all the meta keys to the appropriate ESC-<key> sequence
+ */
+private void
+map_init_meta(EditLine *el)
+{
+       Char buf[3];
+       int i;
+       el_action_t *map = el->el_map.key;
+       el_action_t *alt = el->el_map.alt;
+
+       for (i = 0; i <= 0377 && map[i] != EM_META_NEXT; i++)
+               continue;
+
+       if (i > 0377) {
+               for (i = 0; i <= 0377 && alt[i] != EM_META_NEXT; i++)
+                       continue;
+               if (i > 0377) {
+                       i = 033;
+                       if (el->el_map.type == MAP_VI)
+                               map = alt;
+               } else
+                       map = alt;
+       }
+       buf[0] = (Char) i;
+       buf[2] = 0;
+       for (i = 0200; i <= 0377; i++)
+               switch (map[i]) {
+               case ED_INSERT:
+               case ED_UNASSIGNED:
+               case ED_SEQUENCE_LEAD_IN:
+                       break;
+               default:
+                       buf[1] = i & 0177;
+                       keymacro_add(el, buf, keymacro_map_cmd(el, (int) map[i]), XK_CMD);
+                       break;
+               }
+       map[(int) buf[0]] = ED_SEQUENCE_LEAD_IN;
+}
+
+
+/* map_init_vi():
+ *     Initialize the vi bindings
+ */
+protected void
+map_init_vi(EditLine *el)
+{
+       int i;
+       el_action_t *key = el->el_map.key;
+       el_action_t *alt = el->el_map.alt;
+       const el_action_t *vii = el->el_map.vii;
+       const el_action_t *vic = el->el_map.vic;
+
+       el->el_map.type = MAP_VI;
+       el->el_map.current = el->el_map.key;
+
+       keymacro_reset(el);
+
+       for (i = 0; i < N_KEYS; i++) {
+               key[i] = vii[i];
+               alt[i] = vic[i];
+       }
+
+       map_init_meta(el);
+       map_init_nls(el);
+
+       tty_bind_char(el, 1);
+       terminal_bind_arrow(el);
+}
+
+
+/* map_init_emacs():
+ *     Initialize the emacs bindings
+ */
+protected void
+map_init_emacs(EditLine *el)
+{
+       int i;
+       Char buf[3];
+       el_action_t *key = el->el_map.key;
+       el_action_t *alt = el->el_map.alt;
+       const el_action_t *emacs = el->el_map.emacs;
+
+       el->el_map.type = MAP_EMACS;
+       el->el_map.current = el->el_map.key;
+       keymacro_reset(el);
+
+       for (i = 0; i < N_KEYS; i++) {
+               key[i] = emacs[i];
+               alt[i] = ED_UNASSIGNED;
+       }
+
+       map_init_meta(el);
+       map_init_nls(el);
+
+       buf[0] = CONTROL('X');
+       buf[1] = CONTROL('X');
+       buf[2] = 0;
+       keymacro_add(el, buf, keymacro_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD);
+
+       tty_bind_char(el, 1);
+       terminal_bind_arrow(el);
+}
+
+
+/* map_set_editor():
+ *     Set the editor
+ */
+protected int
+map_set_editor(EditLine *el, Char *editor)
+{
+
+       if (Strcmp(editor, STR("emacs")) == 0) {
+               map_init_emacs(el);
+               return 0;
+       }
+       if (Strcmp(editor, STR("vi")) == 0) {
+               map_init_vi(el);
+               return 0;
+       }
+       return -1;
+}
+
+
+/* map_get_editor():
+ *     Retrieve the editor
+ */
+protected int
+map_get_editor(EditLine *el, const Char **editor)
+{
+
+       if (editor == NULL)
+               return -1;
+       switch (el->el_map.type) {
+       case MAP_EMACS:
+               *editor = STR("emacs");
+               return 0;
+       case MAP_VI:
+               *editor = STR("vi");
+               return 0;
+       }
+       return -1;
+}
+
+
+/* map_print_key():
+ *     Print the function description for 1 key
+ */
+private void
+map_print_key(EditLine *el, el_action_t *map, const Char *in)
+{
+       char outbuf[EL_BUFSIZ];
+       el_bindings_t *bp, *ep;
+
+       if (in[0] == '\0' || in[1] == '\0') {
+               (void) keymacro__decode_str(in, outbuf, sizeof(outbuf), "");
+               ep = &el->el_map.help[el->el_map.nfunc];
+               for (bp = el->el_map.help; bp < ep; bp++)
+                       if (bp->func == map[(unsigned char) *in]) {
+                               (void) fprintf(el->el_outfile,
+                                   "%s\t->\t" FSTR "\n", outbuf, bp->name);
+                               return;
+                       }
+       } else
+               keymacro_print(el, in);
+}
+
+
+/* map_print_some_keys():
+ *     Print keys from first to last
+ */
+private void
+map_print_some_keys(EditLine *el, el_action_t *map, Int first, Int last)
+{
+       el_bindings_t *bp, *ep;
+       Char firstbuf[2], lastbuf[2];
+       char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ];
+
+       firstbuf[0] = first;
+       firstbuf[1] = 0;
+       lastbuf[0] = last;
+       lastbuf[1] = 0;
+       if (map[first] == ED_UNASSIGNED) {
+               if (first == last) {
+                       (void) keymacro__decode_str(firstbuf, unparsbuf, 
+                           sizeof(unparsbuf), STRQQ);
+                       (void) fprintf(el->el_outfile,
+                           "%-15s->  is undefined\n", unparsbuf);
+               }
+               return;
+       }
+       ep = &el->el_map.help[el->el_map.nfunc];
+       for (bp = el->el_map.help; bp < ep; bp++) {
+               if (bp->func == map[first]) {
+                       if (first == last) {
+                               (void) keymacro__decode_str(firstbuf, unparsbuf, 
+                                   sizeof(unparsbuf), STRQQ);
+                               (void) fprintf(el->el_outfile, "%-15s->  " FSTR "\n",
+                                   unparsbuf, bp->name);
+                       } else {
+                               (void) keymacro__decode_str(firstbuf, unparsbuf, 
+                                   sizeof(unparsbuf), STRQQ);
+                               (void) keymacro__decode_str(lastbuf, extrabuf, 
+                                   sizeof(extrabuf), STRQQ);
+                               (void) fprintf(el->el_outfile,
+                                   "%-4s to %-7s->  " FSTR "\n",
+                                   unparsbuf, extrabuf, bp->name);
+                       }
+                       return;
+               }
+       }
+#ifdef MAP_DEBUG
+       if (map == el->el_map.key) {
+               (void) keymacro__decode_str(firstbuf, unparsbuf, 
+                   sizeof(unparsbuf), STRQQ);
+               (void) fprintf(el->el_outfile,
+                   "BUG!!! %s isn't bound to anything.\n", unparsbuf);
+               (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n",
+                   first, el->el_map.key[first]);
+       } else {
+               (void) keymacro__decode_str(firstbuf, unparsbuf, 
+                   sizeof(unparsbuf), STRQQ);
+               (void) fprintf(el->el_outfile,
+                   "BUG!!! %s isn't bound to anything.\n", unparsbuf);
+               (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n",
+                   first, el->el_map.alt[first]);
+       }
+#endif
+       EL_ABORT((el->el_errfile, "Error printing keys\n"));
+}
+
+
+/* map_print_all_keys():
+ *     Print the function description for all keys.
+ */
+private void
+map_print_all_keys(EditLine *el)
+{
+       int prev, i;
+
+       (void) fprintf(el->el_outfile, "Standard key bindings\n");
+       prev = 0;
+       for (i = 0; i < N_KEYS; i++) {
+               if (el->el_map.key[prev] == el->el_map.key[i])
+                       continue;
+               map_print_some_keys(el, el->el_map.key, prev, i - 1);
+               prev = i;
+       }
+       map_print_some_keys(el, el->el_map.key, prev, i - 1);
+
+       (void) fprintf(el->el_outfile, "Alternative key bindings\n");
+       prev = 0;
+       for (i = 0; i < N_KEYS; i++) {
+               if (el->el_map.alt[prev] == el->el_map.alt[i])
+                       continue;
+               map_print_some_keys(el, el->el_map.alt, prev, i - 1);
+               prev = i;
+       }
+       map_print_some_keys(el, el->el_map.alt, prev, i - 1);
+
+       (void) fprintf(el->el_outfile, "Multi-character bindings\n");
+       keymacro_print(el, STR(""));
+       (void) fprintf(el->el_outfile, "Arrow key bindings\n");
+       terminal_print_arrow(el, STR(""));
+}
+
+
+/* map_bind():
+ *     Add/remove/change bindings
+ */
+protected int
+map_bind(EditLine *el, int argc, const Char **argv)
+{
+       el_action_t *map;
+       int ntype, rem;
+       const Char *p;
+       Char inbuf[EL_BUFSIZ];
+       Char outbuf[EL_BUFSIZ];
+       const Char *in = NULL;
+       Char *out = NULL;
+       el_bindings_t *bp, *ep;
+       int cmd;
+       int key;
+
+       if (argv == NULL)
+               return -1;
+
+       map = el->el_map.key;
+       ntype = XK_CMD;
+       key = rem = 0;
+       for (argc = 1; (p = argv[argc]) != NULL; argc++)
+               if (p[0] == '-')
+                       switch (p[1]) {
+                       case 'a':
+                               map = el->el_map.alt;
+                               break;
+
+                       case 's':
+                               ntype = XK_STR;
+                               break;
+#ifdef notyet
+                       case 'c':
+                               ntype = XK_EXE;
+                               break;
+#endif
+                       case 'k':
+                               key = 1;
+                               break;
+
+                       case 'r':
+                               rem = 1;
+                               break;
+
+                       case 'v':
+                               map_init_vi(el);
+                               return 0;
+
+                       case 'e':
+                               map_init_emacs(el);
+                               return 0;
+
+                       case 'l':
+                               ep = &el->el_map.help[el->el_map.nfunc];
+                               for (bp = el->el_map.help; bp < ep; bp++)
+                                       (void) fprintf(el->el_outfile,
+                                           "" FSTR "\n\t" FSTR "\n",
+                                           bp->name, bp->description);
+                               return 0;
+                       default:
+                               (void) fprintf(el->el_errfile,
+                                   "" FSTR ": Invalid switch `%c'.\n",
+                                   argv[0], p[1]);
+                       }
+               else
+                       break;
+
+       if (argv[argc] == NULL) {
+               map_print_all_keys(el);
+               return 0;
+       }
+       if (key)
+               in = argv[argc++];
+       else if ((in = parse__string(inbuf, argv[argc++])) == NULL) {
+               (void) fprintf(el->el_errfile,
+                   "" FSTR ": Invalid \\ or ^ in instring.\n",
+                   argv[0]);
+               return -1;
+       }
+       if (rem) {
+               if (key) {
+                       (void) terminal_clear_arrow(el, in);
+                       return -1;
+               }
+               if (in[1])
+                       (void) keymacro_delete(el, in);
+               else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN)
+                       (void) keymacro_delete(el, in);
+               else
+                       map[(unsigned char) *in] = ED_UNASSIGNED;
+               return 0;
+       }
+       if (argv[argc] == NULL) {
+               if (key)
+                       terminal_print_arrow(el, in);
+               else
+                       map_print_key(el, map, in);
+               return 0;
+       }
+#ifdef notyet
+       if (argv[argc + 1] != NULL) {
+               bindkeymacro_usage();
+               return -1;
+       }
+#endif
+
+       switch (ntype) {
+       case XK_STR:
+       case XK_EXE:
+               if ((out = parse__string(outbuf, argv[argc])) == NULL) {
+                       (void) fprintf(el->el_errfile,
+                           "" FSTR ": Invalid \\ or ^ in outstring.\n", argv[0]);
+                       return -1;
+               }
+               if (key)
+                       terminal_set_arrow(el, in, keymacro_map_str(el, out), ntype);
+               else
+                       keymacro_add(el, in, keymacro_map_str(el, out), ntype);
+               map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
+               break;
+
+       case XK_CMD:
+               if ((cmd = parse_cmd(el, argv[argc])) == -1) {
+                       (void) fprintf(el->el_errfile,
+                           "" FSTR ": Invalid command `" FSTR "'.\n",
+                           argv[0], argv[argc]);
+                       return -1;
+               }
+               if (key)
+                       terminal_set_arrow(el, in, keymacro_map_str(el, out), ntype);
+               else {
+                       if (in[1]) {
+                               keymacro_add(el, in, keymacro_map_cmd(el, cmd), ntype);
+                               map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
+                       } else {
+                               keymacro_clear(el, map, in);
+                               map[(unsigned char) *in] = (el_action_t)cmd;
+                       }
+               }
+               break;
+
+       /* coverity[dead_error_begin] */
+       default:
+               EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+               break;
+       }
+       return 0;
+}
+
+
+/* map_addfunc():
+ *     add a user defined function
+ */
+protected int
+map_addfunc(EditLine *el, const Char *name, const Char *help, el_func_t func)
+{
+       void *p;
+       size_t nf = (size_t)el->el_map.nfunc + 1;
+
+       if (name == NULL || help == NULL || func == NULL)
+               return -1;
+
+       if ((p = el_realloc(el->el_map.func, nf *
+           sizeof(*el->el_map.func))) == NULL)
+               return -1;
+       el->el_map.func = p;
+       if ((p = el_realloc(el->el_map.help, nf * sizeof(*el->el_map.help)))
+           == NULL)
+               return -1;
+       el->el_map.help = p;
+
+       nf = (size_t)el->el_map.nfunc;
+       el->el_map.func[nf] = func;
+
+       el->el_map.help[nf].name = name;
+       el->el_map.help[nf].func = (int)nf;
+       el->el_map.help[nf].description = help;
+       el->el_map.nfunc++;
+
+       return 0;
+}
diff --git a/lib/libedit/map.h b/lib/libedit/map.h
new file mode 100644 (file)
index 0000000..8e0c7e4
--- /dev/null
@@ -0,0 +1,77 @@
+/*     $NetBSD: map.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)map.h       8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.map.h:   Editor maps
+ */
+#ifndef _h_el_map
+#define        _h_el_map
+
+typedef struct el_bindings_t { /* for the "bind" shell command */
+       const Char      *name;          /* function name for bind command */
+       int              func;          /* function numeric value */
+       const Char      *description;   /* description of function */
+} el_bindings_t;
+
+
+typedef struct el_map_t {
+       el_action_t     *alt;           /* The current alternate key map */
+       el_action_t     *key;           /* The current normal key map   */
+       el_action_t     *current;       /* The keymap we are using      */
+       const el_action_t *emacs;       /* The default emacs key map    */
+       const el_action_t *vic;         /* The vi command mode key map  */
+       const el_action_t *vii;         /* The vi insert mode key map   */
+       int              type;          /* Emacs or vi                  */
+       el_bindings_t   *help;          /* The help for the editor functions */
+       el_func_t       *func;          /* List of available functions  */
+       int              nfunc;         /* The number of functions/help items */
+} el_map_t;
+
+#define        MAP_EMACS       0
+#define        MAP_VI          1
+
+#define N_KEYS      256
+
+protected int  map_bind(EditLine *, int, const Char **);
+protected int  map_init(EditLine *);
+protected void map_end(EditLine *);
+protected void map_init_vi(EditLine *);
+protected void map_init_emacs(EditLine *);
+protected int  map_set_editor(EditLine *, Char *);
+protected int  map_get_editor(EditLine *, const Char **);
+protected int  map_addfunc(EditLine *, const Char *, const Char *, el_func_t);
+
+#endif /* _h_el_map */
diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c
new file mode 100644 (file)
index 0000000..f1c4391
--- /dev/null
@@ -0,0 +1,285 @@
+/*     $NetBSD: parse.c,v 1.26 2011/08/16 16:25:15 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)parse.c    8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: parse.c,v 1.26 2011/08/16 16:25:15 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * parse.c: parse an editline extended command
+ *
+ * commands are:
+ *
+ *     bind
+ *     echotc
+ *     edit
+ *     gettc
+ *     history
+ *     settc
+ *     setty
+ */
+#include "el.h"
+#include <stdlib.h>
+
+private const struct {
+       const Char *name;
+       int (*func)(EditLine *, int, const Char **);
+} cmds[] = {
+       { STR("bind"),          map_bind        },
+       { STR("echotc"),        terminal_echotc },
+       { STR("edit"),          el_editmode     },
+       { STR("history"),       hist_command    },
+       { STR("telltc"),        terminal_telltc },
+       { STR("settc"),         terminal_settc  },
+       { STR("setty"),         tty_stty        },
+       { NULL,                 NULL            }
+};
+
+
+/* parse_line():
+ *     Parse a line and dispatch it
+ */
+protected int
+parse_line(EditLine *el, const Char *line)
+{
+       const Char **argv;
+       int argc;
+       TYPE(Tokenizer) *tok;
+
+       tok = FUN(tok,init)(NULL);
+       FUN(tok,str)(tok, line, &argc, &argv);
+       argc = FUN(el,parse)(el, argc, argv);
+       FUN(tok,end)(tok);
+       return argc;
+}
+
+
+/* el_parse():
+ *     Command dispatcher
+ */
+public int
+FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
+{
+       const Char *ptr;
+       int i;
+
+       if (argc < 1)
+               return -1;
+       ptr = Strchr(argv[0], ':');
+       if (ptr != NULL) {
+               Char *tprog;
+               size_t l;
+
+               if (ptr == argv[0])
+                       return 0;
+               l = (size_t)(ptr - argv[0] - 1);
+               tprog = el_malloc((l + 1) * sizeof(*tprog));
+               if (tprog == NULL)
+                       return 0;
+               (void) Strncpy(tprog, argv[0], l);
+               tprog[l] = '\0';
+               ptr++;
+               l = (size_t)el_match(el->el_prog, tprog);
+               el_free(tprog);
+               if (!l)
+                       return 0;
+       } else
+               ptr = argv[0];
+
+       for (i = 0; cmds[i].name != NULL; i++)
+               if (Strcmp(cmds[i].name, ptr) == 0) {
+                       i = (*cmds[i].func) (el, argc, argv);
+                       return -i;
+               }
+       return -1;
+}
+
+
+/* parse__escape():
+ *     Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return
+ *     the appropriate character or -1 if the escape is not valid
+ */
+protected int
+parse__escape(const Char **ptr)
+{
+       const Char *p;
+       Int c;
+
+       p = *ptr;
+
+       if (p[1] == 0)
+               return -1;
+
+       if (*p == '\\') {
+               p++;
+               switch (*p) {
+               case 'a':
+                       c = '\007';     /* Bell */
+                       break;
+               case 'b':
+                       c = '\010';     /* Backspace */
+                       break;
+               case 't':
+                       c = '\011';     /* Horizontal Tab */
+                       break;
+               case 'n':
+                       c = '\012';     /* New Line */
+                       break;
+               case 'v':
+                       c = '\013';     /* Vertical Tab */
+                       break;
+               case 'f':
+                       c = '\014';     /* Form Feed */
+                       break;
+               case 'r':
+                       c = '\015';     /* Carriage Return */
+                       break;
+               case 'e':
+                       c = '\033';     /* Escape */
+                       break;
+                case 'U':               /* Unicode \U+xxxx or \U+xxxxx format */
+                {
+                        int i;
+                        const Char hex[] = STR("0123456789ABCDEF");
+                        const Char *h;
+                        ++p;
+                        if (*p++ != '+')
+                                return -1;
+                       c = 0;
+                        for (i = 0; i < 5; ++i) {
+                                h = Strchr(hex, *p++);
+                                if (!h && i < 4)
+                                        return -1;
+                                else if (h)
+                                        c = (c << 4) | ((int)(h - hex));
+                                else
+                                        --p;
+                        }
+                        if (c > 0x10FFFF) /* outside valid character range */
+                                return -1;
+                        break;
+                }
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               {
+                       int cnt, ch;
+
+                       for (cnt = 0, c = 0; cnt < 3; cnt++) {
+                               ch = *p++;
+                               if (ch < '0' || ch > '7') {
+                                       p--;
+                                       break;
+                               }
+                               c = (c << 3) | (ch - '0');
+                       }
+                       if ((c & (wint_t)0xffffff00) != (wint_t)0)
+                               return -1;
+                       --p;
+                       break;
+               }
+               default:
+                       c = *p;
+                       break;
+               }
+       } else if (*p == '^') {
+               p++;
+               c = (*p == '?') ? '\177' : (*p & 0237);
+       } else
+               c = *p;
+       *ptr = ++p;
+       return c;
+}
+
+/* parse__string():
+ *     Parse the escapes from in and put the raw string out
+ */
+protected Char *
+parse__string(Char *out, const Char *in)
+{
+       Char *rv = out;
+       int n;
+
+       for (;;)
+               switch (*in) {
+               case '\0':
+                       *out = '\0';
+                       return rv;
+
+               case '\\':
+               case '^':
+                       if ((n = parse__escape(&in)) == -1)
+                               return NULL;
+                       *out++ = n;
+                       break;
+
+               case 'M':
+                       if (in[1] == '-' && in[2] != '\0') {
+                               *out++ = '\033';
+                               in += 2;
+                               break;
+                       }
+                       /*FALLTHROUGH*/
+
+               default:
+                       *out++ = *in++;
+                       break;
+               }
+}
+
+
+/* parse_cmd():
+ *     Return the command number for the command string given
+ *     or -1 if one is not found
+ */
+protected int
+parse_cmd(EditLine *el, const Char *cmd)
+{
+       el_bindings_t *b;
+
+       for (b = el->el_map.help; b->name != NULL; b++)
+               if (Strcmp(b->name, cmd) == 0)
+                       return b->func;
+       return -1;
+}
diff --git a/lib/libedit/parse.h b/lib/libedit/parse.h
new file mode 100644 (file)
index 0000000..ec04051
--- /dev/null
@@ -0,0 +1,48 @@
+/*     $NetBSD: parse.h,v 1.7 2009/12/30 22:37:40 christos Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)parse.h     8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.parse.h: Parser functions
+ */
+#ifndef _h_el_parse
+#define        _h_el_parse
+
+protected int   parse_line(EditLine *, const Char *);
+protected int   parse__escape(const Char **);
+protected Char *parse__string(Char *, const Char *);
+protected int   parse_cmd(EditLine *, const Char *);
+
+#endif /* _h_el_parse */
diff --git a/lib/libedit/prompt.c b/lib/libedit/prompt.c
new file mode 100644 (file)
index 0000000..48b2d27
--- /dev/null
@@ -0,0 +1,199 @@
+/*     $NetBSD: prompt.c,v 1.20 2011/07/29 15:16:33 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)prompt.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: prompt.c,v 1.20 2011/07/29 15:16:33 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * prompt.c: Prompt printing functions
+ */
+#include <stdio.h>
+#include "el.h"
+
+private Char   *prompt_default(EditLine *);
+private Char   *prompt_default_r(EditLine *);
+
+/* prompt_default():
+ *     Just a default prompt, in case the user did not provide one
+ */
+private Char *
+/*ARGSUSED*/
+prompt_default(EditLine *el __attribute__((__unused__)))
+{
+       static Char a[3] = {'?', ' ', '\0'};
+
+       return a;
+}
+
+
+/* prompt_default_r():
+ *     Just a default rprompt, in case the user did not provide one
+ */
+private Char *
+/*ARGSUSED*/
+prompt_default_r(EditLine *el __attribute__((__unused__)))
+{
+       static Char a[1] = {'\0'};
+
+       return a;
+}
+
+
+/* prompt_print():
+ *     Print the prompt and update the prompt position.
+ */
+protected void
+prompt_print(EditLine *el, int op)
+{
+       el_prompt_t *elp;
+       Char *p;
+       int ignore = 0;
+
+       if (op == EL_PROMPT)
+               elp = &el->el_prompt;
+       else
+               elp = &el->el_rprompt;
+
+       if (elp->p_wide)
+               p = (*elp->p_func)(el);
+       else
+               p = ct_decode_string((char *)(void *)(*elp->p_func)(el),
+                   &el->el_scratch);
+
+       for (; *p; p++) {
+               if (elp->p_ignore == *p) {
+                       ignore = !ignore;
+                       continue;
+               }
+               if (ignore)
+                       terminal__putc(el, *p);
+               else
+                       re_putc(el, *p, 1);
+       }
+
+       elp->p_pos.v = el->el_refresh.r_cursor.v;
+       elp->p_pos.h = el->el_refresh.r_cursor.h;
+}
+
+
+/* prompt_init():
+ *     Initialize the prompt stuff
+ */
+protected int
+prompt_init(EditLine *el)
+{
+
+       el->el_prompt.p_func = prompt_default;
+       el->el_prompt.p_pos.v = 0;
+       el->el_prompt.p_pos.h = 0;
+       el->el_prompt.p_ignore = '\0';
+       el->el_rprompt.p_func = prompt_default_r;
+       el->el_rprompt.p_pos.v = 0;
+       el->el_rprompt.p_pos.h = 0;
+       el->el_rprompt.p_ignore = '\0';
+       return 0;
+}
+
+
+/* prompt_end():
+ *     Clean up the prompt stuff
+ */
+protected void
+/*ARGSUSED*/
+prompt_end(EditLine *el __attribute__((__unused__)))
+{
+}
+
+
+/* prompt_set():
+ *     Install a prompt printing function
+ */
+protected int
+prompt_set(EditLine *el, el_pfunc_t prf, Char c, int op, int wide)
+{
+       el_prompt_t *p;
+
+       if (op == EL_PROMPT || op == EL_PROMPT_ESC)
+               p = &el->el_prompt;
+       else
+               p = &el->el_rprompt;
+
+       if (prf == NULL) {
+               if (op == EL_PROMPT || op == EL_PROMPT_ESC)
+                       p->p_func = prompt_default;
+               else
+                       p->p_func = prompt_default_r;
+       } else {
+               p->p_func = prf;
+       }
+
+       p->p_ignore = c;
+
+       p->p_pos.v = 0;
+       p->p_pos.h = 0;
+       p->p_wide = wide;
+
+       return 0;
+}
+
+
+/* prompt_get():
+ *     Retrieve the prompt printing function
+ */
+protected int
+prompt_get(EditLine *el, el_pfunc_t *prf, Char *c, int op)
+{
+       el_prompt_t *p;
+
+       if (prf == NULL)
+               return -1;
+
+       if (op == EL_PROMPT)
+               p = &el->el_prompt;
+       else
+               p = &el->el_rprompt;
+
+       if (prf)
+               *prf = p->p_func;
+       if (c)
+               *c = p->p_ignore;
+
+       return 0;
+}
diff --git a/lib/libedit/prompt.h b/lib/libedit/prompt.h
new file mode 100644 (file)
index 0000000..af63b82
--- /dev/null
@@ -0,0 +1,60 @@
+/*     $NetBSD: prompt.h,v 1.10 2009/12/30 22:37:40 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)prompt.h    8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.prompt.h: Prompt printing stuff
+ */
+#ifndef _h_el_prompt
+#define        _h_el_prompt
+
+#include "histedit.h"
+
+typedef Char    *(*el_pfunc_t)(EditLine *);
+
+typedef struct el_prompt_t {
+       el_pfunc_t      p_func;         /* Function to return the prompt */
+       coord_t         p_pos;          /* position in the line after prompt */
+       Char            p_ignore;       /* character to start/end literal */
+       int             p_wide; 
+} el_prompt_t;
+
+protected void prompt_print(EditLine *, int);
+protected int  prompt_set(EditLine *, el_pfunc_t, Char, int, int);
+protected int  prompt_get(EditLine *, el_pfunc_t *, Char *, int);
+protected int  prompt_init(EditLine *);
+protected void prompt_end(EditLine *);
+
+#endif /* _h_el_prompt */
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
new file mode 100644 (file)
index 0000000..74796b1
--- /dev/null
@@ -0,0 +1,728 @@
+/*     $NetBSD: read.c,v 1.69 2012/09/11 12:31:08 christos Exp $       */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)read.c     8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: read.c,v 1.69 2012/09/11 12:31:08 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * read.c: Clean this junk up! This is horrible code.
+ *        Terminal read functions
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "el.h"
+
+#define OKCMD  -1      /* must be -1! */
+
+private int    read__fixio(int, int);
+private int    read_preread(EditLine *);
+private int    read_char(EditLine *, Char *);
+private int    read_getcmd(EditLine *, el_action_t *, Char *);
+private void   read_pop(c_macro_t *);
+
+/* read_init():
+ *     Initialize the read stuff
+ */
+protected int
+read_init(EditLine *el)
+{
+       /* builtin read_char */
+       el->el_read.read_char = read_char;
+       return 0;
+}
+
+
+/* el_read_setfn():
+ *     Set the read char function to the one provided.
+ *     If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
+ */
+protected int
+el_read_setfn(EditLine *el, el_rfunc_t rc)
+{
+       el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
+       return 0;
+}
+
+
+/* el_read_getfn():
+ *     return the current read char function, or EL_BUILTIN_GETCFN
+ *     if it is the default one
+ */
+protected el_rfunc_t
+el_read_getfn(EditLine *el)
+{
+       return el->el_read.read_char == read_char ?
+           EL_BUILTIN_GETCFN : el->el_read.read_char;
+}
+
+
+#ifndef MIN
+#define MIN(A,B) ((A) < (B) ? (A) : (B))
+#endif
+
+#ifdef DEBUG_EDIT
+private void
+read_debug(EditLine *el)
+{
+
+       if (el->el_line.cursor > el->el_line.lastchar)
+               (void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
+       if (el->el_line.cursor < el->el_line.buffer)
+               (void) fprintf(el->el_errfile, "cursor < buffer\r\n");
+       if (el->el_line.cursor > el->el_line.limit)
+               (void) fprintf(el->el_errfile, "cursor > limit\r\n");
+       if (el->el_line.lastchar > el->el_line.limit)
+               (void) fprintf(el->el_errfile, "lastchar > limit\r\n");
+       if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
+               (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
+}
+#endif /* DEBUG_EDIT */
+
+
+/* read__fixio():
+ *     Try to recover from a read error
+ */
+/* ARGSUSED */
+private int
+read__fixio(int fd __attribute__((__unused__)), int e)
+{
+
+       switch (e) {
+       case -1:                /* Make sure that the code is reachable */
+
+#ifdef EWOULDBLOCK
+       case EWOULDBLOCK:
+#ifndef TRY_AGAIN
+#define TRY_AGAIN
+#endif
+#endif /* EWOULDBLOCK */
+
+#if defined(POSIX) && defined(EAGAIN)
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+       case EAGAIN:
+#ifndef TRY_AGAIN
+#define TRY_AGAIN
+#endif
+#endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
+#endif /* POSIX && EAGAIN */
+
+               e = 0;
+#ifdef TRY_AGAIN
+#if defined(F_SETFL) && defined(O_NDELAY)
+               if ((e = fcntl(fd, F_GETFL, 0)) == -1)
+                       return -1;
+
+               if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
+                       return -1;
+               else
+                       e = 1;
+#endif /* F_SETFL && O_NDELAY */
+
+#ifdef FIONBIO
+               {
+                       int zero = 0;
+
+                       if (ioctl(fd, FIONBIO, &zero) == -1)
+                               return -1;
+                       else
+                               e = 1;
+               }
+#endif /* FIONBIO */
+
+#endif /* TRY_AGAIN */
+               return e ? 0 : -1;
+
+       case EINTR:
+               return 0;
+
+       default:
+               return -1;
+       }
+}
+
+
+/* read_preread():
+ *     Try to read the stuff in the input queue;
+ */
+private int
+read_preread(EditLine *el)
+{
+       int chrs = 0;
+
+       if (el->el_tty.t_mode == ED_IO)
+               return 0;
+
+#ifndef WIDECHAR
+/* FIONREAD attempts to buffer up multiple bytes, and to make that work
+ * properly with partial wide/UTF-8 characters would need some careful work. */
+#ifdef FIONREAD
+       (void) ioctl(el->el_infd, FIONREAD, &chrs);
+       if (chrs > 0) {
+               char buf[EL_BUFSIZ];
+
+               chrs = read(el->el_infd, buf,
+                   (size_t) MIN(chrs, EL_BUFSIZ - 1));
+               if (chrs > 0) {
+                       buf[chrs] = '\0';
+                       el_push(el, buf);
+               }
+       }
+#endif /* FIONREAD */
+#endif
+       return chrs > 0;
+}
+
+
+/* el_push():
+ *     Push a macro
+ */
+public void
+FUN(el,push)(EditLine *el, const Char *str)
+{
+       c_macro_t *ma = &el->el_chared.c_macro;
+
+       if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
+               ma->level++;
+               if ((ma->macro[ma->level] = Strdup(str)) != NULL)
+                       return;
+               ma->level--;
+       }
+       terminal_beep(el);
+       terminal__flush(el);
+}
+
+
+/* read_getcmd():
+ *     Get next command from the input stream, return OKCMD on success.
+ *     Character values > 255 are not looked up in the map, but inserted.
+ */
+private int
+read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
+{
+       el_action_t cmd;
+       int num;
+
+       el->el_errno = 0;
+       do {
+               if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */
+                       el->el_errno = num == 0 ? 0 : errno;
+                       return 0;       /* not OKCMD */
+               }
+
+#ifdef KANJI
+               if ((*ch & 0200)) {
+                       el->el_state.metanext = 0;
+                       cmd = CcViMap[' '];
+                       break;
+               } else
+#endif /* KANJI */
+
+               if (el->el_state.metanext) {
+                       el->el_state.metanext = 0;
+                       *ch |= 0200;
+               }
+#ifdef WIDECHAR
+               if (*ch >= N_KEYS)
+                       cmd = ED_INSERT;
+               else
+#endif
+                       cmd = el->el_map.current[(unsigned char) *ch];
+               if (cmd == ED_SEQUENCE_LEAD_IN) {
+                       keymacro_value_t val;
+                       switch (keymacro_get(el, ch, &val)) {
+                       case XK_CMD:
+                               cmd = val.cmd;
+                               break;
+                       case XK_STR:
+                               FUN(el,push)(el, val.str);
+                               break;
+#ifdef notyet
+                       case XK_EXE:
+                               /* XXX: In the future to run a user function */
+                               RunCommand(val.str);
+                               break;
+#endif
+                       default:
+                               EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
+                               break;
+                       }
+               }
+               if (el->el_map.alt == NULL)
+                       el->el_map.current = el->el_map.key;
+       } while (cmd == ED_SEQUENCE_LEAD_IN);
+       *cmdnum = cmd;
+       return OKCMD;
+}
+
+#ifdef WIDECHAR
+/* utf8_islead():
+ *     Test whether a byte is a leading byte of a UTF-8 sequence.
+ */
+private int
+utf8_islead(int c)
+{
+       return c < 0x80 ||             /* single byte char */
+              (c >= 0xc2 && c <= 0xf4); /* start of multibyte sequence */
+}
+#endif
+
+/* read_char():
+ *     Read a character from the tty.
+ */
+private int
+read_char(EditLine *el, Char *cp)
+{
+       ssize_t num_read;
+       int tried = 0;
+       char cbuf[MB_LEN_MAX];
+       size_t cbp = 0;
+       int bytes = 0;
+
+ again:
+       el->el_signal->sig_no = 0;
+       while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) {
+               int e = errno;
+               switch (el->el_signal->sig_no) {
+               case SIGCONT:
+                       FUN(el,set)(el, EL_REFRESH);
+                       /*FALLTHROUGH*/
+               case SIGWINCH:
+                       sig_set(el);
+                       goto again;
+               default:
+                       break;
+               }
+               if (!tried && read__fixio(el->el_infd, e) == 0)
+                       tried = 1;
+               else {
+                       errno = e;
+                       *cp = '\0';
+                       return -1;
+               }
+       }
+
+#ifdef WIDECHAR
+       if (el->el_flags & CHARSET_IS_UTF8) {
+               if (!utf8_islead((unsigned char)cbuf[0]))
+                       goto again; /* discard the byte we read and try again */
+               ++cbp;
+               if ((bytes = ct_mbtowc(cp, cbuf, cbp)) == -1) {
+                       ct_mbtowc_reset;
+                       if (cbp >= MB_LEN_MAX) { /* "shouldn't happen" */
+                               errno = EILSEQ;
+                               *cp = '\0';
+                               return -1;
+                       }
+                       goto again;
+               }
+       } else if (isascii((unsigned char)cbuf[0]) ||
+               /* we don't support other multibyte charsets */
+               ++cbp != 1 ||
+               /* Try non-ASCII characters in a 8-bit character set */
+               (bytes = ct_mbtowc(cp, cbuf, cbp)) != 1)
+#endif
+               *cp = (unsigned char)cbuf[0];
+
+       if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) {
+               cbp = 0; /* skip this character */
+               goto again;
+       }
+
+       return (int)num_read;
+}
+
+/* read_pop():
+ *     Pop a macro from the stack
+ */
+private void
+read_pop(c_macro_t *ma)
+{
+       int i;
+
+       el_free(ma->macro[0]);
+       for (i = 0; i < ma->level; i++)
+               ma->macro[i] = ma->macro[i + 1];
+       ma->level--;
+       ma->offset = 0;
+}
+
+/* el_getc():
+ *     Read a character
+ */
+public int
+FUN(el,getc)(EditLine *el, Char *cp)
+{
+       int num_read;
+       c_macro_t *ma = &el->el_chared.c_macro;
+
+       terminal__flush(el);
+       for (;;) {
+               if (ma->level < 0) {
+                       if (!read_preread(el))
+                               break;
+               }
+
+               if (ma->level < 0)
+                       break;
+
+               if (ma->macro[0][ma->offset] == '\0') {
+                       read_pop(ma);
+                       continue;
+               }
+
+               *cp = ma->macro[0][ma->offset++];
+
+               if (ma->macro[0][ma->offset] == '\0') {
+                       /* Needed for QuoteMode On */
+                       read_pop(ma);
+               }
+
+               return 1;
+       }
+
+#ifdef DEBUG_READ
+       (void) fprintf(el->el_errfile, "Turning raw mode on\n");
+#endif /* DEBUG_READ */
+       if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
+               return 0;
+
+#ifdef DEBUG_READ
+       (void) fprintf(el->el_errfile, "Reading a character\n");
+#endif /* DEBUG_READ */
+       num_read = (*el->el_read.read_char)(el, cp);
+       if (num_read < 0)
+               el->el_errno = errno;
+#ifdef WIDECHAR
+       if (el->el_flags & NARROW_READ)
+               *cp = *(char *)(void *)cp;
+#endif
+#ifdef DEBUG_READ
+       (void) fprintf(el->el_errfile, "Got it %c\n", *cp);
+#endif /* DEBUG_READ */
+       return num_read;
+}
+
+protected void
+read_prepare(EditLine *el)
+{
+       if (el->el_flags & HANDLE_SIGNALS)
+               sig_set(el);
+       if (el->el_flags & NO_TTY)
+               return;
+       if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
+               tty_rawmode(el);
+
+       /* This is relatively cheap, and things go terribly wrong if
+          we have the wrong size. */
+       el_resize(el);
+       re_clear_display(el);   /* reset the display stuff */
+       ch_reset(el, 0);
+       re_refresh(el);         /* print the prompt */
+
+       if (el->el_flags & UNBUFFERED)
+               terminal__flush(el);
+}
+
+protected void
+read_finish(EditLine *el)
+{
+       if ((el->el_flags & UNBUFFERED) == 0)
+               (void) tty_cookedmode(el);
+       if (el->el_flags & HANDLE_SIGNALS)
+               sig_clr(el);
+}
+
+public const Char *
+FUN(el,gets)(EditLine *el, int *nread)
+{
+       int retval;
+       el_action_t cmdnum = 0;
+       int num;                /* how many chars we have read at NL */
+       Char ch, *cp;
+       int crlf = 0;
+       int nrb;
+#ifdef FIONREAD
+       c_macro_t *ma = &el->el_chared.c_macro;
+#endif /* FIONREAD */
+
+       if (nread == NULL)
+               nread = &nrb;
+       *nread = 0;
+
+       if (el->el_flags & NO_TTY) {
+               size_t idx;
+
+               cp = el->el_line.buffer;
+               while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
+                       /* make sure there is space for next character */
+                       if (cp + 1 >= el->el_line.limit) {
+                               idx = (size_t)(cp - el->el_line.buffer);
+                               if (!ch_enlargebufs(el, (size_t)2))
+                                       break;
+                               cp = &el->el_line.buffer[idx];
+                       }
+                       cp++;
+                       if (el->el_flags & UNBUFFERED)
+                               break;
+                       if (cp[-1] == '\r' || cp[-1] == '\n')
+                               break;
+               }
+               if (num == -1) {
+                       if (errno == EINTR)
+                               cp = el->el_line.buffer;
+                       el->el_errno = errno;
+               }
+
+               goto noedit;
+       }
+
+
+#ifdef FIONREAD
+       if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
+               long chrs = 0;
+
+               (void) ioctl(el->el_infd, FIONREAD, &chrs);
+               if (chrs == 0) {
+                       if (tty_rawmode(el) < 0) {
+                               errno = 0;
+                               *nread = 0;
+                               return NULL;
+                       }
+               }
+       }
+#endif /* FIONREAD */
+
+       if ((el->el_flags & UNBUFFERED) == 0)
+               read_prepare(el);
+
+       if (el->el_flags & EDIT_DISABLED) {
+               size_t idx;
+
+               if ((el->el_flags & UNBUFFERED) == 0)
+                       cp = el->el_line.buffer;
+               else
+                       cp = el->el_line.lastchar;
+
+               terminal__flush(el);
+
+               while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
+                       /* make sure there is space next character */
+                       if (cp + 1 >= el->el_line.limit) {
+                               idx = (size_t)(cp - el->el_line.buffer);
+                               if (!ch_enlargebufs(el, (size_t)2))
+                                       break;
+                               cp = &el->el_line.buffer[idx];
+                       }
+                       cp++;
+                       crlf = cp[-1] == '\r' || cp[-1] == '\n';
+                       if (el->el_flags & UNBUFFERED)
+                               break;
+                       if (crlf)
+                               break;
+               }
+
+               if (num == -1) {
+                       if (errno == EINTR)
+                               cp = el->el_line.buffer;
+                       el->el_errno = errno;
+               }
+
+               goto noedit;
+       }
+
+       for (num = OKCMD; num == OKCMD;) {      /* while still editing this
+                                                * line */
+#ifdef DEBUG_EDIT
+               read_debug(el);
+#endif /* DEBUG_EDIT */
+               /* if EOF or error */
+               if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
+                       num = -1;
+#ifdef DEBUG_READ
+                       (void) fprintf(el->el_errfile,
+                           "Returning from el_gets %d\n", num);
+#endif /* DEBUG_READ */
+                       break;
+               }
+               if (el->el_errno == EINTR) {
+                       el->el_line.buffer[0] = '\0';
+                       el->el_line.lastchar =
+                           el->el_line.cursor = el->el_line.buffer;
+                       break;
+               }
+               if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) {   /* BUG CHECK command */
+#ifdef DEBUG_EDIT
+                       (void) fprintf(el->el_errfile,
+                           "ERROR: illegal command from key 0%o\r\n", ch);
+#endif /* DEBUG_EDIT */
+                       continue;       /* try again */
+               }
+               /* now do the real command */
+#ifdef DEBUG_READ
+               {
+                       el_bindings_t *b;
+                       for (b = el->el_map.help; b->name; b++)
+                               if (b->func == cmdnum)
+                                       break;
+                       if (b->name)
+                               (void) fprintf(el->el_errfile,
+                                   "Executing %s\n", b->name);
+                       else
+                               (void) fprintf(el->el_errfile,
+                                   "Error command = %d\n", cmdnum);
+               }
+#endif /* DEBUG_READ */
+               /* vi redo needs these way down the levels... */
+               el->el_state.thiscmd = cmdnum;
+               el->el_state.thisch = ch;
+               if (el->el_map.type == MAP_VI &&
+                   el->el_map.current == el->el_map.key &&
+                   el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
+                       if (cmdnum == VI_DELETE_PREV_CHAR &&
+                           el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
+                           && Isprint(el->el_chared.c_redo.pos[-1]))
+                               el->el_chared.c_redo.pos--;
+                       else
+                               *el->el_chared.c_redo.pos++ = ch;
+               }
+               retval = (*el->el_map.func[cmdnum]) (el, ch);
+#ifdef DEBUG_READ
+               (void) fprintf(el->el_errfile,
+                       "Returned state %d\n", retval );
+#endif /* DEBUG_READ */
+
+               /* save the last command here */
+               el->el_state.lastcmd = cmdnum;
+
+               /* use any return value */
+               switch (retval) {
+               case CC_CURSOR:
+                       re_refresh_cursor(el);
+                       break;
+
+               case CC_REDISPLAY:
+                       re_clear_lines(el);
+                       re_clear_display(el);
+                       /* FALLTHROUGH */
+
+               case CC_REFRESH:
+                       re_refresh(el);
+                       break;
+
+               case CC_REFRESH_BEEP:
+                       re_refresh(el);
+                       terminal_beep(el);
+                       break;
+
+               case CC_NORM:   /* normal char */
+                       break;
+
+               case CC_ARGHACK:        /* Suggested by Rich Salz */
+                       /* <rsalz@pineapple.bbn.com> */
+                       continue;       /* keep going... */
+
+               case CC_EOF:    /* end of file typed */
+                       if ((el->el_flags & UNBUFFERED) == 0)
+                               num = 0;
+                       else if (num == -1) {
+                               *el->el_line.lastchar++ = CONTROL('d');
+                               el->el_line.cursor = el->el_line.lastchar;
+                               num = 1;
+                       }
+                       break;
+
+               case CC_NEWLINE:        /* normal end of line */
+                       num = (int)(el->el_line.lastchar - el->el_line.buffer);
+                       break;
+
+               case CC_FATAL:  /* fatal error, reset to known state */
+#ifdef DEBUG_READ
+                       (void) fprintf(el->el_errfile,
+                           "*** editor fatal ERROR ***\r\n\n");
+#endif /* DEBUG_READ */
+                       /* put (real) cursor in a known place */
+                       re_clear_display(el);   /* reset the display stuff */
+                       ch_reset(el, 1);        /* reset the input pointers */
+                       re_refresh(el); /* print the prompt again */
+                       break;
+
+               case CC_ERROR:
+               default:        /* functions we don't know about */
+#ifdef DEBUG_READ
+                       (void) fprintf(el->el_errfile,
+                           "*** editor ERROR ***\r\n\n");
+#endif /* DEBUG_READ */
+                       terminal_beep(el);
+                       terminal__flush(el);
+                       break;
+               }
+               el->el_state.argument = 1;
+               el->el_state.doingarg = 0;
+               el->el_chared.c_vcmd.action = NOP;
+               if (el->el_flags & UNBUFFERED)
+                       break;
+       }
+
+       terminal__flush(el);            /* flush any buffered output */
+       /* make sure the tty is set up correctly */
+       if ((el->el_flags & UNBUFFERED) == 0) {
+               read_finish(el);
+               *nread = num != -1 ? num : 0;
+       } else {
+               *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
+       }
+       goto done;
+noedit:
+       el->el_line.cursor = el->el_line.lastchar = cp;
+       *cp = '\0';
+       *nread = (int)(el->el_line.cursor - el->el_line.buffer);
+done:
+       if (*nread == 0) {
+               if (num == -1) {
+                       *nread = -1;
+                       errno = el->el_errno;
+               }
+               return NULL;
+       } else
+               return el->el_line.buffer;
+}
diff --git a/lib/libedit/read.h b/lib/libedit/read.h
new file mode 100644 (file)
index 0000000..852606a
--- /dev/null
@@ -0,0 +1,50 @@
+/*     $NetBSD: read.h,v 1.7 2009/12/30 22:37:40 christos Exp $        */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Anthony Mallet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * el.read.h: Character reading functions
+ */
+#ifndef        _h_el_read
+#define        _h_el_read
+
+typedef int (*el_rfunc_t)(EditLine *, Char *);
+
+typedef struct el_read_t {
+       el_rfunc_t      read_char;      /* Function to read a character */
+} el_read_t;
+protected int          read_init(EditLine *);
+protected void         read_prepare(EditLine *);
+protected void         read_finish(EditLine *);
+protected int          el_read_setfn(EditLine *, el_rfunc_t);
+protected el_rfunc_t   el_read_getfn(EditLine *);
+
+#endif /* _h_el_read */
diff --git a/lib/libedit/readline.c b/lib/libedit/readline.c
new file mode 100644 (file)
index 0000000..8d6a1b4
--- /dev/null
@@ -0,0 +1,2274 @@
+/*     $NetBSD: readline.c,v 1.106 2012/10/12 23:35:02 christos Exp $  */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+__RCSID("$NetBSD: readline.c,v 1.106 2012/10/12 23:35:02 christos Exp $");
+#endif /* not lint && not SCCSID */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <vis.h>
+
+#include "readline/readline.h"
+#include "el.h"
+#include "fcns.h"              /* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+void rl_prep_terminal(int);
+void rl_deprep_terminal(void);
+
+/* for rl_complete() */
+#define TAB            '\r'
+
+/* see comment at the #ifdef for sense of this */
+/* #define GDB_411_HACK */
+
+/* readline compatibility stuff - look at readline sources/documentation */
+/* to see what these variables mean */
+const char *rl_library_version = "EditLine wrapper";
+int rl_readline_version = RL_READLINE_VERSION;
+static char empty[] = { '\0' };
+static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
+static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
+    '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
+char *rl_readline_name = empty;
+FILE *rl_instream = NULL;
+FILE *rl_outstream = NULL;
+int rl_point = 0;
+int rl_end = 0;
+char *rl_line_buffer = NULL;
+VCPFunction *rl_linefunc = NULL;
+int rl_done = 0;
+VFunction *rl_event_hook = NULL;
+KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
+    emacs_meta_keymap,
+    emacs_ctlx_keymap;
+
+int history_base = 1;          /* probably never subject to change */
+int history_length = 0;
+int max_input_history = 0;
+char history_expansion_char = '!';
+char history_subst_char = '^';
+char *history_no_expand_chars = expand_chars;
+Function *history_inhibit_expansion_function = NULL;
+char *history_arg_extract(int start, int end, const char *str);
+
+int rl_inhibit_completion = 0;
+int rl_attempted_completion_over = 0;
+char *rl_basic_word_break_characters = break_chars;
+char *rl_completer_word_break_characters = NULL;
+char *rl_completer_quote_characters = NULL;
+Function *rl_completion_entry_function = NULL;
+char *(*rl_completion_word_break_hook)(void) = NULL;
+CPPFunction *rl_attempted_completion_function = NULL;
+Function *rl_pre_input_hook = NULL;
+Function *rl_startup1_hook = NULL;
+int (*rl_getc_function)(FILE *) = NULL;
+char *rl_terminal_name = NULL;
+int rl_already_prompted = 0;
+int rl_filename_completion_desired = 0;
+int rl_ignore_completion_duplicates = 0;
+int rl_catch_signals = 1;
+int readline_echoing_p = 1;
+int _rl_print_completions_horizontally = 0;
+VFunction *rl_redisplay_function = NULL;
+Function *rl_startup_hook = NULL;
+VFunction *rl_completion_display_matches_hook = NULL;
+VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
+VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
+KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
+
+/*
+ * The current prompt string.
+ */
+char *rl_prompt = NULL;
+/*
+ * This is set to character indicating type of completion being done by
+ * rl_complete_internal(); this is available for application completion
+ * functions.
+ */
+int rl_completion_type = 0;
+
+/*
+ * If more than this number of items results from query for possible
+ * completions, we ask user if they are sure to really display the list.
+ */
+int rl_completion_query_items = 100;
+
+/*
+ * List of characters which are word break characters, but should be left
+ * in the parsed text when it is passed to the completion function.
+ * Shell uses this to help determine what kind of completing to do.
+ */
+char *rl_special_prefixes = NULL;
+
+/*
+ * This is the character appended to the completed words if at the end of
+ * the line. Default is ' ' (a space).
+ */
+int rl_completion_append_character = ' ';
+
+/* stuff below is used internally by libedit for readline emulation */
+
+static History *h = NULL;
+static EditLine *e = NULL;
+static Function *map[256];
+static jmp_buf topbuf;
+
+/* internal functions */
+static unsigned char    _el_rl_complete(EditLine *, int);
+static unsigned char    _el_rl_tstp(EditLine *, int);
+static char            *_get_prompt(EditLine *);
+static int              _getc_function(EditLine *, char *);
+static HIST_ENTRY      *_move_history(int);
+static int              _history_expand_command(const char *, size_t, size_t,
+    char **);
+static char            *_rl_compat_sub(const char *, const char *,
+    const char *, int);
+static int              _rl_event_read_char(EditLine *, char *);
+static void             _rl_update_pos(void);
+
+
+/* ARGSUSED */
+static char *
+_get_prompt(EditLine *el __attribute__((__unused__)))
+{
+       rl_already_prompted = 1;
+       return rl_prompt;
+}
+
+
+/*
+ * generic function for moving around history
+ */
+static HIST_ENTRY *
+_move_history(int op)
+{
+       HistEvent ev;
+       static HIST_ENTRY rl_he;
+
+       if (history(h, &ev, op) != 0)
+               return NULL;
+
+       rl_he.line = ev.str;
+       rl_he.data = NULL;
+
+       return &rl_he;
+}
+
+
+/*
+ * read one key from user defined input function
+ */
+static int
+/*ARGSUSED*/
+_getc_function(EditLine *el __attribute__((__unused__)), char *c)
+{
+       int i;
+
+       i = (*rl_getc_function)(NULL);
+       if (i == -1)
+               return 0;
+       *c = (char)i;
+       return 1;
+}
+
+static void
+_resize_fun(EditLine *el, void *a)
+{
+       const LineInfo *li;
+       char **ap = a;
+
+       li = el_line(el);
+       /* a cheesy way to get rid of const cast. */
+       *ap = memchr(li->buffer, *li->buffer, (size_t)1);
+}
+
+static const char *
+_default_history_file(void)
+{
+       struct passwd *p;
+       static char path[PATH_MAX];
+
+       if (*path)
+               return path;
+       if ((p = getpwuid(getuid())) == NULL)
+               return NULL;
+       (void)snprintf(path, sizeof(path), "%s/.history", p->pw_dir);
+       return path;
+}
+
+/*
+ * READLINE compatibility stuff
+ */
+
+/*
+ * Set the prompt
+ */
+int
+rl_set_prompt(const char *prompt)
+{
+       char *p;
+
+       if (!prompt)
+               prompt = "";
+       if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) 
+               return 0;
+       if (rl_prompt)
+               el_free(rl_prompt);
+       rl_prompt = strdup(prompt);
+       if (rl_prompt == NULL)
+               return -1;
+
+       while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL)
+               *p = RL_PROMPT_START_IGNORE;
+
+       return 0;
+}
+
+/*
+ * initialize rl compat stuff
+ */
+int
+rl_initialize(void)
+{
+       HistEvent ev;
+       int editmode = 1;
+       struct termios t;
+
+       if (e != NULL)
+               el_end(e);
+       if (h != NULL)
+               history_end(h);
+
+       if (!rl_instream)
+               rl_instream = stdin;
+       if (!rl_outstream)
+               rl_outstream = stdout;
+
+       /*
+        * See if we don't really want to run the editor
+        */
+       if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
+               editmode = 0;
+
+       e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
+
+       if (!editmode)
+               el_set(e, EL_EDITMODE, 0);
+
+       h = history_init();
+       if (!e || !h)
+               return -1;
+
+       history(h, &ev, H_SETSIZE, INT_MAX);    /* unlimited */
+       history_length = 0;
+       max_input_history = INT_MAX;
+       el_set(e, EL_HIST, history, h);
+
+       /* Setup resize function */
+       el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
+
+       /* setup getc function if valid */
+       if (rl_getc_function)
+               el_set(e, EL_GETCFN, _getc_function);
+
+       /* for proper prompt printing in readline() */
+       if (rl_set_prompt("") == -1) {
+               history_end(h);
+               el_end(e);
+               return -1;
+       }
+       el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);
+       el_set(e, EL_SIGNAL, rl_catch_signals);
+
+       /* set default mode to "emacs"-style and read setting afterwards */
+       /* so this can be overriden */
+       el_set(e, EL_EDITOR, "emacs");
+       if (rl_terminal_name != NULL)
+               el_set(e, EL_TERMINAL, rl_terminal_name);
+       else
+               el_get(e, EL_TERMINAL, &rl_terminal_name);
+
+       /*
+        * Word completion - this has to go AFTER rebinding keys
+        * to emacs-style.
+        */
+       el_set(e, EL_ADDFN, "rl_complete",
+           "ReadLine compatible completion function",
+           _el_rl_complete);
+       el_set(e, EL_BIND, "^I", "rl_complete", NULL);
+
+       /*
+        * Send TSTP when ^Z is pressed.
+        */
+       el_set(e, EL_ADDFN, "rl_tstp",
+           "ReadLine compatible suspend function",
+           _el_rl_tstp);
+       el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
+               
+       /* read settings from configuration file */
+       el_source(e, NULL);
+
+       /*
+        * Unfortunately, some applications really do use rl_point
+        * and rl_line_buffer directly.
+        */
+       _resize_fun(e, &rl_line_buffer);
+       _rl_update_pos();
+
+       if (rl_startup_hook)
+               (*rl_startup_hook)(NULL, 0);
+
+       return 0;
+}
+
+
+/*
+ * read one line from input stream and return it, chomping
+ * trailing newline (if there is any)
+ */
+char *
+readline(const char *p)
+{
+       HistEvent ev;
+       const char * volatile prompt = p;
+       int count;
+       const char *ret;
+       char *buf;
+       static int used_event_hook;
+
+       if (e == NULL || h == NULL)
+               rl_initialize();
+
+       rl_done = 0;
+
+       (void)setjmp(topbuf);
+
+       /* update prompt accordingly to what has been passed */
+       if (rl_set_prompt(prompt) == -1)
+               return NULL;
+
+       if (rl_pre_input_hook)
+               (*rl_pre_input_hook)(NULL, 0);
+
+       if (rl_event_hook && !(e->el_flags&NO_TTY)) {
+               el_set(e, EL_GETCFN, _rl_event_read_char);
+               used_event_hook = 1;
+       }
+
+       if (!rl_event_hook && used_event_hook) {
+               el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
+               used_event_hook = 0;
+       }
+
+       rl_already_prompted = 0;
+
+       /* get one line from input stream */
+       ret = el_gets(e, &count);
+
+       if (ret && count > 0) {
+               int lastidx;
+
+               buf = strdup(ret);
+               if (buf == NULL)
+                       return NULL;
+               lastidx = count - 1;
+               if (buf[lastidx] == '\n')
+                       buf[lastidx] = '\0';
+       } else
+               buf = NULL;
+
+       history(h, &ev, H_GETSIZE);
+       history_length = ev.num;
+
+       return buf;
+}
+
+/*
+ * history functions
+ */
+
+/*
+ * is normally called before application starts to use
+ * history expansion functions
+ */
+void
+using_history(void)
+{
+       if (h == NULL || e == NULL)
+               rl_initialize();
+}
+
+
+/*
+ * substitute ``what'' with ``with'', returning resulting string; if
+ * globally == 1, substitutes all occurrences of what, otherwise only the
+ * first one
+ */
+static char *
+_rl_compat_sub(const char *str, const char *what, const char *with,
+    int globally)
+{
+       const   char    *s;
+       char    *r, *result;
+       size_t  len, with_len, what_len;
+
+       len = strlen(str);
+       with_len = strlen(with);
+       what_len = strlen(what);
+
+       /* calculate length we need for result */
+       s = str;
+       while (*s) {
+               if (*s == *what && !strncmp(s, what, what_len)) {
+                       len += with_len - what_len;
+                       if (!globally)
+                               break;
+                       s += what_len;
+               } else
+                       s++;
+       }
+       r = result = el_malloc((len + 1) * sizeof(*r));
+       if (result == NULL)
+               return NULL;
+       s = str;
+       while (*s) {
+               if (*s == *what && !strncmp(s, what, what_len)) {
+                       (void)strncpy(r, with, with_len);
+                       r += with_len;
+                       s += what_len;
+                       if (!globally) {
+                               (void)strcpy(r, s);
+                               return result;
+                       }
+               } else
+                       *r++ = *s++;
+       }
+       *r = '\0';
+       return result;
+}
+
+static char    *last_search_pat;       /* last !?pat[?] search pattern */
+static char    *last_search_match;     /* last !?pat[?] that matched */
+
+const char *
+get_history_event(const char *cmd, int *cindex, int qchar)
+{
+       int idx, sign, sub, num, begin, ret;
+       size_t len;
+       char    *pat;
+       const char *rptr;
+       HistEvent ev;
+
+       idx = *cindex;
+       if (cmd[idx++] != history_expansion_char)
+               return NULL;
+
+       /* find out which event to take */
+       if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
+               if (history(h, &ev, H_FIRST) != 0)
+                       return NULL;
+               *cindex = cmd[idx]? (idx + 1):idx;
+               return ev.str;
+       }
+       sign = 0;
+       if (cmd[idx] == '-') {
+               sign = 1;
+               idx++;
+       }
+
+       if ('0' <= cmd[idx] && cmd[idx] <= '9') {
+               HIST_ENTRY *rl_he;
+
+               num = 0;
+               while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
+                       num = num * 10 + cmd[idx] - '0';
+                       idx++;
+               }
+               if (sign)
+                       num = history_length - num + 1;
+
+               if (!(rl_he = history_get(num)))
+                       return NULL;
+
+               *cindex = idx;
+               return rl_he->line;
+       }
+       sub = 0;
+       if (cmd[idx] == '?') {
+               sub = 1;
+               idx++;
+       }
+       begin = idx;
+       while (cmd[idx]) {
+               if (cmd[idx] == '\n')
+                       break;
+               if (sub && cmd[idx] == '?')
+                       break;
+               if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
+                                   || cmd[idx] == '\t' || cmd[idx] == qchar))
+                       break;
+               idx++;
+       }
+       len = (size_t)idx - (size_t)begin;
+       if (sub && cmd[idx] == '?')
+               idx++;
+       if (sub && len == 0 && last_search_pat && *last_search_pat)
+               pat = last_search_pat;
+       else if (len == 0)
+               return NULL;
+       else {
+               if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL)
+                       return NULL;
+               (void)strncpy(pat, cmd + begin, len);
+               pat[len] = '\0';
+       }
+
+       if (history(h, &ev, H_CURR) != 0) {
+               if (pat != last_search_pat)
+                       el_free(pat);
+               return NULL;
+       }
+       num = ev.num;
+
+       if (sub) {
+               if (pat != last_search_pat) {
+                       if (last_search_pat)
+                               el_free(last_search_pat);
+                       last_search_pat = pat;
+               }
+               ret = history_search(pat, -1);
+       } else
+               ret = history_search_prefix(pat, -1);
+
+       if (ret == -1) {
+               /* restore to end of list on failed search */
+               history(h, &ev, H_FIRST);
+               (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
+               if (pat != last_search_pat)
+                       el_free(pat);
+               return NULL;
+       }
+
+       if (sub && len) {
+               if (last_search_match && last_search_match != pat)
+                       el_free(last_search_match);
+               last_search_match = pat;
+       }
+
+       if (pat != last_search_pat)
+               el_free(pat);
+
+       if (history(h, &ev, H_CURR) != 0)
+               return NULL;
+       *cindex = idx;
+       rptr = ev.str;
+
+       /* roll back to original position */
+       (void)history(h, &ev, H_SET, num);
+
+       return rptr;
+}
+
+/*
+ * the real function doing history expansion - takes as argument command
+ * to do and data upon which the command should be executed
+ * does expansion the way I've understood readline documentation
+ *
+ * returns 0 if data was not modified, 1 if it was and 2 if the string
+ * should be only printed and not executed; in case of error,
+ * returns -1 and *result points to NULL
+ * it's callers responsibility to free() string returned in *result
+ */
+static int
+_history_expand_command(const char *command, size_t offs, size_t cmdlen,
+    char **result)
+{
+       char *tmp, *search = NULL, *aptr;
+       const char *ptr, *cmd;
+       static char *from = NULL, *to = NULL;
+       int start, end, idx, has_mods = 0;
+       int p_on = 0, g_on = 0;
+
+       *result = NULL;
+       aptr = NULL;
+       ptr = NULL;
+
+       /* First get event specifier */
+       idx = 0;
+
+       if (strchr(":^*$", command[offs + 1])) {
+               char str[4];
+               /*
+               * "!:" is shorthand for "!!:".
+               * "!^", "!*" and "!$" are shorthand for
+               * "!!:^", "!!:*" and "!!:$" respectively.
+               */
+               str[0] = str[1] = '!';
+               str[2] = '0';
+               ptr = get_history_event(str, &idx, 0);
+               idx = (command[offs + 1] == ':')? 1:0;
+               has_mods = 1;
+       } else {
+               if (command[offs + 1] == '#') {
+                       /* use command so far */
+                       if ((aptr = el_malloc((offs + 1) * sizeof(*aptr)))
+                           == NULL)
+                               return -1;
+                       (void)strncpy(aptr, command, offs);
+                       aptr[offs] = '\0';
+                       idx = 1;
+               } else {
+                       int     qchar;
+
+                       qchar = (offs > 0 && command[offs - 1] == '"')? '"':0;
+                       ptr = get_history_event(command + offs, &idx, qchar);
+               }
+               has_mods = command[offs + (size_t)idx] == ':';
+       }
+
+       if (ptr == NULL && aptr == NULL)
+               return -1;
+
+       if (!has_mods) {
+               *result = strdup(aptr ? aptr : ptr);
+               if (aptr)
+                       el_free(aptr);
+               if (*result == NULL)
+                       return -1;
+               return 1;
+       }
+
+       cmd = command + offs + idx + 1;
+
+       /* Now parse any word designators */
+
+       if (*cmd == '%')        /* last word matched by ?pat? */
+               tmp = strdup(last_search_match? last_search_match:"");
+       else if (strchr("^*$-0123456789", *cmd)) {
+               start = end = -1;
+               if (*cmd == '^')
+                       start = end = 1, cmd++;
+               else if (*cmd == '$')
+                       start = -1, cmd++;
+               else if (*cmd == '*')
+                       start = 1, cmd++;
+              else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
+                       start = 0;
+                       while (*cmd && '0' <= *cmd && *cmd <= '9')
+                               start = start * 10 + *cmd++ - '0';
+
+                       if (*cmd == '-') {
+                               if (isdigit((unsigned char) cmd[1])) {
+                                       cmd++;
+                                       end = 0;
+                                       while (*cmd && '0' <= *cmd && *cmd <= '9')
+                                               end = end * 10 + *cmd++ - '0';
+                               } else if (cmd[1] == '$') {
+                                       cmd += 2;
+                                       end = -1;
+                               } else {
+                                       cmd++;
+                                       end = -2;
+                               }
+                       } else if (*cmd == '*')
+                               end = -1, cmd++;
+                       else
+                               end = start;
+               }
+               tmp = history_arg_extract(start, end, aptr? aptr:ptr);
+               if (tmp == NULL) {
+                       (void)fprintf(rl_outstream, "%s: Bad word specifier",
+                           command + offs + idx);
+                       if (aptr)
+                               el_free(aptr);
+                       return -1;
+               }
+       } else
+               tmp = strdup(aptr? aptr:ptr);
+
+       if (aptr)
+               el_free(aptr);
+
+       if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
+               *result = tmp;
+               return 1;
+       }
+
+       for (; *cmd; cmd++) {
+               if (*cmd == ':')
+                       continue;
+               else if (*cmd == 'h') {         /* remove trailing path */
+                       if ((aptr = strrchr(tmp, '/')) != NULL)
+                               *aptr = '\0';
+               } else if (*cmd == 't') {       /* remove leading path */
+                       if ((aptr = strrchr(tmp, '/')) != NULL) {
+                               aptr = strdup(aptr + 1);
+                               el_free(tmp);
+                               tmp = aptr;
+                       }
+               } else if (*cmd == 'r') {       /* remove trailing suffix */
+                       if ((aptr = strrchr(tmp, '.')) != NULL)
+                               *aptr = '\0';
+               } else if (*cmd == 'e') {       /* remove all but suffix */
+                       if ((aptr = strrchr(tmp, '.')) != NULL) {
+                               aptr = strdup(aptr);
+                               el_free(tmp);
+                               tmp = aptr;
+                       }
+               } else if (*cmd == 'p')         /* print only */
+                       p_on = 1;
+               else if (*cmd == 'g')
+                       g_on = 2;
+               else if (*cmd == 's' || *cmd == '&') {
+                       char *what, *with, delim;
+                       size_t len, from_len;
+                       size_t size;
+
+                       if (*cmd == '&' && (from == NULL || to == NULL))
+                               continue;
+                       else if (*cmd == 's') {
+                               delim = *(++cmd), cmd++;
+                               size = 16;
+                               what = el_realloc(from, size * sizeof(*what));
+                               if (what == NULL) {
+                                       el_free(from);
+                                       el_free(tmp);
+                                       return 0;
+                               }
+                               len = 0;
+                               for (; *cmd && *cmd != delim; cmd++) {
+                                       if (*cmd == '\\' && cmd[1] == delim)
+                                               cmd++;
+                                       if (len >= size) {
+                                               char *nwhat;
+                                               nwhat = el_realloc(what,
+                                                   (size <<= 1) *
+                                                   sizeof(*nwhat));
+                                               if (nwhat == NULL) {
+                                                       el_free(what);
+                                                       el_free(tmp);
+                                                       return 0;
+                                               }
+                                               what = nwhat;
+                                       }
+                                       what[len++] = *cmd;
+                               }
+                               what[len] = '\0';
+                               from = what;
+                               if (*what == '\0') {
+                                       el_free(what);
+                                       if (search) {
+                                               from = strdup(search);
+                                               if (from == NULL) {
+                                                       el_free(tmp);
+                                                       return 0;
+                                               }
+                                       } else {
+                                               from = NULL;
+                                               el_free(tmp);
+                                               return -1;
+                                       }
+                               }
+                               cmd++;  /* shift after delim */
+                               if (!*cmd)
+                                       continue;
+
+                               size = 16;
+                               with = el_realloc(to, size * sizeof(*with));
+                               if (with == NULL) {
+                                       el_free(to);
+                                       el_free(tmp);
+                                       return -1;
+                               }
+                               len = 0;
+                               from_len = strlen(from);
+                               for (; *cmd && *cmd != delim; cmd++) {
+                                       if (len + from_len + 1 >= size) {
+                                               char *nwith;
+                                               size += from_len + 1;
+                                               nwith = el_realloc(with,
+                                                   size * sizeof(*nwith));
+                                               if (nwith == NULL) {
+                                                       el_free(with);
+                                                       el_free(tmp);
+                                                       return -1;
+                                               }
+                                               with = nwith;
+                                       }
+                                       if (*cmd == '&') {
+                                               /* safe */
+                                               (void)strcpy(&with[len], from);
+                                               len += from_len;
+                                               continue;
+                                       }
+                                       if (*cmd == '\\'
+                                           && (*(cmd + 1) == delim
+                                               || *(cmd + 1) == '&'))
+                                               cmd++;
+                                       with[len++] = *cmd;
+                               }
+                               with[len] = '\0';
+                               to = with;
+                       }
+
+                       aptr = _rl_compat_sub(tmp, from, to, g_on);
+                       if (aptr) {
+                               el_free(tmp);
+                               tmp = aptr;
+                       }
+                       g_on = 0;
+               }
+       }
+       *result = tmp;
+       return p_on? 2:1;
+}
+
+
+/*
+ * csh-style history expansion
+ */
+int
+history_expand(char *str, char **output)
+{
+       int ret = 0;
+       size_t idx, i, size;
+       char *tmp, *result;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       if (history_expansion_char == 0) {
+               *output = strdup(str);
+               return 0;
+       }
+
+       *output = NULL;
+       if (str[0] == history_subst_char) {
+               /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
+               *output = el_malloc((strlen(str) + 4 + 1) * sizeof(**output));
+               if (*output == NULL)
+                       return 0;
+               (*output)[0] = (*output)[1] = history_expansion_char;
+               (*output)[2] = ':';
+               (*output)[3] = 's';
+               (void)strcpy((*output) + 4, str);
+               str = *output;
+       } else {
+               *output = strdup(str);
+               if (*output == NULL)
+                       return 0;
+       }
+
+#define ADD_STRING(what, len, fr)                                      \
+       {                                                               \
+               if (idx + len + 1 > size) {                             \
+                       char *nresult = el_realloc(result,              \
+                           (size += len + 1) * sizeof(*nresult));      \
+                       if (nresult == NULL) {                          \
+                               el_free(*output);                       \
+                               if (/*CONSTCOND*/fr)                    \
+                                       el_free(tmp);                   \
+                               return 0;                               \
+                       }                                               \
+                       result = nresult;                               \
+               }                                                       \
+               (void)strncpy(&result[idx], what, len);                 \
+               idx += len;                                             \
+               result[idx] = '\0';                                     \
+       }
+
+       result = NULL;
+       size = idx = 0;
+       tmp = NULL;
+       for (i = 0; str[i];) {
+               int qchar, loop_again;
+               size_t len, start, j;
+
+               qchar = 0;
+               loop_again = 1;
+               start = j = i;
+loop:
+               for (; str[j]; j++) {
+                       if (str[j] == '\\' &&
+                           str[j + 1] == history_expansion_char) {
+                               (void)strcpy(&str[j], &str[j + 1]);
+                               continue;
+                       }
+                       if (!loop_again) {
+                               if (isspace((unsigned char) str[j])
+                                   || str[j] == qchar)
+                                       break;
+                       }
+                       if (str[j] == history_expansion_char
+                           && !strchr(history_no_expand_chars, str[j + 1])
+                           && (!history_inhibit_expansion_function ||
+                           (*history_inhibit_expansion_function)(str,
+                           (int)j) == 0))
+                               break;
+               }
+
+               if (str[j] && loop_again) {
+                       i = j;
+                       qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
+                       j++;
+                       if (str[j] == history_expansion_char)
+                               j++;
+                       loop_again = 0;
+                       goto loop;
+               }
+               len = i - start;
+               ADD_STRING(&str[start], len, 0);
+
+               if (str[i] == '\0' || str[i] != history_expansion_char) {
+                       len = j - i;
+                       ADD_STRING(&str[i], len, 0);
+                       if (start == 0)
+                               ret = 0;
+                       else
+                               ret = 1;
+                       break;
+               }
+               ret = _history_expand_command (str, i, (j - i), &tmp);
+               if (ret > 0 && tmp) {
+                       len = strlen(tmp);
+                       ADD_STRING(tmp, len, 1);
+               }
+               if (tmp) {
+                       el_free(tmp);
+                       tmp = NULL;
+               }
+               i = j;
+       }
+
+       /* ret is 2 for "print only" option */
+       if (ret == 2) {
+               add_history(result);
+#ifdef GDB_411_HACK
+               /* gdb 4.11 has been shipped with readline, where */
+               /* history_expand() returned -1 when the line     */
+               /* should not be executed; in readline 2.1+       */
+               /* it should return 2 in such a case              */
+               ret = -1;
+#endif
+       }
+       el_free(*output);
+       *output = result;
+
+       return ret;
+}
+
+/*
+* Return a string consisting of arguments of "str" from "start" to "end".
+*/
+char *
+history_arg_extract(int start, int end, const char *str)
+{
+       size_t  i, len, max;
+       char    **arr, *result = NULL;
+
+       arr = history_tokenize(str);
+       if (!arr)
+               return NULL;
+       if (arr && *arr == NULL)
+               goto out;
+
+       for (max = 0; arr[max]; max++)
+               continue;
+       max--;
+
+       if (start == '$')
+               start = (int)max;
+       if (end == '$')
+               end = (int)max;
+       if (end < 0)
+               end = (int)max + end + 1;
+       if (start < 0)
+               start = end;
+
+       if (start < 0 || end < 0 || (size_t)start > max ||
+           (size_t)end > max || start > end)
+               goto out;
+
+       for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
+               len += strlen(arr[i]) + 1;
+       len++;
+       result = el_malloc(len * sizeof(*result));
+       if (result == NULL)
+               goto out;
+
+       for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
+               (void)strcpy(result + len, arr[i]);
+               len += strlen(arr[i]);
+               if (i < (size_t)end)
+                       result[len++] = ' ';
+       }
+       result[len] = '\0';
+
+out:
+       for (i = 0; arr[i]; i++)
+               el_free(arr[i]);
+       el_free(arr);
+
+       return result;
+}
+
+/*
+ * Parse the string into individual tokens,
+ * similar to how shell would do it.
+ */
+char **
+history_tokenize(const char *str)
+{
+       int size = 1, idx = 0, i, start;
+       size_t len;
+       char **result = NULL, *temp, delim = '\0';
+
+       for (i = 0; str[i];) {
+               while (isspace((unsigned char) str[i]))
+                       i++;
+               start = i;
+               for (; str[i];) {
+                       if (str[i] == '\\') {
+                               if (str[i+1] != '\0')
+                                       i++;
+                       } else if (str[i] == delim)
+                               delim = '\0';
+                       else if (!delim &&
+                                   (isspace((unsigned char) str[i]) ||
+                               strchr("()<>;&|$", str[i])))
+                               break;
+                       else if (!delim && strchr("'`\"", str[i]))
+                               delim = str[i];
+                       if (str[i])
+                               i++;
+               }
+
+               if (idx + 2 >= size) {
+                       char **nresult;
+                       size <<= 1;
+                       nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
+                       if (nresult == NULL) {
+                               el_free(result);
+                               return NULL;
+                       }
+                       result = nresult;
+               }
+               len = (size_t)i - (size_t)start;
+               temp = el_malloc((size_t)(len + 1) * sizeof(*temp));
+               if (temp == NULL) {
+                       for (i = 0; i < idx; i++)
+                               el_free(result[i]);
+                       el_free(result);
+                       return NULL;
+               }
+               (void)strncpy(temp, &str[start], len);
+               temp[len] = '\0';
+               result[idx++] = temp;
+               result[idx] = NULL;
+               if (str[i])
+                       i++;
+       }
+       return result;
+}
+
+
+/*
+ * limit size of history record to ``max'' events
+ */
+void
+stifle_history(int max)
+{
+       HistEvent ev;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       if (history(h, &ev, H_SETSIZE, max) == 0)
+               max_input_history = max;
+}
+
+
+/*
+ * "unlimit" size of history - set the limit to maximum allowed int value
+ */
+int
+unstifle_history(void)
+{
+       HistEvent ev;
+       int omax;
+
+       history(h, &ev, H_SETSIZE, INT_MAX);
+       omax = max_input_history;
+       max_input_history = INT_MAX;
+       return omax;            /* some value _must_ be returned */
+}
+
+
+int
+history_is_stifled(void)
+{
+
+       /* cannot return true answer */
+       return max_input_history != INT_MAX;
+}
+
+static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
+
+int
+history_truncate_file (const char *filename, int nlines)
+{
+       int ret = 0;
+       FILE *fp, *tp;
+       char template[sizeof(_history_tmp_template)];
+       char buf[4096];
+       int fd;
+       char *cp;
+       off_t off;
+       int count = 0;
+       ssize_t left = 0;
+
+       if (filename == NULL && (filename = _default_history_file()) == NULL)
+               return errno;
+       if ((fp = fopen(filename, "r+")) == NULL)
+               return errno;
+       strcpy(template, _history_tmp_template);
+       if ((fd = mkstemp(template)) == -1) {
+               ret = errno;
+               goto out1;
+       }
+
+       if ((tp = fdopen(fd, "r+")) == NULL) {
+               close(fd);
+               ret = errno;
+               goto out2;
+       }
+
+       for(;;) {
+               if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
+                       if (ferror(fp)) {
+                               ret = errno;
+                               break;
+                       }
+                       if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
+                           (off_t)-1) {
+                               ret = errno;
+                               break;
+                       }
+                       left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
+                       if (ferror(fp)) {
+                               ret = errno;
+                               break;
+                       }
+                       if (left == 0) {
+                               count--;
+                               left = sizeof(buf);
+                       } else if (fwrite(buf, (size_t)left, (size_t)1, tp)
+                           != 1) {
+                               ret = errno;
+                               break;
+                       }
+                       fflush(tp);
+                       break;
+               }
+               if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
+                       ret = errno;
+                       break;
+               }
+               count++;
+       }
+       if (ret)
+               goto out3;
+       cp = buf + left - 1;
+       if(*cp != '\n')
+               cp++;
+       for(;;) {
+               while (--cp >= buf) {
+                       if (*cp == '\n') {
+                               if (--nlines == 0) {
+                                       if (++cp >= buf + sizeof(buf)) {
+                                               count++;
+                                               cp = buf;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+               if (nlines <= 0 || count == 0)
+                       break;
+               count--;
+               if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
+                       ret = errno;
+                       break;
+               }
+               if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
+                       if (ferror(tp)) {
+                               ret = errno;
+                               break;
+                       }
+                       ret = EAGAIN;
+                       break;
+               }
+               cp = buf + sizeof(buf);
+       }
+
+       if (ret || nlines > 0)
+               goto out3;
+
+       if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
+               ret = errno;
+               goto out3;
+       }
+
+       if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
+           (off_t)-1) {
+               ret = errno;
+               goto out3;
+       }
+
+       for(;;) {
+               if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
+                       if (ferror(fp))
+                               ret = errno;
+                       break;
+               }
+               if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
+                       ret = errno;
+                       break;
+               }
+       }
+       fflush(fp);
+       if((off = ftello(fp)) > 0)
+               (void)ftruncate(fileno(fp), off);
+out3:
+       fclose(tp);
+out2:
+       unlink(template);
+out1:
+       fclose(fp);
+
+       return ret;
+}
+
+
+/*
+ * read history from a file given
+ */
+int
+read_history(const char *filename)
+{
+       HistEvent ev;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+       if (filename == NULL && (filename = _default_history_file()) == NULL)
+               return errno;
+       return history(h, &ev, H_LOAD, filename) == -1 ?
+           (errno ? errno : EINVAL) : 0;
+}
+
+
+/*
+ * write history to a file given
+ */
+int
+write_history(const char *filename)
+{
+       HistEvent ev;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+       if (filename == NULL && (filename = _default_history_file()) == NULL)
+               return errno;
+       return history(h, &ev, H_SAVE, filename) == -1 ?
+           (errno ? errno : EINVAL) : 0;
+}
+
+
+/*
+ * returns history ``num''th event
+ *
+ * returned pointer points to static variable
+ */
+HIST_ENTRY *
+history_get(int num)
+{
+       static HIST_ENTRY she;
+       HistEvent ev;
+       int curr_num;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       /* save current position */
+       if (history(h, &ev, H_CURR) != 0)
+               return NULL;
+       curr_num = ev.num;
+
+       /* start from the oldest */
+       if (history(h, &ev, H_LAST) != 0)
+               return NULL;    /* error */
+
+       /* look forwards for event matching specified offset */
+       if (history(h, &ev, H_NEXT_EVDATA, num, &she.data))
+               return NULL;
+
+       she.line = ev.str;
+
+       /* restore pointer to where it was */
+       (void)history(h, &ev, H_SET, curr_num);
+
+       return &she;
+}
+
+
+/*
+ * add the line to history table
+ */
+int
+add_history(const char *line)
+{
+       HistEvent ev;
+
+       if (line == NULL)
+               return 0;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       (void)history(h, &ev, H_ENTER, line);
+       if (history(h, &ev, H_GETSIZE) == 0)
+               history_length = ev.num;
+
+       return !(history_length > 0); /* return 0 if all is okay */
+}
+
+
+/*
+ * remove the specified entry from the history list and return it.
+ */
+HIST_ENTRY *
+remove_history(int num)
+{
+       HIST_ENTRY *he;
+       HistEvent ev;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       if ((he = el_malloc(sizeof(*he))) == NULL)
+               return NULL;
+
+       if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
+               el_free(he);
+               return NULL;
+       }
+
+       he->line = ev.str;
+       if (history(h, &ev, H_GETSIZE) == 0)
+               history_length = ev.num;
+
+       return he;
+}
+
+
+/*
+ * replace the line and data of the num-th entry
+ */
+HIST_ENTRY *
+replace_history_entry(int num, const char *line, histdata_t data)
+{
+       HIST_ENTRY *he;
+       HistEvent ev;
+       int curr_num;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       /* save current position */
+       if (history(h, &ev, H_CURR) != 0)
+               return NULL;
+       curr_num = ev.num;
+
+       /* start from the oldest */
+       if (history(h, &ev, H_LAST) != 0)
+               return NULL;    /* error */
+
+       if ((he = el_malloc(sizeof(*he))) == NULL)
+               return NULL;
+
+       /* look forwards for event matching specified offset */
+       if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
+               goto out;
+
+       he->line = strdup(ev.str);
+       if (he->line == NULL)
+               goto out;
+
+       if (history(h, &ev, H_REPLACE, line, data))
+               goto out;
+
+       /* restore pointer to where it was */
+       if (history(h, &ev, H_SET, curr_num))
+               goto out;
+
+       return he;
+out:
+       el_free(he);
+       return NULL;
+}
+
+/*
+ * clear the history list - delete all entries
+ */
+void
+clear_history(void)
+{
+       HistEvent ev;
+
+       (void)history(h, &ev, H_CLEAR);
+       history_length = 0;
+}
+
+
+/*
+ * returns offset of the current history event
+ */
+int
+where_history(void)
+{
+       HistEvent ev;
+       int curr_num, off;
+
+       if (history(h, &ev, H_CURR) != 0)
+               return 0;
+       curr_num = ev.num;
+
+       (void)history(h, &ev, H_FIRST);
+       off = 1;
+       while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
+               off++;
+
+       return off;
+}
+
+
+/*
+ * returns current history event or NULL if there is no such event
+ */
+HIST_ENTRY *
+current_history(void)
+{
+
+       return _move_history(H_CURR);
+}
+
+
+/*
+ * returns total number of bytes history events' data are using
+ */
+int
+history_total_bytes(void)
+{
+       HistEvent ev;
+       int curr_num;
+       size_t size;
+
+       if (history(h, &ev, H_CURR) != 0)
+               return -1;
+       curr_num = ev.num;
+
+       (void)history(h, &ev, H_FIRST);
+       size = 0;
+       do
+               size += strlen(ev.str) * sizeof(*ev.str);
+       while (history(h, &ev, H_NEXT) == 0);
+
+       /* get to the same position as before */
+       history(h, &ev, H_PREV_EVENT, curr_num);
+
+       return (int)size;
+}
+
+
+/*
+ * sets the position in the history list to ``pos''
+ */
+int
+history_set_pos(int pos)
+{
+       HistEvent ev;
+       int curr_num;
+
+       if (pos >= history_length || pos < 0)
+               return -1;
+
+       (void)history(h, &ev, H_CURR);
+       curr_num = ev.num;
+
+       /*
+        * use H_DELDATA to set to nth history (without delete) by passing
+        * (void **)-1
+        */
+       if (history(h, &ev, H_DELDATA, pos, (void **)-1)) {
+               (void)history(h, &ev, H_SET, curr_num);
+               return -1;
+       }
+       return 0;
+}
+
+
+/*
+ * returns previous event in history and shifts pointer accordingly
+ */
+HIST_ENTRY *
+previous_history(void)
+{
+
+       return _move_history(H_PREV);
+}
+
+
+/*
+ * returns next event in history and shifts pointer accordingly
+ */
+HIST_ENTRY *
+next_history(void)
+{
+
+       return _move_history(H_NEXT);
+}
+
+
+/*
+ * searches for first history event containing the str
+ */
+int
+history_search(const char *str, int direction)
+{
+       HistEvent ev;
+       const char *strp;
+       int curr_num;
+
+       if (history(h, &ev, H_CURR) != 0)
+               return -1;
+       curr_num = ev.num;
+
+       for (;;) {
+               if ((strp = strstr(ev.str, str)) != NULL)
+                       return (int)(strp - ev.str);
+               if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
+                       break;
+       }
+       (void)history(h, &ev, H_SET, curr_num);
+       return -1;
+}
+
+
+/*
+ * searches for first history event beginning with str
+ */
+int
+history_search_prefix(const char *str, int direction)
+{
+       HistEvent ev;
+
+       return (history(h, &ev, direction < 0 ?
+           H_PREV_STR : H_NEXT_STR, str));
+}
+
+
+/*
+ * search for event in history containing str, starting at offset
+ * abs(pos); continue backward, if pos<0, forward otherwise
+ */
+/* ARGSUSED */
+int
+history_search_pos(const char *str,
+                  int direction __attribute__((__unused__)), int pos)
+{
+       HistEvent ev;
+       int curr_num, off;
+
+       off = (pos > 0) ? pos : -pos;
+       pos = (pos > 0) ? 1 : -1;
+
+       if (history(h, &ev, H_CURR) != 0)
+               return -1;
+       curr_num = ev.num;
+
+       if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
+               return -1;
+
+       for (;;) {
+               if (strstr(ev.str, str))
+                       return off;
+               if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
+                       break;
+       }
+
+       /* set "current" pointer back to previous state */
+       (void)history(h, &ev,
+           pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
+
+       return -1;
+}
+
+
+/********************************/
+/* completion functions */
+
+char *
+tilde_expand(char *name)
+{
+       return fn_tilde_expand(name);
+}
+
+char *
+filename_completion_function(const char *name, int state)
+{
+       return fn_filename_completion_function(name, state);
+}
+
+/*
+ * a completion generator for usernames; returns _first_ username
+ * which starts with supplied text
+ * text contains a partial username preceded by random character
+ * (usually '~'); state resets search from start (??? should we do that anyway)
+ * it's callers responsibility to free returned value
+ */
+char *
+username_completion_function(const char *text, int state)
+{
+#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
+       struct passwd pwres;
+       char pwbuf[1024];
+#endif
+       struct passwd *pass = NULL;
+
+       if (text[0] == '\0')
+               return NULL;
+
+       if (*text == '~')
+               text++;
+
+       if (state == 0)
+               setpwent();
+
+       while (
+#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
+           getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
+#else
+           (pass = getpwent()) != NULL
+#endif
+           && text[0] == pass->pw_name[0]
+           && strcmp(text, pass->pw_name) == 0)
+               continue;
+
+       if (pass == NULL) {
+               endpwent();
+               return NULL;
+       }
+       return strdup(pass->pw_name);
+}
+
+
+/*
+ * el-compatible wrapper to send TSTP on ^Z
+ */
+/* ARGSUSED */
+static unsigned char
+_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
+{
+       (void)kill(0, SIGTSTP);
+       return CC_NORM;
+}
+
+/*
+ * Display list of strings in columnar format on readline's output stream.
+ * 'matches' is list of strings, 'len' is number of strings in 'matches',
+ * 'max' is maximum length of string in 'matches'.
+ */
+void
+rl_display_match_list(char **matches, int len, int max)
+{
+
+       fn_display_match_list(e, matches, (size_t)len, (size_t)max);
+}
+
+static const char *
+/*ARGSUSED*/
+_rl_completion_append_character_function(const char *dummy
+    __attribute__((__unused__)))
+{
+       static char buf[2];
+       buf[0] = (char)rl_completion_append_character;
+       buf[1] = '\0';
+       return buf;
+}
+
+
+/*
+ * complete word at current point
+ */
+/* ARGSUSED */
+int
+rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
+{
+#ifdef WIDECHAR
+       static ct_buffer_t wbreak_conv, sprefix_conv;
+#endif
+       char *breakchars;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       if (rl_inhibit_completion) {
+               char arr[2];
+               arr[0] = (char)invoking_key;
+               arr[1] = '\0';
+               el_insertstr(e, arr);
+               return CC_REFRESH;
+       }
+
+       if (rl_completion_word_break_hook != NULL)
+               breakchars = (*rl_completion_word_break_hook)();
+       else
+               breakchars = rl_basic_word_break_characters;
+
+       /* Just look at how many global variables modify this operation! */
+       return fn_complete(e,
+           (CPFunction *)rl_completion_entry_function,
+           rl_attempted_completion_function,
+           ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
+           ct_decode_string(breakchars, &sprefix_conv),
+           _rl_completion_append_character_function,
+           (size_t)rl_completion_query_items,
+           &rl_completion_type, &rl_attempted_completion_over,
+           &rl_point, &rl_end);
+
+
+}
+
+
+/* ARGSUSED */
+static unsigned char
+_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
+{
+       return (unsigned char)rl_complete(0, ch);
+}
+
+/*
+ * misc other functions
+ */
+
+/*
+ * bind key c to readline-type function func
+ */
+int
+rl_bind_key(int c, rl_command_func_t *func)
+{
+       int retval = -1;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       if (func == rl_insert) {
+               /* XXX notice there is no range checking of ``c'' */
+               e->el_map.key[c] = ED_INSERT;
+               retval = 0;
+       }
+       return retval;
+}
+
+
+/*
+ * read one key from input - handles chars pushed back
+ * to input stream also
+ */
+int
+rl_read_key(void)
+{
+       char fooarr[2 * sizeof(int)];
+
+       if (e == NULL || h == NULL)
+               rl_initialize();
+
+       return el_getc(e, fooarr);
+}
+
+
+/*
+ * reset the terminal
+ */
+/* ARGSUSED */
+void
+rl_reset_terminal(const char *p __attribute__((__unused__)))
+{
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+       el_reset(e);
+}
+
+
+/*
+ * insert character ``c'' back into input stream, ``count'' times
+ */
+int
+rl_insert(int count, int c)
+{
+       char arr[2];
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       /* XXX - int -> char conversion can lose on multichars */
+       arr[0] = (char)c;
+       arr[1] = '\0';
+
+       for (; count > 0; count--)
+               el_push(e, arr);
+
+       return 0;
+}
+
+int
+rl_insert_text(const char *text)
+{
+       if (!text || *text == 0)
+               return 0;
+
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
+       if (el_insertstr(e, text) < 0)
+               return 0;
+       return (int)strlen(text);
+}
+
+/*ARGSUSED*/
+int
+rl_newline(int count __attribute__((__unused__)),
+    int c __attribute__((__unused__)))
+{
+       /*
+        * Readline-4.0 appears to ignore the args.
+        */
+       return rl_insert(1, '\n');
+}
+
+/*ARGSUSED*/
+static unsigned char
+rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
+{
+       if (map[c] == NULL)
+           return CC_ERROR;
+
+       _rl_update_pos();
+
+       (*map[c])(NULL, c);
+
+       /* If rl_done was set by the above call, deal with it here */
+       if (rl_done)
+               return CC_EOF;
+
+       return CC_NORM;
+}
+
+int
+rl_add_defun(const char *name, Function *fun, int c)
+{
+       char dest[8];
+       if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
+               return -1;
+       map[(unsigned char)c] = fun;
+       el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
+       vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
+       el_set(e, EL_BIND, dest, name, NULL);
+       return 0;
+}
+
+void
+rl_callback_read_char(void)
+{
+       int count = 0, done = 0;
+       const char *buf = el_gets(e, &count);
+       char *wbuf;
+
+       if (buf == NULL || count-- <= 0)
+               return;
+       if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
+               done = 1;
+       if (buf[count] == '\n' || buf[count] == '\r')
+               done = 2;
+
+       if (done && rl_linefunc != NULL) {
+               el_set(e, EL_UNBUFFERED, 0);
+               if (done == 2) {
+                   if ((wbuf = strdup(buf)) != NULL)
+                       wbuf[count] = '\0';
+               } else
+                       wbuf = NULL;
+               (*(void (*)(const char *))rl_linefunc)(wbuf);
+               //el_set(e, EL_UNBUFFERED, 1);
+       }
+}
+
+void 
+rl_callback_handler_install(const char *prompt, VCPFunction *linefunc)
+{
+       if (e == NULL) {
+               rl_initialize();
+       }
+       (void)rl_set_prompt(prompt);
+       rl_linefunc = linefunc;
+       el_set(e, EL_UNBUFFERED, 1);
+}   
+
+void 
+rl_callback_handler_remove(void)
+{
+       el_set(e, EL_UNBUFFERED, 0);
+       rl_linefunc = NULL;
+}
+
+void
+rl_redisplay(void)
+{
+       char a[2];
+       a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
+       a[1] = '\0';
+       el_push(e, a);
+}
+
+int
+rl_get_previous_history(int count, int key)
+{
+       char a[2];
+       a[0] = (char)key;
+       a[1] = '\0';
+       while (count--)
+               el_push(e, a);
+       return 0;
+}
+
+void
+/*ARGSUSED*/
+rl_prep_terminal(int meta_flag __attribute__((__unused__)))
+{
+       el_set(e, EL_PREP_TERM, 1);
+}
+
+void
+rl_deprep_terminal(void)
+{
+       el_set(e, EL_PREP_TERM, 0);
+}
+
+int
+rl_read_init_file(const char *s)
+{
+       return el_source(e, s);
+}
+
+int
+rl_parse_and_bind(const char *line)
+{
+       const char **argv;
+       int argc;
+       Tokenizer *tok;
+
+       tok = tok_init(NULL);
+       tok_str(tok, line, &argc, &argv);
+       argc = el_parse(e, argc, argv);
+       tok_end(tok);
+       return argc ? 1 : 0;
+}
+
+int
+rl_variable_bind(const char *var, const char *value)
+{
+       /*
+        * The proper return value is undocument, but this is what the
+        * readline source seems to do.
+        */
+       return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
+}
+
+void
+rl_stuff_char(int c)
+{
+       char buf[2];
+
+       buf[0] = (char)c;
+       buf[1] = '\0';
+       el_insertstr(e, buf);
+}
+
+static int
+_rl_event_read_char(EditLine *el, char *cp)
+{
+       int     n;
+       ssize_t num_read = 0;
+
+       *cp = '\0';
+       while (rl_event_hook) {
+
+               (*rl_event_hook)();
+
+#if defined(FIONREAD)
+               if (ioctl(el->el_infd, FIONREAD, &n) < 0)
+                       return -1;
+               if (n)
+                       num_read = read(el->el_infd, cp, (size_t)1);
+               else
+                       num_read = 0;
+#elif defined(F_SETFL) && defined(O_NDELAY)
+               if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
+                       return -1;
+               if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
+                       return -1;
+               num_read = read(el->el_infd, cp, 1);
+               if (fcntl(el->el_infd, F_SETFL, n))
+                       return -1;
+#else
+               /* not non-blocking, but what you gonna do? */
+               num_read = read(el->el_infd, cp, 1);
+               return -1;
+#endif
+
+               if (num_read < 0 && errno == EAGAIN)
+                       continue;
+               if (num_read == 0)
+                       continue;
+               break;
+       }
+       if (!rl_event_hook)
+               el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
+       return (int)num_read;
+}
+
+static void
+_rl_update_pos(void)
+{
+       const LineInfo *li = el_line(e);
+
+       rl_point = (int)(li->cursor - li->buffer);
+       rl_end = (int)(li->lastchar - li->buffer);
+}
+
+void
+rl_get_screen_size(int *rows, int *cols)
+{
+       if (rows)
+               el_get(e, EL_GETTC, "li", rows, NULL);
+       if (cols)
+               el_get(e, EL_GETTC, "co", cols, NULL);
+}
+
+void
+rl_set_screen_size(int rows, int cols)
+{
+       char buf[64];
+       (void)snprintf(buf, sizeof(buf), "%d", rows);
+       el_set(e, EL_SETTC, "li", buf, NULL);
+       (void)snprintf(buf, sizeof(buf), "%d", cols);
+       el_set(e, EL_SETTC, "co", buf, NULL);
+}
+
+char **
+rl_completion_matches(const char *str, rl_compentry_func_t *fun)
+{
+       size_t len, max, i, j, min;
+       char **list, *match, *a, *b;
+
+       len = 1;
+       max = 10;
+       if ((list = el_malloc(max * sizeof(*list))) == NULL)
+               return NULL;
+
+       while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
+               list[len++] = match;
+               if (len == max) {
+                       char **nl;
+                       max += 10;
+                       if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
+                               goto out;
+                       list = nl;
+               }
+       }
+       if (len == 1)
+               goto out;
+       list[len] = NULL;
+       if (len == 2) {
+               if ((list[0] = strdup(list[1])) == NULL)
+                       goto out;
+               return list;
+       }
+       qsort(&list[1], len - 1, sizeof(*list),
+           (int (*)(const void *, const void *)) strcmp);
+       min = SIZE_T_MAX;
+       for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
+               b = list[i + 1];
+               for (j = 0; a[j] && a[j] == b[j]; j++)
+                       continue;
+               if (min > j)
+                       min = j;
+       }
+       if (min == 0 && *str) {
+               if ((list[0] = strdup(str)) == NULL)
+                       goto out;
+       } else {
+               if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL)
+                       goto out;
+               (void)memcpy(list[0], list[1], min);
+               list[0][min] = '\0';
+       }
+       return list;
+               
+out:
+       el_free(list);
+       return NULL;
+}
+
+char *
+rl_filename_completion_function (const char *text, int state)
+{
+       return fn_filename_completion_function(text, state);
+}
+
+void
+rl_forced_update_display(void)
+{
+       el_set(e, EL_REFRESH);
+}
+
+int
+_rl_abort_internal(void)
+{
+       el_beep(e);
+       longjmp(topbuf, 1);
+       /*NOTREACHED*/
+}
+
+int
+_rl_qsort_string_compare(char **s1, char **s2)
+{
+       return strcoll(*s1, *s2);
+}
+
+HISTORY_STATE *
+history_get_history_state(void)
+{
+       HISTORY_STATE *hs;
+
+       if ((hs = el_malloc(sizeof(*hs))) == NULL)
+               return NULL;
+       hs->length = history_length;
+       return hs;
+}
+
+int
+/*ARGSUSED*/
+rl_kill_text(int from __attribute__((__unused__)),
+    int to __attribute__((__unused__)))
+{
+       return 0;
+}
+
+Keymap
+rl_make_bare_keymap(void)
+{
+       return NULL;
+}
+
+Keymap
+rl_get_keymap(void)
+{
+       return NULL;
+}
+
+void
+/*ARGSUSED*/
+rl_set_keymap(Keymap k __attribute__((__unused__)))
+{
+}
+
+int
+/*ARGSUSED*/
+rl_generic_bind(int type __attribute__((__unused__)),
+    const char * keyseq __attribute__((__unused__)),
+    const char * data __attribute__((__unused__)),
+    Keymap k __attribute__((__unused__)))
+{
+       return 0;
+}
+
+int
+/*ARGSUSED*/
+rl_bind_key_in_map(int key __attribute__((__unused__)),
+    rl_command_func_t *fun __attribute__((__unused__)),
+    Keymap k __attribute__((__unused__)))
+{
+       return 0;
+}
+
+/* unsupported, but needed by python */
+void
+rl_cleanup_after_signal(void)
+{
+}
+
+int
+rl_on_new_line(void)
+{
+       return 0;
+}
+
+void
+rl_free_line_state(void)
+{
+}
diff --git a/lib/libedit/readline/Makefile b/lib/libedit/readline/Makefile
new file mode 100644 (file)
index 0000000..3d5111f
--- /dev/null
@@ -0,0 +1,13 @@
+#      $NetBSD: Makefile,v 1.7 2003/08/03 09:23:15 lukem Exp $ 
+
+NOOBJ=         # defined
+
+.include <bsd.own.mk>
+
+.PATH: ${NETBSDSRCDIR}/lib/libedit
+
+INCS=          readline.h
+INCSDIR=       /usr/include/readline
+INCSYMLINKS=   readline.h ${INCSDIR}/history.h
+
+.include <bsd.prog.mk>
diff --git a/lib/libedit/readline/readline.h b/lib/libedit/readline/readline.h
new file mode 100644 (file)
index 0000000..0d13713
--- /dev/null
@@ -0,0 +1,222 @@
+/*     $NetBSD: readline.h,v 1.33 2012/05/15 17:30:04 christos Exp $   */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _READLINE_H_
+#define _READLINE_H_
+
+#include <sys/types.h>
+#include <stdio.h>
+
+/* list of readline stuff supported by editline library's readline wrapper */
+
+/* typedefs */
+typedef int      Function(const char *, int);
+typedef void     VFunction(void);
+typedef void     VCPFunction(char *);
+typedef char    *CPFunction(const char *, int);
+typedef char   **CPPFunction(const char *, int, int);
+typedef char     *rl_compentry_func_t(const char *, int);
+typedef int      rl_command_func_t(int, int);
+
+/* only supports length */
+typedef struct {
+       int length;
+} HISTORY_STATE;
+
+typedef void *histdata_t;
+
+typedef struct _hist_entry {
+       const char      *line;
+       histdata_t       data;
+} HIST_ENTRY;
+
+typedef struct _keymap_entry {
+       char type;
+#define ISFUNC 0
+#define ISKMAP 1
+#define ISMACR 2
+       Function *function;
+} KEYMAP_ENTRY;
+
+#define KEYMAP_SIZE    256
+
+typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
+typedef KEYMAP_ENTRY *Keymap;
+
+#define control_character_threshold    0x20
+#define control_character_bit          0x40
+
+#ifndef CTRL
+#include <sys/ioctl.h>
+#if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
+#include <sys/ttydefaults.h>
+#endif
+#ifndef CTRL
+#define CTRL(c)                ((c) & 037)
+#endif
+#endif
+#ifndef UNCTRL
+#define UNCTRL(c)      (((c) - 'a' + 'A')|control_character_bit)
+#endif
+
+#define RUBOUT         0x7f
+#define ABORT_CHAR     CTRL('G')
+#define RL_READLINE_VERSION    0x0402
+#define RL_PROMPT_START_IGNORE '\1'
+#define RL_PROMPT_END_IGNORE   '\2'
+
+/* global variables used by readline enabled applications */
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern const char      *rl_library_version;
+extern int             rl_readline_version; 
+extern char            *rl_readline_name;
+extern FILE            *rl_instream;
+extern FILE            *rl_outstream;
+extern char            *rl_line_buffer;
+extern int              rl_point, rl_end;
+extern int              history_base, history_length;
+extern int              max_input_history;
+extern char            *rl_basic_word_break_characters;
+extern char            *rl_completer_word_break_characters;
+extern char            *rl_completer_quote_characters;
+extern Function                *rl_completion_entry_function;
+extern char            *(*rl_completion_word_break_hook)(void);
+extern CPPFunction     *rl_attempted_completion_function;
+extern int              rl_attempted_completion_over;
+extern int             rl_completion_type;
+extern int             rl_completion_query_items;
+extern char            *rl_special_prefixes;
+extern int             rl_completion_append_character;
+extern int             rl_inhibit_completion;
+extern Function                *rl_pre_input_hook;
+extern Function                *rl_startup_hook;
+extern char            *rl_terminal_name;
+extern int             rl_already_prompted;
+extern char            *rl_prompt;
+/*
+ * The following is not implemented
+ */
+extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
+                       emacs_meta_keymap,
+                       emacs_ctlx_keymap;
+extern int             rl_filename_completion_desired;
+extern int             rl_ignore_completion_duplicates;
+extern int             (*rl_getc_function)(FILE *);
+extern VFunction       *rl_redisplay_function;
+extern VFunction       *rl_completion_display_matches_hook;
+extern VFunction       *rl_prep_term_function;
+extern VFunction       *rl_deprep_term_function;
+extern int             readline_echoing_p;
+extern int             _rl_print_completions_horizontally;
+
+/* supported functions */
+char           *readline(const char *);
+int             rl_initialize(void);
+
+void            using_history(void);
+int             add_history(const char *);
+void            clear_history(void);
+void            stifle_history(int);
+int             unstifle_history(void);
+int             history_is_stifled(void);
+int             where_history(void);
+HIST_ENTRY     *current_history(void);
+HIST_ENTRY     *history_get(int);
+HIST_ENTRY     *remove_history(int);
+HIST_ENTRY     *replace_history_entry(int, const char *, histdata_t);
+int             history_total_bytes(void);
+int             history_set_pos(int);
+HIST_ENTRY     *previous_history(void);
+HIST_ENTRY     *next_history(void);
+int             history_search(const char *, int);
+int             history_search_prefix(const char *, int);
+int             history_search_pos(const char *, int, int);
+int             read_history(const char *);
+int             write_history(const char *);
+int             history_truncate_file (const char *, int);
+int             history_expand(char *, char **);
+char          **history_tokenize(const char *);
+const char     *get_history_event(const char *, int *, int);
+char           *history_arg_extract(int, int, const char *);
+
+char           *tilde_expand(char *);
+char           *filename_completion_function(const char *, int);
+char           *username_completion_function(const char *, int);
+int             rl_complete(int, int);
+int             rl_read_key(void);
+char          **completion_matches(const char *, CPFunction *);
+void            rl_display_match_list(char **, int, int);
+
+int             rl_insert(int, int);
+int             rl_insert_text(const char *);
+void            rl_reset_terminal(const char *);
+int             rl_bind_key(int, rl_command_func_t *);
+int             rl_newline(int, int);
+void            rl_callback_read_char(void);
+void            rl_callback_handler_install(const char *, VCPFunction *);
+void            rl_callback_handler_remove(void);
+void            rl_redisplay(void);
+int             rl_get_previous_history(int, int);
+void            rl_prep_terminal(int);
+void            rl_deprep_terminal(void);
+int             rl_read_init_file(const char *);
+int             rl_parse_and_bind(const char *);
+int             rl_variable_bind(const char *, const char *);
+void            rl_stuff_char(int);
+int             rl_add_defun(const char *, Function *, int);
+HISTORY_STATE  *history_get_history_state(void);
+void            rl_get_screen_size(int *, int *);
+void            rl_set_screen_size(int, int);
+char           *rl_filename_completion_function (const char *, int);
+int             _rl_abort_internal(void);
+int             _rl_qsort_string_compare(char **, char **);
+char          **rl_completion_matches(const char *, rl_compentry_func_t *);
+void            rl_forced_update_display(void);
+int             rl_set_prompt(const char *);
+int             rl_on_new_line(void);
+
+/*
+ * The following are not implemented
+ */
+int             rl_kill_text(int, int);
+Keymap          rl_get_keymap(void);
+void            rl_set_keymap(Keymap);
+Keymap          rl_make_bare_keymap(void);
+int             rl_generic_bind(int, const char *, const char *, Keymap);
+int             rl_bind_key_in_map(int, rl_command_func_t *, Keymap);
+void            rl_cleanup_after_signal(void);
+void            rl_free_line_state(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _READLINE_H_ */
diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c
new file mode 100644 (file)
index 0000000..3e1176e
--- /dev/null
@@ -0,0 +1,1183 @@
+/*     $NetBSD: refresh.c,v 1.37 2011/07/29 23:44:45 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)refresh.c  8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: refresh.c,v 1.37 2011/07/29 23:44:45 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * refresh.c: Lower level screen refreshing functions
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "el.h"
+
+private void   re_nextline(EditLine *);
+private void   re_addc(EditLine *, Int);
+private void   re_update_line(EditLine *, Char *, Char *, int);
+private void   re_insert (EditLine *, Char *, int, int, Char *, int);
+private void   re_delete(EditLine *, Char *, int, int, int);
+private void   re_fastputc(EditLine *, Int);
+private void   re_clear_eol(EditLine *, int, int, int);
+private void   re__strncopy(Char *, Char *, size_t);
+private void   re__copy_and_pad(Char *, const Char *, size_t);
+
+#ifdef DEBUG_REFRESH
+private void   re_printstr(EditLine *, const char *, char *, char *);
+#define        __F el->el_errfile
+#define        ELRE_ASSERT(a, b, c)    do                              \
+                                   if (/*CONSTCOND*/ a) {      \
+                                       (void) fprintf b;       \
+                                       c;                      \
+                                   }                           \
+                               while (/*CONSTCOND*/0)
+#define        ELRE_DEBUG(a, b)        ELRE_ASSERT(a,b,;)
+
+/* re_printstr():
+ *     Print a string on the debugging pty
+ */
+private void
+re_printstr(EditLine *el, const char *str, char *f, char *t)
+{
+
+       ELRE_DEBUG(1, (__F, "%s:\"", str));
+       while (f < t)
+               ELRE_DEBUG(1, (__F, "%c", *f++ & 0177));
+       ELRE_DEBUG(1, (__F, "\"\r\n"));
+}
+#else
+#define        ELRE_ASSERT(a, b, c)
+#define        ELRE_DEBUG(a, b)
+#endif
+
+/* re_nextline():
+ *     Move to the next line or scroll
+ */
+private void
+re_nextline(EditLine *el)
+{
+       el->el_refresh.r_cursor.h = 0;  /* reset it. */
+
+       /*
+        * If we would overflow (input is longer than terminal size),
+        * emulate scroll by dropping first line and shuffling the rest.
+        * We do this via pointer shuffling - it's safe in this case
+        * and we avoid memcpy().
+        */
+       if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) {
+               int i, lins = el->el_terminal.t_size.v;
+               Char *firstline = el->el_vdisplay[0];
+
+               for(i = 1; i < lins; i++)
+                       el->el_vdisplay[i - 1] = el->el_vdisplay[i];
+
+               firstline[0] = '\0';            /* empty the string */  
+               el->el_vdisplay[i - 1] = firstline;
+       } else
+               el->el_refresh.r_cursor.v++;
+
+       ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_terminal.t_size.v,
+           (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
+           el->el_refresh.r_cursor.v, el->el_terminal.t_size.v),
+           abort());
+}
+
+/* re_addc():
+ *     Draw c, expanding tabs, control chars etc.
+ */
+private void
+re_addc(EditLine *el, Int c)
+{
+       switch (ct_chr_class((Char)c)) {
+       case CHTYPE_TAB:        /* expand the tab */
+               for (;;) {
+                       re_putc(el, ' ', 1);
+                       if ((el->el_refresh.r_cursor.h & 07) == 0)
+                               break;                  /* go until tab stop */
+               }
+               break;
+       case CHTYPE_NL: {
+               int oldv = el->el_refresh.r_cursor.v;
+               re_putc(el, '\0', 0);                   /* assure end of line */
+               if (oldv == el->el_refresh.r_cursor.v)  /* XXX */
+                       re_nextline(el);
+               break;
+       }
+       case CHTYPE_PRINT:
+               re_putc(el, c, 1);
+               break;
+       default: {
+               Char visbuf[VISUAL_WIDTH_MAX];
+               ssize_t i, n =
+                   ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
+               for (i = 0; n-- > 0; ++i)
+                   re_putc(el, visbuf[i], 1);
+               break;
+       }
+       }
+}
+
+
+/* re_putc():
+ *     Draw the character given
+ */
+protected void
+re_putc(EditLine *el, Int c, int shift)
+{
+       int i, w = Width(c);
+       ELRE_DEBUG(1, (__F, "printing %5x '%c'\r\n", c, c));
+
+       while (shift && (el->el_refresh.r_cursor.h + w > el->el_terminal.t_size.h))
+           re_putc(el, ' ', 1);
+
+       el->el_vdisplay[el->el_refresh.r_cursor.v]
+           [el->el_refresh.r_cursor.h] = c;
+       /* assumes !shift is only used for single-column chars */
+       i = w;
+       while (--i > 0)
+               el->el_vdisplay[el->el_refresh.r_cursor.v]
+                   [el->el_refresh.r_cursor.h + i] = MB_FILL_CHAR;
+
+       if (!shift)
+               return;
+
+       el->el_refresh.r_cursor.h += w; /* advance to next place */
+       if (el->el_refresh.r_cursor.h >= el->el_terminal.t_size.h) {
+               /* assure end of line */
+               el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_terminal.t_size.h]
+                   = '\0';
+               re_nextline(el);
+       }
+}
+
+
+/* re_refresh():
+ *     draws the new virtual screen image from the current input
+ *     line, then goes line-by-line changing the real image to the new
+ *     virtual image. The routine to re-draw a line can be replaced
+ *     easily in hopes of a smarter one being placed there.
+ */
+protected void
+re_refresh(EditLine *el)
+{
+       int i, rhdiff;
+       Char *cp, *st;
+       coord_t cur;
+#ifdef notyet
+       size_t termsz;
+#endif
+
+       ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%s:\r\n",
+           el->el_line.buffer));
+
+       /* reset the Drawing cursor */
+       el->el_refresh.r_cursor.h = 0;
+       el->el_refresh.r_cursor.v = 0;
+
+       /* temporarily draw rprompt to calculate its size */
+       prompt_print(el, EL_RPROMPT);
+
+       /* reset the Drawing cursor */
+       el->el_refresh.r_cursor.h = 0;
+       el->el_refresh.r_cursor.v = 0;
+
+       if (el->el_line.cursor >= el->el_line.lastchar) {
+               if (el->el_map.current == el->el_map.alt
+                   && el->el_line.lastchar != el->el_line.buffer)
+                       el->el_line.cursor = el->el_line.lastchar - 1;
+               else
+                       el->el_line.cursor = el->el_line.lastchar;
+       }
+
+       cur.h = -1;             /* set flag in case I'm not set */
+       cur.v = 0;
+
+       prompt_print(el, EL_PROMPT);
+
+       /* draw the current input buffer */
+#if notyet
+       termsz = el->el_terminal.t_size.h * el->el_terminal.t_size.v;
+       if (el->el_line.lastchar - el->el_line.buffer > termsz) {
+               /*
+                * If line is longer than terminal, process only part
+                * of line which would influence display.
+                */
+               size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz;
+
+               st = el->el_line.lastchar - rem
+                       - (termsz - (((rem / el->el_terminal.t_size.v) - 1)
+                                       * el->el_terminal.t_size.v));
+       } else
+#endif
+               st = el->el_line.buffer;
+
+       for (cp = st; cp < el->el_line.lastchar; cp++) {
+               if (cp == el->el_line.cursor) {
+                        int w = Width(*cp);
+                       /* save for later */
+                       cur.h = el->el_refresh.r_cursor.h;
+                       cur.v = el->el_refresh.r_cursor.v;
+                        /* handle being at a linebroken doublewidth char */
+                        if (w > 1 && el->el_refresh.r_cursor.h + w >
+                           el->el_terminal.t_size.h) {
+                               cur.h = 0;
+                               cur.v++;
+                        }
+               }
+               re_addc(el, *cp);
+       }
+
+       if (cur.h == -1) {      /* if I haven't been set yet, I'm at the end */
+               cur.h = el->el_refresh.r_cursor.h;
+               cur.v = el->el_refresh.r_cursor.v;
+       }
+       rhdiff = el->el_terminal.t_size.h - el->el_refresh.r_cursor.h -
+           el->el_rprompt.p_pos.h;
+       if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v &&
+           !el->el_refresh.r_cursor.v && rhdiff > 1) {
+               /*
+                * have a right-hand side prompt that will fit
+                * on the end of the first line with at least
+                * one character gap to the input buffer.
+                */
+               while (--rhdiff > 0)    /* pad out with spaces */
+                       re_putc(el, ' ', 1);
+               prompt_print(el, EL_RPROMPT);
+       } else {
+               el->el_rprompt.p_pos.h = 0;     /* flag "not using rprompt" */
+               el->el_rprompt.p_pos.v = 0;
+       }
+
+       re_putc(el, '\0', 0);   /* make line ended with NUL, no cursor shift */
+
+       el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
+
+       ELRE_DEBUG(1, (__F,
+               "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
+               el->el_terminal.t_size.h, el->el_refresh.r_cursor.h,
+               el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0])));
+
+       ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv));
+       for (i = 0; i <= el->el_refresh.r_newcv; i++) {
+               /* NOTE THAT re_update_line MAY CHANGE el_display[i] */
+               re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
+
+               /*
+                * Copy the new line to be the current one, and pad out with
+                * spaces to the full width of the terminal so that if we try
+                * moving the cursor by writing the character that is at the
+                * end of the screen line, it won't be a NUL or some old
+                * leftover stuff.
+                */
+               re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
+                   (size_t) el->el_terminal.t_size.h);
+       }
+       ELRE_DEBUG(1, (__F,
+       "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
+           el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i));
+
+       if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
+               for (; i <= el->el_refresh.r_oldcv; i++) {
+                       terminal_move_to_line(el, i);
+                       terminal_move_to_char(el, 0);
+                        /* This Strlen should be safe even with MB_FILL_CHARs */
+                       terminal_clear_EOL(el, (int) Strlen(el->el_display[i]));
+#ifdef DEBUG_REFRESH
+                       terminal_overwrite(el, "C\b", (size_t)2);
+#endif /* DEBUG_REFRESH */
+                       el->el_display[i][0] = '\0';
+               }
+
+       el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */
+       ELRE_DEBUG(1, (__F,
+           "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
+           el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
+           cur.h, cur.v));
+       terminal_move_to_line(el, cur.v);       /* go to where the cursor is */
+       terminal_move_to_char(el, cur.h);
+}
+
+
+/* re_goto_bottom():
+ *      used to go to last used screen line
+ */
+protected void
+re_goto_bottom(EditLine *el)
+{
+
+       terminal_move_to_line(el, el->el_refresh.r_oldcv);
+       terminal__putc(el, '\n');
+       re_clear_display(el);
+       terminal__flush(el);
+}
+
+
+/* re_insert():
+ *     insert num characters of s into d (in front of the character)
+ *     at dat, maximum length of d is dlen
+ */
+private void
+/*ARGSUSED*/
+re_insert(EditLine *el __attribute__((__unused__)),
+    Char *d, int dat, int dlen, Char *s, int num)
+{
+       Char *a, *b;
+
+       if (num <= 0)
+               return;
+       if (num > dlen - dat)
+               num = dlen - dat;
+
+       ELRE_DEBUG(1,
+           (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
+           num, dat, dlen, ct_encode_string(d)));
+       ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s)));
+
+       /* open up the space for num chars */
+       if (num > 0) {
+               b = d + dlen - 1;
+               a = b - num;
+               while (a >= &d[dat])
+                       *b-- = *a--;
+               d[dlen] = '\0'; /* just in case */
+       }
+
+       ELRE_DEBUG(1, (__F,
+               "re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
+               num, dat, dlen, ct_encode_string(d)));
+       ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s)));
+
+       /* copy the characters */
+       for (a = d + dat; (a < d + dlen) && (num > 0); num--)
+               *a++ = *s++;
+
+#ifdef notyet
+        /* ct_encode_string() uses a static buffer, so we can't conveniently
+         * encode both d & s here */
+       ELRE_DEBUG(1,
+           (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
+           num, dat, dlen, d, s));
+       ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s));
+#endif
+}
+
+
+/* re_delete():
+ *     delete num characters d at dat, maximum length of d is dlen
+ */
+private void
+/*ARGSUSED*/
+re_delete(EditLine *el __attribute__((__unused__)),
+    Char *d, int dat, int dlen, int num)
+{
+       Char *a, *b;
+
+       if (num <= 0)
+               return;
+       if (dat + num >= dlen) {
+               d[dat] = '\0';
+               return;
+       }
+       ELRE_DEBUG(1,
+           (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
+           num, dat, dlen, ct_encode_string(d)));
+
+       /* open up the space for num chars */
+       if (num > 0) {
+               b = d + dat;
+               a = b + num;
+               while (a < &d[dlen])
+                       *b++ = *a++;
+               d[dlen] = '\0'; /* just in case */
+       }
+       ELRE_DEBUG(1,
+           (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
+           num, dat, dlen, ct_encode_string(d)));
+}
+
+
+/* re__strncopy():
+ *     Like strncpy without padding.
+ */
+private void
+re__strncopy(Char *a, Char *b, size_t n)
+{
+
+       while (n-- && *b)
+               *a++ = *b++;
+}
+
+/* re_clear_eol():
+ *     Find the number of characters we need to clear till the end of line
+ *     in order to make sure that we have cleared the previous contents of
+ *     the line. fx and sx is the number of characters inserted or deleted
+ *     in the first or second diff, diff is the difference between the
+ *     number of characters between the new and old line.
+ */
+private void
+re_clear_eol(EditLine *el, int fx, int sx, int diff)
+{
+
+       ELRE_DEBUG(1, (__F, "re_clear_eol sx %d, fx %d, diff %d\n",
+           sx, fx, diff));
+
+       if (fx < 0)
+               fx = -fx;
+       if (sx < 0)
+               sx = -sx;
+       if (fx > diff)
+               diff = fx;
+       if (sx > diff)
+               diff = sx;
+
+       ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff));
+       terminal_clear_EOL(el, diff);
+}
+
+/*****************************************************************
+    re_update_line() is based on finding the middle difference of each line
+    on the screen; vis:
+
+                            /old first difference
+       /beginning of line   |              /old last same       /old EOL
+       v                    v              v                    v
+old:   eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new:   eddie> Oh, my little buggy says to me, as lurgid as
+       ^                    ^        ^                    ^
+       \beginning of line   |        \new last same       \new end of line
+                            \new first difference
+
+    all are character pointers for the sake of speed.  Special cases for
+    no differences, as well as for end of line additions must be handled.
+**************************************************************** */
+
+/* Minimum at which doing an insert it "worth it".  This should be about
+ * half the "cost" of going into insert mode, inserting a character, and
+ * going back out.  This should really be calculated from the termcap
+ * data...  For the moment, a good number for ANSI terminals.
+ */
+#define        MIN_END_KEEP    4
+
+private void
+re_update_line(EditLine *el, Char *old, Char *new, int i)
+{
+       Char *o, *n, *p, c;
+       Char *ofd, *ols, *oe, *nfd, *nls, *ne;
+       Char *osb, *ose, *nsb, *nse;
+       int fx, sx;
+       size_t len;
+
+       /*
+         * find first diff
+         */
+       for (o = old, n = new; *o && (*o == *n); o++, n++)
+               continue;
+       ofd = o;
+       nfd = n;
+
+       /*
+         * Find the end of both old and new
+         */
+       while (*o)
+               o++;
+       /*
+         * Remove any trailing blanks off of the end, being careful not to
+         * back up past the beginning.
+         */
+       while (ofd < o) {
+               if (o[-1] != ' ')
+                       break;
+               o--;
+       }
+       oe = o;
+       *oe = '\0';
+
+       while (*n)
+               n++;
+
+       /* remove blanks from end of new */
+       while (nfd < n) {
+               if (n[-1] != ' ')
+                       break;
+               n--;
+       }
+       ne = n;
+       *ne = '\0';
+
+       /*
+         * if no diff, continue to next line of redraw
+         */
+       if (*ofd == '\0' && *nfd == '\0') {
+               ELRE_DEBUG(1, (__F, "no difference.\r\n"));
+               return;
+       }
+       /*
+         * find last same pointer
+         */
+       while ((o > ofd) && (n > nfd) && (*--o == *--n))
+               continue;
+       ols = ++o;
+       nls = ++n;
+
+       /*
+         * find same begining and same end
+         */
+       osb = ols;
+       nsb = nls;
+       ose = ols;
+       nse = nls;
+
+       /*
+         * case 1: insert: scan from nfd to nls looking for *ofd
+         */
+       if (*ofd) {
+               for (c = *ofd, n = nfd; n < nls; n++) {
+                       if (c == *n) {
+                               for (o = ofd, p = n;
+                                   p < nls && o < ols && *o == *p;
+                                   o++, p++)
+                                       continue;
+                               /*
+                                * if the new match is longer and it's worth
+                                * keeping, then we take it
+                                */
+                               if (((nse - nsb) < (p - n)) &&
+                                   (2 * (p - n) > n - nfd)) {
+                                       nsb = n;
+                                       nse = p;
+                                       osb = ofd;
+                                       ose = o;
+                               }
+                       }
+               }
+       }
+       /*
+         * case 2: delete: scan from ofd to ols looking for *nfd
+         */
+       if (*nfd) {
+               for (c = *nfd, o = ofd; o < ols; o++) {
+                       if (c == *o) {
+                               for (n = nfd, p = o;
+                                   p < ols && n < nls && *p == *n;
+                                   p++, n++)
+                                       continue;
+                               /*
+                                * if the new match is longer and it's worth
+                                * keeping, then we take it
+                                */
+                               if (((ose - osb) < (p - o)) &&
+                                   (2 * (p - o) > o - ofd)) {
+                                       nsb = nfd;
+                                       nse = n;
+                                       osb = o;
+                                       ose = p;
+                               }
+                       }
+               }
+       }
+       /*
+         * Pragmatics I: If old trailing whitespace or not enough characters to
+         * save to be worth it, then don't save the last same info.
+         */
+       if ((oe - ols) < MIN_END_KEEP) {
+               ols = oe;
+               nls = ne;
+       }
+       /*
+         * Pragmatics II: if the terminal isn't smart enough, make the data
+         * dumber so the smart update doesn't try anything fancy
+         */
+
+       /*
+         * fx is the number of characters we need to insert/delete: in the
+         * beginning to bring the two same begins together
+         */
+       fx = (int)((nsb - nfd) - (osb - ofd));
+       /*
+         * sx is the number of characters we need to insert/delete: in the
+         * end to bring the two same last parts together
+         */
+       sx = (int)((nls - nse) - (ols - ose));
+
+       if (!EL_CAN_INSERT) {
+               if (fx > 0) {
+                       osb = ols;
+                       ose = ols;
+                       nsb = nls;
+                       nse = nls;
+               }
+               if (sx > 0) {
+                       ols = oe;
+                       nls = ne;
+               }
+               if ((ols - ofd) < (nls - nfd)) {
+                       ols = oe;
+                       nls = ne;
+               }
+       }
+       if (!EL_CAN_DELETE) {
+               if (fx < 0) {
+                       osb = ols;
+                       ose = ols;
+                       nsb = nls;
+                       nse = nls;
+               }
+               if (sx < 0) {
+                       ols = oe;
+                       nls = ne;
+               }
+               if ((ols - ofd) > (nls - nfd)) {
+                       ols = oe;
+                       nls = ne;
+               }
+       }
+       /*
+         * Pragmatics III: make sure the middle shifted pointers are correct if
+         * they don't point to anything (we may have moved ols or nls).
+         */
+       /* if the change isn't worth it, don't bother */
+       /* was: if (osb == ose) */
+       if ((ose - osb) < MIN_END_KEEP) {
+               osb = ols;
+               ose = ols;
+               nsb = nls;
+               nse = nls;
+       }
+       /*
+         * Now that we are done with pragmatics we recompute fx, sx
+         */
+       fx = (int)((nsb - nfd) - (osb - ofd));
+       sx = (int)((nls - nse) - (ols - ose));
+
+       ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx));
+       ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n",
+               ofd - old, osb - old, ose - old, ols - old, oe - old));
+       ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
+               nfd - new, nsb - new, nse - new, nls - new, ne - new));
+       ELRE_DEBUG(1, (__F,
+               "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"));
+       ELRE_DEBUG(1, (__F,
+               "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));
+#ifdef DEBUG_REFRESH
+       re_printstr(el, "old- oe", old, oe);
+       re_printstr(el, "new- ne", new, ne);
+       re_printstr(el, "old-ofd", old, ofd);
+       re_printstr(el, "new-nfd", new, nfd);
+       re_printstr(el, "ofd-osb", ofd, osb);
+       re_printstr(el, "nfd-nsb", nfd, nsb);
+       re_printstr(el, "osb-ose", osb, ose);
+       re_printstr(el, "nsb-nse", nsb, nse);
+       re_printstr(el, "ose-ols", ose, ols);
+       re_printstr(el, "nse-nls", nse, nls);
+       re_printstr(el, "ols- oe", ols, oe);
+       re_printstr(el, "nls- ne", nls, ne);
+#endif /* DEBUG_REFRESH */
+
+       /*
+         * el_cursor.v to this line i MUST be in this routine so that if we
+         * don't have to change the line, we don't move to it. el_cursor.h to
+         * first diff char
+         */
+       terminal_move_to_line(el, i);
+
+       /*
+         * at this point we have something like this:
+         *
+         * /old                  /ofd    /osb               /ose    /ols     /oe
+         * v.....................v       v..................v       v........v
+         * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
+         * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
+         * ^.....................^     ^..................^       ^........^
+         * \new                  \nfd  \nsb               \nse     \nls    \ne
+         *
+         * fx is the difference in length between the chars between nfd and
+         * nsb, and the chars between ofd and osb, and is thus the number of
+         * characters to delete if < 0 (new is shorter than old, as above),
+         * or insert (new is longer than short).
+         *
+         * sx is the same for the second differences.
+         */
+
+       /*
+         * if we have a net insert on the first difference, AND inserting the
+         * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful
+         * character (which is ne if nls != ne, otherwise is nse) off the edge
+        * of the screen (el->el_terminal.t_size.h) else we do the deletes first
+        * so that we keep everything we need to.
+         */
+
+       /*
+         * if the last same is the same like the end, there is no last same
+         * part, otherwise we want to keep the last same part set p to the
+         * last useful old character
+         */
+       p = (ols != oe) ? oe : ose;
+
+       /*
+         * if (There is a diffence in the beginning) && (we need to insert
+         *   characters) && (the number of characters to insert is less than
+         *   the term width)
+        *      We need to do an insert!
+        * else if (we need to delete characters)
+        *      We need to delete characters!
+        * else
+        *      No insert or delete
+         */
+       if ((nsb != nfd) && fx > 0 &&
+           ((p - old) + fx <= el->el_terminal.t_size.h)) {
+               ELRE_DEBUG(1,
+                   (__F, "first diff insert at %d...\r\n", nfd - new));
+               /*
+                * Move to the first char to insert, where the first diff is.
+                */
+               terminal_move_to_char(el, (int)(nfd - new));
+               /*
+                * Check if we have stuff to keep at end
+                */
+               if (nsb != ne) {
+                       ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
+                       /*
+                        * insert fx chars of new starting at nfd
+                        */
+                       if (fx > 0) {
+                               ELRE_DEBUG(!EL_CAN_INSERT, (__F,
+                               "ERROR: cannot insert in early first diff\n"));
+                               terminal_insertwrite(el, nfd, fx);
+                               re_insert(el, old, (int)(ofd - old),
+                                   el->el_terminal.t_size.h, nfd, fx);
+                       }
+                       /*
+                        * write (nsb-nfd) - fx chars of new starting at
+                        * (nfd + fx)
+                        */
+                       len = (size_t) ((nsb - nfd) - fx);
+                       terminal_overwrite(el, (nfd + fx), len);
+                       re__strncopy(ofd + fx, nfd + fx, len);
+               } else {
+                       ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
+                       len = (size_t)(nsb - nfd);
+                       terminal_overwrite(el, nfd, len);
+                       re__strncopy(ofd, nfd, len);
+                       /*
+                        * Done
+                        */
+                       return;
+               }
+       } else if (fx < 0) {
+               ELRE_DEBUG(1,
+                   (__F, "first diff delete at %d...\r\n", ofd - old));
+               /*
+                * move to the first char to delete where the first diff is
+                */
+               terminal_move_to_char(el, (int)(ofd - old));
+               /*
+                * Check if we have stuff to save
+                */
+               if (osb != oe) {
+                       ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
+                       /*
+                        * fx is less than zero *always* here but we check
+                        * for code symmetry
+                        */
+                       if (fx < 0) {
+                               ELRE_DEBUG(!EL_CAN_DELETE, (__F,
+                                   "ERROR: cannot delete in first diff\n"));
+                               terminal_deletechars(el, -fx);
+                               re_delete(el, old, (int)(ofd - old),
+                                   el->el_terminal.t_size.h, -fx);
+                       }
+                       /*
+                        * write (nsb-nfd) chars of new starting at nfd
+                        */
+                       len = (size_t) (nsb - nfd);
+                       terminal_overwrite(el, nfd, len);
+                       re__strncopy(ofd, nfd, len);
+
+               } else {
+                       ELRE_DEBUG(1, (__F,
+                           "but with nothing left to save\r\n"));
+                       /*
+                        * write (nsb-nfd) chars of new starting at nfd
+                        */
+                       terminal_overwrite(el, nfd, (size_t)(nsb - nfd));
+                       re_clear_eol(el, fx, sx,
+                           (int)((oe - old) - (ne - new)));
+                       /*
+                        * Done
+                        */
+                       return;
+               }
+       } else
+               fx = 0;
+
+       if (sx < 0 && (ose - old) + fx < el->el_terminal.t_size.h) {
+               ELRE_DEBUG(1, (__F,
+                   "second diff delete at %d...\r\n", (ose - old) + fx));
+               /*
+                * Check if we have stuff to delete
+                */
+               /*
+                * fx is the number of characters inserted (+) or deleted (-)
+                */
+
+               terminal_move_to_char(el, (int)((ose - old) + fx));
+               /*
+                * Check if we have stuff to save
+                */
+               if (ols != oe) {
+                       ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
+                       /*
+                        * Again a duplicate test.
+                        */
+                       if (sx < 0) {
+                               ELRE_DEBUG(!EL_CAN_DELETE, (__F,
+                                   "ERROR: cannot delete in second diff\n"));
+                               terminal_deletechars(el, -sx);
+                       }
+                       /*
+                        * write (nls-nse) chars of new starting at nse
+                        */
+                       terminal_overwrite(el, nse, (size_t)(nls - nse));
+               } else {
+                       ELRE_DEBUG(1, (__F,
+                           "but with nothing left to save\r\n"));
+                       terminal_overwrite(el, nse, (size_t)(nls - nse));
+                       re_clear_eol(el, fx, sx,
+                           (int)((oe - old) - (ne - new)));
+               }
+       }
+       /*
+         * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
+         */
+       if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
+               ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n",
+                   nfd - new));
+
+               terminal_move_to_char(el, (int)(nfd - new));
+               /*
+                * Check if we have stuff to keep at the end
+                */
+               if (nsb != ne) {
+                       ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
+                       /*
+                        * We have to recalculate fx here because we set it
+                        * to zero above as a flag saying that we hadn't done
+                        * an early first insert.
+                        */
+                       fx = (int)((nsb - nfd) - (osb - ofd));
+                       if (fx > 0) {
+                               /*
+                                * insert fx chars of new starting at nfd
+                                */
+                               ELRE_DEBUG(!EL_CAN_INSERT, (__F,
+                                "ERROR: cannot insert in late first diff\n"));
+                               terminal_insertwrite(el, nfd, fx);
+                               re_insert(el, old, (int)(ofd - old),
+                                   el->el_terminal.t_size.h, nfd, fx);
+                       }
+                       /*
+                        * write (nsb-nfd) - fx chars of new starting at
+                        * (nfd + fx)
+                        */
+                       len = (size_t) ((nsb - nfd) - fx);
+                       terminal_overwrite(el, (nfd + fx), len);
+                       re__strncopy(ofd + fx, nfd + fx, len);
+               } else {
+                       ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
+                       len = (size_t) (nsb - nfd);
+                       terminal_overwrite(el, nfd, len);
+                       re__strncopy(ofd, nfd, len);
+               }
+       }
+       /*
+         * line is now NEW up to nse
+         */
+       if (sx >= 0) {
+               ELRE_DEBUG(1, (__F,
+                   "second diff insert at %d...\r\n", (int)(nse - new)));
+               terminal_move_to_char(el, (int)(nse - new));
+               if (ols != oe) {
+                       ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
+                       if (sx > 0) {
+                               /* insert sx chars of new starting at nse */
+                               ELRE_DEBUG(!EL_CAN_INSERT, (__F,
+                                   "ERROR: cannot insert in second diff\n"));
+                               terminal_insertwrite(el, nse, sx);
+                       }
+                       /*
+                        * write (nls-nse) - sx chars of new starting at
+                        * (nse + sx)
+                        */
+                       terminal_overwrite(el, (nse + sx),
+                           (size_t)((nls - nse) - sx));
+               } else {
+                       ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
+                       terminal_overwrite(el, nse, (size_t)(nls - nse));
+
+                       /*
+                        * No need to do a clear-to-end here because we were
+                        * doing a second insert, so we will have over
+                        * written all of the old string.
+                        */
+               }
+       }
+       ELRE_DEBUG(1, (__F, "done.\r\n"));
+}
+
+
+/* re__copy_and_pad():
+ *     Copy string and pad with spaces
+ */
+private void
+re__copy_and_pad(Char *dst, const Char *src, size_t width)
+{
+       size_t i;
+
+       for (i = 0; i < width; i++) {
+               if (*src == '\0')
+                       break;
+               *dst++ = *src++;
+       }
+
+       for (; i < width; i++)
+               *dst++ = ' ';
+
+       *dst = '\0';
+}
+
+
+/* re_refresh_cursor():
+ *     Move to the new cursor position
+ */
+protected void
+re_refresh_cursor(EditLine *el)
+{
+       Char *cp;
+       int h, v, th, w;
+
+       if (el->el_line.cursor >= el->el_line.lastchar) {
+               if (el->el_map.current == el->el_map.alt
+                   && el->el_line.lastchar != el->el_line.buffer)
+                       el->el_line.cursor = el->el_line.lastchar - 1;
+               else
+                       el->el_line.cursor = el->el_line.lastchar;
+       }
+
+       /* first we must find where the cursor is... */
+       h = el->el_prompt.p_pos.h;
+       v = el->el_prompt.p_pos.v;
+       th = el->el_terminal.t_size.h;  /* optimize for speed */
+
+       /* do input buffer to el->el_line.cursor */
+       for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
+                switch (ct_chr_class(*cp)) {
+               case CHTYPE_NL:  /* handle newline in data part too */
+                       h = 0;
+                       v++;
+                       break;
+               case CHTYPE_TAB: /* if a tab, to next tab stop */
+                       while (++h & 07)
+                               continue;
+                       break;
+               default:
+                       w = Width(*cp);
+                       if (w > 1 && h + w > th) { /* won't fit on line */
+                               h = 0;
+                               v++;
+                       }
+                       h += ct_visual_width(*cp);
+                       break;
+                }
+
+               if (h >= th) {  /* check, extra long tabs picked up here also */
+                       h -= th;
+                       v++;
+               }
+       }
+        /* if we have a next character, and it's a doublewidth one, we need to
+         * check whether we need to linebreak for it to fit */
+        if (cp < el->el_line.lastchar && (w = Width(*cp)) > 1)
+                if (h + w > th) {
+                    h = 0;
+                    v++;
+                }
+
+       /* now go there */
+       terminal_move_to_line(el, v);
+       terminal_move_to_char(el, h);
+       terminal__flush(el);
+}
+
+
+/* re_fastputc():
+ *     Add a character fast.
+ */
+private void
+re_fastputc(EditLine *el, Int c)
+{
+       int w = Width((Char)c);
+       while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h)
+           re_fastputc(el, ' ');
+
+       terminal__putc(el, c);
+       el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
+       while (--w > 0)
+               el->el_display[el->el_cursor.v][el->el_cursor.h++]
+                       = MB_FILL_CHAR;
+
+       if (el->el_cursor.h >= el->el_terminal.t_size.h) {
+               /* if we must overflow */
+               el->el_cursor.h = 0;
+
+               /*
+                * If we would overflow (input is longer than terminal size),
+                * emulate scroll by dropping first line and shuffling the rest.
+                * We do this via pointer shuffling - it's safe in this case
+                * and we avoid memcpy().
+                */
+               if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) {
+                       int i, lins = el->el_terminal.t_size.v;
+                       Char *firstline = el->el_display[0];
+       
+                       for(i = 1; i < lins; i++)
+                               el->el_display[i - 1] = el->el_display[i];
+
+                       re__copy_and_pad(firstline, STR(""), (size_t)0);
+                       el->el_display[i - 1] = firstline;
+               } else {
+                       el->el_cursor.v++;
+                       el->el_refresh.r_oldcv++;
+               }
+               if (EL_HAS_AUTO_MARGINS) {
+                       if (EL_HAS_MAGIC_MARGINS) {
+                               terminal__putc(el, ' ');
+                               terminal__putc(el, '\b');
+                       }
+               } else {
+                       terminal__putc(el, '\r');
+                       terminal__putc(el, '\n');
+               }
+       }
+}
+
+
+/* re_fastaddc():
+ *     we added just one char, handle it fast.
+ *     Assumes that screen cursor == real cursor
+ */
+protected void
+re_fastaddc(EditLine *el)
+{
+       Char c;
+       int rhdiff;
+
+       c = el->el_line.cursor[-1];
+
+       if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
+               re_refresh(el); /* too hard to handle */
+               return;
+       }
+       rhdiff = el->el_terminal.t_size.h - el->el_cursor.h -
+           el->el_rprompt.p_pos.h;
+       if (el->el_rprompt.p_pos.h && rhdiff < 3) {
+               re_refresh(el); /* clear out rprompt if less than 1 char gap */
+               return;
+       }                       /* else (only do at end of line, no TAB) */
+       switch (ct_chr_class(c)) {
+       case CHTYPE_TAB: /* already handled, should never happen here */
+               break;
+       case CHTYPE_NL:
+       case CHTYPE_PRINT:
+               re_fastputc(el, c);
+               break;
+       case CHTYPE_ASCIICTL:
+       case CHTYPE_NONPRINT: {
+               Char visbuf[VISUAL_WIDTH_MAX];
+               ssize_t i, n =
+                   ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
+               for (i = 0; n-- > 0; ++i)
+                       re_fastputc(el, visbuf[i]);
+               break;
+       }
+       }
+       terminal__flush(el);
+}
+
+
+/* re_clear_display():
+ *     clear the screen buffers so that new new prompt starts fresh.
+ */
+protected void
+re_clear_display(EditLine *el)
+{
+       int i;
+
+       el->el_cursor.v = 0;
+       el->el_cursor.h = 0;
+       for (i = 0; i < el->el_terminal.t_size.v; i++)
+               el->el_display[i][0] = '\0';
+       el->el_refresh.r_oldcv = 0;
+}
+
+
+/* re_clear_lines():
+ *     Make sure all lines are *really* blank
+ */
+protected void
+re_clear_lines(EditLine *el)
+{
+
+       if (EL_CAN_CEOL) {
+               int i;
+               for (i = el->el_refresh.r_oldcv; i >= 0; i--) {
+                       /* for each line on the screen */
+                       terminal_move_to_line(el, i);
+                       terminal_move_to_char(el, 0);
+                       terminal_clear_EOL(el, el->el_terminal.t_size.h);
+               }
+       } else {
+               terminal_move_to_line(el, el->el_refresh.r_oldcv);
+                                       /* go to last line */
+               terminal__putc(el, '\r');       /* go to BOL */
+               terminal__putc(el, '\n');       /* go to new line */
+       }
+}
diff --git a/lib/libedit/refresh.h b/lib/libedit/refresh.h
new file mode 100644 (file)
index 0000000..f80be46
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: refresh.h,v 1.6 2009/12/30 22:37:40 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)refresh.h   8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.refresh.h: Screen refresh functions
+ */
+#ifndef _h_el_refresh
+#define        _h_el_refresh
+
+#include "histedit.h"
+
+typedef struct {
+       coord_t r_cursor;       /* Refresh cursor position      */
+       int     r_oldcv;        /* Vertical locations           */
+       int     r_newcv;
+} el_refresh_t;
+
+protected void re_putc(EditLine *, Int, int);
+protected void re_clear_lines(EditLine *);
+protected void re_clear_display(EditLine *);
+protected void re_refresh(EditLine *);
+protected void re_refresh_cursor(EditLine *);
+protected void re_fastaddc(EditLine *);
+protected void re_goto_bottom(EditLine *);
+
+#endif /* _h_el_refresh */
diff --git a/lib/libedit/search.c b/lib/libedit/search.c
new file mode 100644 (file)
index 0000000..762b406
--- /dev/null
@@ -0,0 +1,641 @@
+/*     $NetBSD: search.c,v 1.30 2011/10/04 15:27:04 christos Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)search.c   8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: search.c,v 1.30 2011/10/04 15:27:04 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * search.c: History and character search functions
+ */
+#include <stdlib.h>
+#if defined(REGEX)
+#include <regex.h>
+#elif defined(REGEXP)
+#include <regexp.h>
+#endif
+#include "el.h"
+
+/*
+ * Adjust cursor in vi mode to include the character under it
+ */
+#define        EL_CURSOR(el) \
+    ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
+                           ((el)->el_map.current == (el)->el_map.alt)))
+
+/* search_init():
+ *     Initialize the search stuff
+ */
+protected int
+search_init(EditLine *el)
+{
+
+       el->el_search.patbuf = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_search.patbuf));
+       if (el->el_search.patbuf == NULL)
+               return -1;
+       el->el_search.patlen = 0;
+       el->el_search.patdir = -1;
+       el->el_search.chacha = '\0';
+       el->el_search.chadir = CHAR_FWD;
+       el->el_search.chatflg = 0;
+       return 0;
+}
+
+
+/* search_end():
+ *     Initialize the search stuff
+ */
+protected void
+search_end(EditLine *el)
+{
+
+       el_free(el->el_search.patbuf);
+       el->el_search.patbuf = NULL;
+}
+
+
+#ifdef REGEXP
+/* regerror():
+ *     Handle regular expression errors
+ */
+public void
+/*ARGSUSED*/
+regerror(const char *msg)
+{
+}
+#endif
+
+
+/* el_match():
+ *     Return if string matches pattern
+ */
+protected int
+el_match(const Char *str, const Char *pat)
+{
+#ifdef WIDECHAR
+       static ct_buffer_t conv;
+#endif
+#if defined (REGEX)
+       regex_t re;
+       int rv;
+#elif defined (REGEXP)
+       regexp *rp;
+       int rv;
+#else
+       extern char     *re_comp(const char *);
+       extern int       re_exec(const char *);
+#endif
+
+       if (Strstr(str, pat) != 0)
+               return 1;
+
+#if defined(REGEX)
+       if (regcomp(&re, ct_encode_string(pat, &conv), 0) == 0) {
+               rv = regexec(&re, ct_encode_string(str, &conv), (size_t)0, NULL,
+                   0) == 0;
+               regfree(&re);
+       } else {
+               rv = 0;
+       }
+       return rv;
+#elif defined(REGEXP)
+       if ((re = regcomp(ct_encode_string(pat, &conv))) != NULL) {
+               rv = regexec(re, ct_encode_string(str, &conv));
+               el_free(re);
+       } else {
+               rv = 0;
+       }
+       return rv;
+#else
+       if (re_comp(ct_encode_string(pat, &conv)) != NULL)
+               return 0;
+       else
+               return re_exec(ct_encode_string(str, &conv) == 1);
+#endif
+}
+
+
+/* c_hmatch():
+ *      return True if the pattern matches the prefix
+ */
+protected int
+c_hmatch(EditLine *el, const Char *str)
+{
+#ifdef SDEBUG
+       (void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
+           el->el_search.patbuf, str);
+#endif /* SDEBUG */
+
+       return el_match(str, el->el_search.patbuf);
+}
+
+
+/* c_setpat():
+ *     Set the history seatch pattern
+ */
+protected void
+c_setpat(EditLine *el)
+{
+       if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
+           el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
+               el->el_search.patlen =
+                   (size_t)(EL_CURSOR(el) - el->el_line.buffer);
+               if (el->el_search.patlen >= EL_BUFSIZ)
+                       el->el_search.patlen = EL_BUFSIZ - 1;
+               if (el->el_search.patlen != 0) {
+                       (void) Strncpy(el->el_search.patbuf, el->el_line.buffer,
+                           el->el_search.patlen);
+                       el->el_search.patbuf[el->el_search.patlen] = '\0';
+               } else
+                       el->el_search.patlen = Strlen(el->el_search.patbuf);
+       }
+#ifdef SDEBUG
+       (void) fprintf(el->el_errfile, "\neventno = %d\n",
+           el->el_history.eventno);
+       (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
+       (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n",
+           el->el_search.patbuf);
+       (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
+           EL_CURSOR(el) - el->el_line.buffer,
+           el->el_line.lastchar - el->el_line.buffer);
+#endif
+}
+
+
+/* ce_inc_search():
+ *     Emacs incremental search
+ */
+protected el_action_t
+ce_inc_search(EditLine *el, int dir)
+{
+       static const Char STRfwd[] = {'f', 'w', 'd', '\0'},
+            STRbck[] = {'b', 'c', 'k', '\0'};
+       static Char pchar = ':';/* ':' = normal, '?' = failed */
+       static Char endcmd[2] = {'\0', '\0'};
+       Char ch, *ocursor = el->el_line.cursor, oldpchar = pchar;
+       const Char *cp;
+
+       el_action_t ret = CC_NORM;
+
+       int ohisteventno = el->el_history.eventno;
+       size_t oldpatlen = el->el_search.patlen;
+       int newdir = dir;
+       int done, redo;
+
+       if (el->el_line.lastchar + sizeof(STRfwd) /
+           sizeof(*el->el_line.lastchar) + 2 +
+           el->el_search.patlen >= el->el_line.limit)
+               return CC_ERROR;
+
+       for (;;) {
+
+               if (el->el_search.patlen == 0) {        /* first round */
+                       pchar = ':';
+#ifdef ANCHOR
+#define        LEN     2
+                       el->el_search.patbuf[el->el_search.patlen++] = '.';
+                       el->el_search.patbuf[el->el_search.patlen++] = '*';
+#else
+#define        LEN     0
+#endif
+               }
+               done = redo = 0;
+               *el->el_line.lastchar++ = '\n';
+               for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd;
+                   *cp; *el->el_line.lastchar++ = *cp++)
+                       continue;
+               *el->el_line.lastchar++ = pchar;
+               for (cp = &el->el_search.patbuf[LEN];
+                   cp < &el->el_search.patbuf[el->el_search.patlen];
+                   *el->el_line.lastchar++ = *cp++)
+                       continue;
+               *el->el_line.lastchar = '\0';
+               re_refresh(el);
+
+               if (FUN(el,getc)(el, &ch) != 1)
+                       return ed_end_of_file(el, 0);
+
+               switch (el->el_map.current[(unsigned char) ch]) {
+               case ED_INSERT:
+               case ED_DIGIT:
+                       if (el->el_search.patlen >= EL_BUFSIZ - LEN)
+                               terminal_beep(el);
+                       else {
+                               el->el_search.patbuf[el->el_search.patlen++] =
+                                   ch;
+                               *el->el_line.lastchar++ = ch;
+                               *el->el_line.lastchar = '\0';
+                               re_refresh(el);
+                       }
+                       break;
+
+               case EM_INC_SEARCH_NEXT:
+                       newdir = ED_SEARCH_NEXT_HISTORY;
+                       redo++;
+                       break;
+
+               case EM_INC_SEARCH_PREV:
+                       newdir = ED_SEARCH_PREV_HISTORY;
+                       redo++;
+                       break;
+
+               case EM_DELETE_PREV_CHAR:
+               case ED_DELETE_PREV_CHAR:
+                       if (el->el_search.patlen > LEN)
+                               done++;
+                       else
+                               terminal_beep(el);
+                       break;
+
+               default:
+                       switch (ch) {
+                       case 0007:      /* ^G: Abort */
+                               ret = CC_ERROR;
+                               done++;
+                               break;
+
+                       case 0027:      /* ^W: Append word */
+                       /* No can do if globbing characters in pattern */
+                               for (cp = &el->el_search.patbuf[LEN];; cp++)
+                                   if (cp >= &el->el_search.patbuf[
+                                       el->el_search.patlen]) {
+                                       el->el_line.cursor +=
+                                           el->el_search.patlen - LEN - 1;
+                                       cp = c__next_word(el->el_line.cursor,
+                                           el->el_line.lastchar, 1,
+                                           ce__isword);
+                                       while (el->el_line.cursor < cp &&
+                                           *el->el_line.cursor != '\n') {
+                                               if (el->el_search.patlen >=
+                                                   EL_BUFSIZ - LEN) {
+                                                       terminal_beep(el);
+                                                       break;
+                                               }
+                                               el->el_search.patbuf[el->el_search.patlen++] =
+                                                   *el->el_line.cursor;
+                                               *el->el_line.lastchar++ =
+                                                   *el->el_line.cursor++;
+                                       }
+                                       el->el_line.cursor = ocursor;
+                                       *el->el_line.lastchar = '\0';
+                                       re_refresh(el);
+                                       break;
+                                   } else if (isglob(*cp)) {
+                                           terminal_beep(el);
+                                           break;
+                                   }
+                               break;
+
+                       default:        /* Terminate and execute cmd */
+                               endcmd[0] = ch;
+                               FUN(el,push)(el, endcmd);
+                               /* FALLTHROUGH */
+
+                       case 0033:      /* ESC: Terminate */
+                               ret = CC_REFRESH;
+                               done++;
+                               break;
+                       }
+                       break;
+               }
+
+               while (el->el_line.lastchar > el->el_line.buffer &&
+                   *el->el_line.lastchar != '\n')
+                       *el->el_line.lastchar-- = '\0';
+               *el->el_line.lastchar = '\0';
+
+               if (!done) {
+
+                       /* Can't search if unmatched '[' */
+                       for (cp = &el->el_search.patbuf[el->el_search.patlen-1],
+                           ch = ']';
+                           cp >= &el->el_search.patbuf[LEN];
+                           cp--)
+                               if (*cp == '[' || *cp == ']') {
+                                       ch = *cp;
+                                       break;
+                               }
+                       if (el->el_search.patlen > LEN && ch != '[') {
+                               if (redo && newdir == dir) {
+                                       if (pchar == '?') { /* wrap around */
+                                               el->el_history.eventno =
+                                                   newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
+                                               if (hist_get(el) == CC_ERROR)
+                                                       /* el->el_history.event
+                                                        * no was fixed by
+                                                        * first call */
+                                                       (void) hist_get(el);
+                                               el->el_line.cursor = newdir ==
+                                                   ED_SEARCH_PREV_HISTORY ?
+                                                   el->el_line.lastchar :
+                                                   el->el_line.buffer;
+                                       } else
+                                               el->el_line.cursor +=
+                                                   newdir ==
+                                                   ED_SEARCH_PREV_HISTORY ?
+                                                   -1 : 1;
+                               }
+#ifdef ANCHOR
+                               el->el_search.patbuf[el->el_search.patlen++] =
+                                   '.';
+                               el->el_search.patbuf[el->el_search.patlen++] =
+                                   '*';
+#endif
+                               el->el_search.patbuf[el->el_search.patlen] =
+                                   '\0';
+                               if (el->el_line.cursor < el->el_line.buffer ||
+                                   el->el_line.cursor > el->el_line.lastchar ||
+                                   (ret = ce_search_line(el, newdir))
+                                   == CC_ERROR) {
+                                       /* avoid c_setpat */
+                                       el->el_state.lastcmd =
+                                           (el_action_t) newdir;
+                                       ret = (el_action_t)
+                                           (newdir == ED_SEARCH_PREV_HISTORY ?
+                                           ed_search_prev_history(el, 0) :
+                                           ed_search_next_history(el, 0));
+                                       if (ret != CC_ERROR) {
+                                               el->el_line.cursor = newdir ==
+                                                   ED_SEARCH_PREV_HISTORY ?
+                                                   el->el_line.lastchar :
+                                                   el->el_line.buffer;
+                                               (void) ce_search_line(el,
+                                                   newdir);
+                                       }
+                               }
+                               el->el_search.patlen -= LEN;
+                               el->el_search.patbuf[el->el_search.patlen] =
+                                   '\0';
+                               if (ret == CC_ERROR) {
+                                       terminal_beep(el);
+                                       if (el->el_history.eventno !=
+                                           ohisteventno) {
+                                               el->el_history.eventno =
+                                                   ohisteventno;
+                                               if (hist_get(el) == CC_ERROR)
+                                                       return CC_ERROR;
+                                       }
+                                       el->el_line.cursor = ocursor;
+                                       pchar = '?';
+                               } else {
+                                       pchar = ':';
+                               }
+                       }
+                       ret = ce_inc_search(el, newdir);
+
+                       if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
+                               /*
+                                * break abort of failed search at last
+                                * non-failed
+                                */
+                               ret = CC_NORM;
+
+               }
+               if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
+                       /* restore on normal return or error exit */
+                       pchar = oldpchar;
+                       el->el_search.patlen = oldpatlen;
+                       if (el->el_history.eventno != ohisteventno) {
+                               el->el_history.eventno = ohisteventno;
+                               if (hist_get(el) == CC_ERROR)
+                                       return CC_ERROR;
+                       }
+                       el->el_line.cursor = ocursor;
+                       if (ret == CC_ERROR)
+                               re_refresh(el);
+               }
+               if (done || ret != CC_NORM)
+                       return ret;
+       }
+}
+
+
+/* cv_search():
+ *     Vi search.
+ */
+protected el_action_t
+cv_search(EditLine *el, int dir)
+{
+       Char ch;
+       Char tmpbuf[EL_BUFSIZ];
+       ssize_t tmplen;
+
+#ifdef ANCHOR
+       tmpbuf[0] = '.';
+       tmpbuf[1] = '*';
+#endif
+       tmplen = LEN;
+
+       el->el_search.patdir = dir;
+
+       tmplen = c_gets(el, &tmpbuf[LEN],
+               dir == ED_SEARCH_PREV_HISTORY ? STR("\n/") : STR("\n?") );
+       if (tmplen == -1)
+               return CC_REFRESH;
+
+       tmplen += LEN;
+       ch = tmpbuf[tmplen];
+       tmpbuf[tmplen] = '\0';
+
+       if (tmplen == LEN) {
+               /*
+                * Use the old pattern, but wild-card it.
+                */
+               if (el->el_search.patlen == 0) {
+                       re_refresh(el);
+                       return CC_ERROR;
+               }
+#ifdef ANCHOR
+               if (el->el_search.patbuf[0] != '.' &&
+                   el->el_search.patbuf[0] != '*') {
+                       (void) Strncpy(tmpbuf, el->el_search.patbuf,
+                           sizeof(tmpbuf) / sizeof(*tmpbuf) - 1);
+                       el->el_search.patbuf[0] = '.';
+                       el->el_search.patbuf[1] = '*';
+                       (void) Strncpy(&el->el_search.patbuf[2], tmpbuf,
+                           EL_BUFSIZ - 3);
+                       el->el_search.patlen++;
+                       el->el_search.patbuf[el->el_search.patlen++] = '.';
+                       el->el_search.patbuf[el->el_search.patlen++] = '*';
+                       el->el_search.patbuf[el->el_search.patlen] = '\0';
+               }
+#endif
+       } else {
+#ifdef ANCHOR
+               tmpbuf[tmplen++] = '.';
+               tmpbuf[tmplen++] = '*';
+#endif
+               tmpbuf[tmplen] = '\0';
+               (void) Strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
+               el->el_search.patlen = (size_t)tmplen;
+       }
+       el->el_state.lastcmd = (el_action_t) dir;       /* avoid c_setpat */
+       el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
+       if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
+           ed_search_next_history(el, 0)) == CC_ERROR) {
+               re_refresh(el);
+               return CC_ERROR;
+       }
+       if (ch == 0033) {
+               re_refresh(el);
+               return ed_newline(el, 0);
+       }
+       return CC_REFRESH;
+}
+
+
+/* ce_search_line():
+ *     Look for a pattern inside a line
+ */
+protected el_action_t
+ce_search_line(EditLine *el, int dir)
+{
+       Char *cp = el->el_line.cursor;
+       Char *pattern = el->el_search.patbuf;
+       Char oc, *ocp;
+#ifdef ANCHOR
+       ocp = &pattern[1];
+       oc = *ocp;
+       *ocp = '^';
+#else
+       ocp = pattern;
+       oc = *ocp;
+#endif
+
+       if (dir == ED_SEARCH_PREV_HISTORY) {
+               for (; cp >= el->el_line.buffer; cp--) {
+                       if (el_match(cp, ocp)) {
+                               *ocp = oc;
+                               el->el_line.cursor = cp;
+                               return CC_NORM;
+                       }
+               }
+               *ocp = oc;
+               return CC_ERROR;
+       } else {
+               for (; *cp != '\0' && cp < el->el_line.limit; cp++) {
+                       if (el_match(cp, ocp)) {
+                               *ocp = oc;
+                               el->el_line.cursor = cp;
+                               return CC_NORM;
+                       }
+               }
+               *ocp = oc;
+               return CC_ERROR;
+       }
+}
+
+
+/* cv_repeat_srch():
+ *     Vi repeat search
+ */
+protected el_action_t
+cv_repeat_srch(EditLine *el, Int c)
+{
+
+#ifdef SDEBUG
+       (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
+           c, el->el_search.patlen, ct_encode_string(el->el_search.patbuf));
+#endif
+
+       el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
+       el->el_line.lastchar = el->el_line.buffer;
+
+       switch (c) {
+       case ED_SEARCH_NEXT_HISTORY:
+               return ed_search_next_history(el, 0);
+       case ED_SEARCH_PREV_HISTORY:
+               return ed_search_prev_history(el, 0);
+       default:
+               return CC_ERROR;
+       }
+}
+
+
+/* cv_csearch():
+ *     Vi character search
+ */
+protected el_action_t
+cv_csearch(EditLine *el, int direction, Int ch, int count, int tflag)
+{
+       Char *cp;
+
+       if (ch == 0)
+               return CC_ERROR;
+
+       if (ch == (Int)-1) {
+               Char c;
+               if (FUN(el,getc)(el, &c) != 1)
+                       return ed_end_of_file(el, 0);
+               ch = c;
+       }
+
+       /* Save for ';' and ',' commands */
+       el->el_search.chacha = ch;
+       el->el_search.chadir = direction;
+       el->el_search.chatflg = (char)tflag;
+
+       cp = el->el_line.cursor;
+       while (count--) {
+               if ((Int)*cp == ch)
+                       cp += direction;
+               for (;;cp += direction) {
+                       if (cp >= el->el_line.lastchar)
+                               return CC_ERROR;
+                       if (cp < el->el_line.buffer)
+                               return CC_ERROR;
+                       if ((Int)*cp == ch)
+                               break;
+               }
+       }
+
+       if (tflag)
+               cp -= direction;
+
+       el->el_line.cursor = cp;
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               if (direction > 0)
+                       el->el_line.cursor++;
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
diff --git a/lib/libedit/search.h b/lib/libedit/search.h
new file mode 100644 (file)
index 0000000..d9f27e5
--- /dev/null
@@ -0,0 +1,66 @@
+/*     $NetBSD: search.h,v 1.9 2009/12/30 22:37:40 christos Exp $      */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)search.h    8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.search.h: Line and history searching utilities
+ */
+#ifndef _h_el_search
+#define        _h_el_search
+
+#include "histedit.h"
+
+typedef struct el_search_t {
+       Char    *patbuf;                /* The pattern buffer           */
+       size_t   patlen;                /* Length of the pattern buffer */
+       int      patdir;                /* Direction of the last search */
+       int      chadir;                /* Character search direction   */
+       Char     chacha;                /* Character we are looking for */
+       char     chatflg;               /* 0 if f, 1 if t */
+} el_search_t;
+
+
+protected int          el_match(const Char *, const Char *);
+protected int          search_init(EditLine *);
+protected void         search_end(EditLine *);
+protected int          c_hmatch(EditLine *, const Char *);
+protected void         c_setpat(EditLine *);
+protected el_action_t  ce_inc_search(EditLine *, int);
+protected el_action_t  cv_search(EditLine *, int);
+protected el_action_t  ce_search_line(EditLine *, int);
+protected el_action_t  cv_repeat_srch(EditLine *, Int);
+protected el_action_t  cv_csearch(EditLine *, int, Int, int, int);
+
+#endif /* _h_el_search */
diff --git a/lib/libedit/shlib_version b/lib/libedit/shlib_version
new file mode 100644 (file)
index 0000000..778486c
--- /dev/null
@@ -0,0 +1,5 @@
+#      $NetBSD: shlib_version,v 1.18 2009/01/11 03:07:48 christos Exp $
+#      Remember to update distrib/sets/lists/base/shl.* when changing
+#
+major=3
+minor=0
diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c
new file mode 100644 (file)
index 0000000..a5a8a89
--- /dev/null
@@ -0,0 +1,200 @@
+/*     $NetBSD: sig.c,v 1.17 2011/07/28 20:50:55 christos Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)sig.c      8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: sig.c,v 1.17 2011/07/28 20:50:55 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * sig.c: Signal handling stuff.
+ *       our policy is to trap all signals, set a good state
+ *       and pass the ball to our caller.
+ */
+#include "el.h"
+#include <stdlib.h>
+
+private EditLine *sel = NULL;
+
+private const int sighdl[] = {
+#define        _DO(a)  (a),
+       ALLSIGS
+#undef _DO
+       - 1
+};
+
+private void sig_handler(int);
+
+/* sig_handler():
+ *     This is the handler called for all signals
+ *     XXX: we cannot pass any data so we just store the old editline
+ *     state in a private variable
+ */
+private void
+sig_handler(int signo)
+{
+       int i;
+       sigset_t nset, oset;
+
+       (void) sigemptyset(&nset);
+       (void) sigaddset(&nset, signo);
+       (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+       sel->el_signal->sig_no = signo;
+
+       switch (signo) {
+       case SIGCONT:
+               tty_rawmode(sel);
+               if (ed_redisplay(sel, 0) == CC_REFRESH)
+                       re_refresh(sel);
+               terminal__flush(sel);
+               break;
+
+       case SIGWINCH:
+               el_resize(sel);
+               break;
+
+       default:
+               tty_cookedmode(sel);
+               break;
+       }
+
+       for (i = 0; sighdl[i] != -1; i++)
+               if (signo == sighdl[i])
+                       break;
+
+       (void) sigaction(signo, &sel->el_signal->sig_action[i], NULL);
+       sel->el_signal->sig_action[i].sa_handler = SIG_ERR;
+       sel->el_signal->sig_action[i].sa_flags = 0;
+       sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+       (void) kill(0, signo);
+}
+
+
+/* sig_init():
+ *     Initialize all signal stuff
+ */
+protected int
+sig_init(EditLine *el)
+{
+       size_t i;
+       sigset_t *nset, oset;
+
+       el->el_signal = el_malloc(sizeof(*el->el_signal));
+       if (el->el_signal == NULL)
+               return -1;
+
+       nset = &el->el_signal->sig_set;
+       (void) sigemptyset(nset);
+#define        _DO(a) (void) sigaddset(nset, a);
+       ALLSIGS
+#undef _DO
+       (void) sigprocmask(SIG_BLOCK, nset, &oset);
+
+       for (i = 0; sighdl[i] != -1; i++) {
+               el->el_signal->sig_action[i].sa_handler = SIG_ERR;
+               el->el_signal->sig_action[i].sa_flags = 0;
+               sigemptyset(&el->el_signal->sig_action[i].sa_mask);
+       }
+
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+
+       return 0;
+}
+
+
+/* sig_end():
+ *     Clear all signal stuff
+ */
+protected void
+sig_end(EditLine *el)
+{
+
+       el_free(el->el_signal);
+       el->el_signal = NULL;
+}
+
+
+/* sig_set():
+ *     set all the signal handlers
+ */
+protected void
+sig_set(EditLine *el)
+{
+       size_t i;
+       sigset_t oset;
+       struct sigaction osa, nsa;
+
+       nsa.sa_handler = sig_handler;
+       nsa.sa_flags = 0;
+       sigemptyset(&nsa.sa_mask);
+
+       (void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
+
+       for (i = 0; sighdl[i] != -1; i++) {
+               /* This could happen if we get interrupted */
+               if (sigaction(sighdl[i], &nsa, &osa) != -1 &&
+                   osa.sa_handler != sig_handler)
+                       el->el_signal->sig_action[i] = osa;
+       }
+       sel = el;
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+
+/* sig_clr():
+ *     clear all the signal handlers
+ */
+protected void
+sig_clr(EditLine *el)
+{
+       size_t i;
+       sigset_t oset;
+
+       (void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
+
+       for (i = 0; sighdl[i] != -1; i++)
+               if (el->el_signal->sig_action[i].sa_handler != SIG_ERR)
+                       (void)sigaction(sighdl[i],
+                           &el->el_signal->sig_action[i], NULL);
+
+       sel = NULL;             /* we are going to die if the handler is
+                                * called */
+       (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+}
diff --git a/lib/libedit/sig.h b/lib/libedit/sig.h
new file mode 100644 (file)
index 0000000..c957cfd
--- /dev/null
@@ -0,0 +1,72 @@
+/*     $NetBSD: sig.h,v 1.8 2009/02/19 15:20:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)sig.h       8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.sig.h: Signal handling functions
+ */
+#ifndef _h_el_sig
+#define        _h_el_sig
+
+#include <signal.h>
+
+#include "histedit.h"
+
+/*
+ * Define here all the signals we are going to handle
+ * The _DO macro is used to iterate in the source code
+ */
+#define        ALLSIGS         \
+       _DO(SIGINT)     \
+       _DO(SIGTSTP)    \
+       _DO(SIGQUIT)    \
+       _DO(SIGHUP)     \
+       _DO(SIGTERM)    \
+       _DO(SIGCONT)    \
+       _DO(SIGWINCH)
+#define ALLSIGSNO      7
+
+typedef struct {
+       struct sigaction sig_action[ALLSIGSNO];
+       sigset_t sig_set;
+       volatile sig_atomic_t sig_no;
+} *el_signal_t;
+
+protected void sig_end(EditLine*);
+protected int  sig_init(EditLine*);
+protected void sig_set(EditLine*);
+protected void sig_clr(EditLine*);
+
+#endif /* _h_el_sig */
diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h
new file mode 100644 (file)
index 0000000..690e135
--- /dev/null
@@ -0,0 +1,128 @@
+/*     $NetBSD: sys.h,v 1.17 2011/09/28 14:08:04 christos Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)sys.h       8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * sys.h: Put all the stupid compiler and system dependencies here...
+ */
+#ifndef _h_sys
+#define        _h_sys
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__)  || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
+# define __attribute__(A)
+#endif
+
+#ifndef __BEGIN_DECLS
+# ifdef  __cplusplus
+#  define __BEGIN_DECLS  extern "C" {
+#  define __END_DECLS    }
+# else
+#  define __BEGIN_DECLS
+#  define __END_DECLS
+# endif
+#endif
+#ifndef public
+# define public                /* Externally visible functions/variables */
+#endif
+
+#ifndef private
+# define private       static  /* Always hidden internals */
+#endif
+
+#ifndef protected
+# define protected     /* Redefined from elsewhere to "static" */
+                       /* When we want to hide everything      */
+#endif
+
+#ifndef __arraycount
+# define __arraycount(a) (sizeof(a) / sizeof(*(a)))
+#endif
+
+#include <stdio.h>
+
+#ifndef HAVE_STRLCAT
+#define        strlcat libedit_strlcat
+size_t strlcat(char *dst, const char *src, size_t size);
+#endif
+
+#ifndef HAVE_STRLCPY
+#define        strlcpy libedit_strlcpy
+size_t strlcpy(char *dst, const char *src, size_t size);
+#endif
+
+#ifndef HAVE_FGETLN
+#define        fgetln libedit_fgetln
+char   *fgetln(FILE *fp, size_t *len);
+#endif
+
+#ifndef HAVE_WCSDUP
+#include <wchar.h>
+wchar_t *wcsdup(const wchar_t *);
+#endif
+
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(x)
+#endif
+
+#ifndef __RCSID
+#define __RCSID(x)
+#endif
+
+#ifndef HAVE_U_INT32_T
+typedef unsigned int   u_int32_t;
+#endif
+
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX     ((size_t)-1)
+#endif
+
+#define        REGEX           /* Use POSIX.2 regular expression functions */
+#undef REGEXP          /* Use UNIX V8 regular expression functions */
+
+#if defined(__sun)
+extern int tgetent(char *, const char *);
+extern int tgetflag(char *);
+extern int tgetnum(char *);
+extern int tputs(const char *, int, int (*)(int));
+extern char* tgoto(const char*, int, int);
+extern char* tgetstr(char*, char**);
+#endif
+
+#endif /* _h_sys */
diff --git a/lib/libedit/sysunix.c b/lib/libedit/sysunix.c
deleted file mode 100644 (file)
index 0bee530..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-**  Unix system-dependant routines for editline library.
-*/
-#include "editline.h"
-
-#if    defined(HAVE_TCGETATTR)
-#include <termios.h>
-
-void
-rl_ttyset(Reset)
-    int                                Reset;
-{
-    static struct termios      old;
-    struct termios             new;
-
-    if (Reset == 0) {
-       (void)tcgetattr(0, &old);
-       rl_erase = old.c_cc[VERASE];
-       rl_kill = old.c_cc[VKILL];
-       rl_eof = old.c_cc[VEOF];
-       rl_intr = old.c_cc[VINTR];
-       rl_quit = old.c_cc[VQUIT];
-
-       new = old;
-       new.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
-       new.c_iflag &= ~(ICRNL);
-       new.c_cc[VMIN] = 1;
-       new.c_cc[VTIME] = 0;
-       (void)tcsetattr(0, TCSADRAIN, &new);
-    }
-    else
-       (void)tcsetattr(0, TCSADRAIN, &old);
-}
-
-#else
-#if    defined(HAVE_TERMIO)
-#include <termio.h>
-
-void
-rl_ttyset(Reset)
-    int                                Reset;
-{
-    static struct termio       old;
-    struct termio              new;
-
-    if (Reset == 0) {
-       (void)ioctl(0, TCGETA, &old);
-       rl_erase = old.c_cc[VERASE];
-       rl_kill = old.c_cc[VKILL];
-       rl_eof = old.c_cc[VEOF];
-       rl_intr = old.c_cc[VINTR];
-       rl_quit = old.c_cc[VQUIT];
-
-       new = old;
-       new.c_cc[VINTR] = -1;
-       new.c_cc[VQUIT] = -1;
-       new.c_lflag &= ~(ECHO | ICANON);
-       new.c_cc[VMIN] = 1;
-       new.c_cc[VTIME] = 0;
-       (void)ioctl(0, TCSETAW, &new);
-    }
-    else
-       (void)ioctl(0, TCSETAW, &old);
-}
-
-#else
-#include <sgtty.h>
-
-void
-rl_ttyset(Reset)
-    int                                Reset;
-{
-    static struct sgttyb       old_sgttyb;
-    static struct tchars       old_tchars;
-    struct sgttyb              new_sgttyb;
-    struct tchars              new_tchars;
-
-    if (Reset == 0) {
-       (void)ioctl(0, TIOCGETP, &old_sgttyb);
-       rl_erase = old_sgttyb.sg_erase;
-       rl_kill = old_sgttyb.sg_kill;
-
-       (void)ioctl(0, TIOCGETC, &old_tchars);
-       rl_eof = old_tchars.t_eofc;
-       rl_intr = old_tchars.t_intrc;
-       rl_quit = old_tchars.t_quitc;
-
-       new_sgttyb = old_sgttyb;
-       new_sgttyb.sg_flags &= ~ECHO;
-       new_sgttyb.sg_flags |= RAW;
-       (void)ioctl(0, TIOCSETP, &new_sgttyb);
-
-       new_tchars = old_tchars;
-       new_tchars.t_intrc = -1;
-       new_tchars.t_quitc = -1;
-       (void)ioctl(0, TIOCSETC, &new_tchars);
-    }
-    else {
-       (void)ioctl(0, TIOCSETP, &old_sgttyb);
-       (void)ioctl(0, TIOCSETC, &old_tchars);
-    }
-}
-#endif /* defined(HAVE_TERMIO) */
-#endif /* defined(HAVE_TCGETATTR) */
-
-void
-rl_add_slash(path, p)
-    char       *path;
-    char       *p;
-{
-    struct stat        Sb;
-
-    if (stat(path, &Sb) >= 0)
-       (void)strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ");
-}
-
-/*
- * $PchId: sysunix.c,v 1.4 1996/02/22 21:16:56 philip Exp $
- */
diff --git a/lib/libedit/terminal.c b/lib/libedit/terminal.c
new file mode 100644 (file)
index 0000000..c4a2543
--- /dev/null
@@ -0,0 +1,1673 @@
+/*     $NetBSD: terminal.c,v 1.14 2012/05/30 18:21:14 christos Exp $   */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)term.c     8.2 (Berkeley) 4/30/95";
+#else
+__RCSID("$NetBSD: terminal.c,v 1.14 2012/05/30 18:21:14 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * terminal.c: Editor/termcap-curses interface
+ *            We have to declare a static variable here, since the
+ *            termcap putchar routine does not take an argument!
+ */
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#ifdef HAVE_TERMCAP_H
+#include <termcap.h>
+#endif
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#elif HAVE_NCURSES_H
+#include <ncurses.h>
+#endif
+
+/* Solaris's term.h does horrid things. */
+#if defined(HAVE_TERM_H) && !defined(__sun) && !defined(HAVE_TERMCAP_H)
+#include <term.h>
+#endif
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#ifdef _REENTRANT
+#include <pthread.h>
+#endif
+
+#include "el.h"
+
+/*
+ * IMPORTANT NOTE: these routines are allowed to look at the current screen
+ * and the current position assuming that it is correct.  If this is not
+ * true, then the update will be WRONG!  This is (should be) a valid
+ * assumption...
+ */
+
+#define        TC_BUFSIZE      ((size_t)2048)
+
+#define        GoodStr(a)      (el->el_terminal.t_str[a] != NULL && \
+                           el->el_terminal.t_str[a][0] != '\0')
+#define        Str(a)          el->el_terminal.t_str[a]
+#define        Val(a)          el->el_terminal.t_val[a]
+
+private const struct termcapstr {
+       const char *name;
+       const char *long_name;
+} tstr[] = {
+#define        T_al    0
+       { "al", "add new blank line" },
+#define        T_bl    1
+       { "bl", "audible bell" },
+#define        T_cd    2
+       { "cd", "clear to bottom" },
+#define        T_ce    3
+       { "ce", "clear to end of line" },
+#define        T_ch    4
+       { "ch", "cursor to horiz pos" },
+#define        T_cl    5
+       { "cl", "clear screen" },
+#define        T_dc    6
+       { "dc", "delete a character" },
+#define        T_dl    7
+       { "dl", "delete a line" },
+#define        T_dm    8
+       { "dm", "start delete mode" },
+#define        T_ed    9
+       { "ed", "end delete mode" },
+#define        T_ei    10
+       { "ei", "end insert mode" },
+#define        T_fs    11
+       { "fs", "cursor from status line" },
+#define        T_ho    12
+       { "ho", "home cursor" },
+#define        T_ic    13
+       { "ic", "insert character" },
+#define        T_im    14
+       { "im", "start insert mode" },
+#define        T_ip    15
+       { "ip", "insert padding" },
+#define        T_kd    16
+       { "kd", "sends cursor down" },
+#define        T_kl    17
+       { "kl", "sends cursor left" },
+#define        T_kr    18
+       { "kr", "sends cursor right" },
+#define        T_ku    19
+       { "ku", "sends cursor up" },
+#define        T_md    20
+       { "md", "begin bold" },
+#define        T_me    21
+       { "me", "end attributes" },
+#define        T_nd    22
+       { "nd", "non destructive space" },
+#define        T_se    23
+       { "se", "end standout" },
+#define        T_so    24
+       { "so", "begin standout" },
+#define        T_ts    25
+       { "ts", "cursor to status line" },
+#define        T_up    26
+       { "up", "cursor up one" },
+#define        T_us    27
+       { "us", "begin underline" },
+#define        T_ue    28
+       { "ue", "end underline" },
+#define        T_vb    29
+       { "vb", "visible bell" },
+#define        T_DC    30
+       { "DC", "delete multiple chars" },
+#define        T_DO    31
+       { "DO", "cursor down multiple" },
+#define        T_IC    32
+       { "IC", "insert multiple chars" },
+#define        T_LE    33
+       { "LE", "cursor left multiple" },
+#define        T_RI    34
+       { "RI", "cursor right multiple" },
+#define        T_UP    35
+       { "UP", "cursor up multiple" },
+#define        T_kh    36
+       { "kh", "send cursor home" },
+#define        T_at7   37
+       { "@7", "send cursor end" },
+#define        T_kD    38
+       { "kD", "send cursor delete" },
+#define        T_str   39
+       { NULL, NULL }
+};
+
+private const struct termcapval {
+       const char *name;
+       const char *long_name;
+} tval[] = {
+#define        T_am    0
+       { "am", "has automatic margins" },
+#define        T_pt    1
+       { "pt", "has physical tabs" },
+#define        T_li    2
+       { "li", "Number of lines" },
+#define        T_co    3
+       { "co", "Number of columns" },
+#define        T_km    4
+       { "km", "Has meta key" },
+#define        T_xt    5
+       { "xt", "Tab chars destructive" },
+#define        T_xn    6
+       { "xn", "newline ignored at right margin" },
+#define        T_MT    7
+       { "MT", "Has meta key" },                       /* XXX? */
+#define        T_val   8
+       { NULL, NULL, }
+};
+/* do two or more of the attributes use me */
+
+private void   terminal_setflags(EditLine *);
+private int    terminal_rebuffer_display(EditLine *);
+private void   terminal_free_display(EditLine *);
+private int    terminal_alloc_display(EditLine *);
+private void   terminal_alloc(EditLine *, const struct termcapstr *,
+    const char *);
+private void   terminal_init_arrow(EditLine *);
+private void   terminal_reset_arrow(EditLine *);
+private int    terminal_putc(int);
+private void   terminal_tputs(EditLine *, const char *, int);
+
+#ifdef _REENTRANT
+private pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+private FILE *terminal_outfile = NULL;
+
+
+/* terminal_setflags():
+ *     Set the terminal capability flags
+ */
+private void
+terminal_setflags(EditLine *el)
+{
+       EL_FLAGS = 0;
+       if (el->el_tty.t_tabs)
+               EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0;
+
+       EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0;
+       EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0;
+       EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0;
+       EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ?
+           TERM_CAN_INSERT : 0;
+       EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0;
+       EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0;
+       EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0;
+
+       if (GoodStr(T_me) && GoodStr(T_ue))
+               EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ?
+                   TERM_CAN_ME : 0;
+       else
+               EL_FLAGS &= ~TERM_CAN_ME;
+       if (GoodStr(T_me) && GoodStr(T_se))
+               EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ?
+                   TERM_CAN_ME : 0;
+
+
+#ifdef DEBUG_SCREEN
+       if (!EL_CAN_UP) {
+               (void) fprintf(el->el_errfile,
+                   "WARNING: Your terminal cannot move up.\n");
+               (void) fprintf(el->el_errfile,
+                   "Editing may be odd for long lines.\n");
+       }
+       if (!EL_CAN_CEOL)
+               (void) fprintf(el->el_errfile, "no clear EOL capability.\n");
+       if (!EL_CAN_DELETE)
+               (void) fprintf(el->el_errfile, "no delete char capability.\n");
+       if (!EL_CAN_INSERT)
+               (void) fprintf(el->el_errfile, "no insert char capability.\n");
+#endif /* DEBUG_SCREEN */
+}
+
+/* terminal_init():
+ *     Initialize the terminal stuff
+ */
+protected int
+terminal_init(EditLine *el)
+{
+
+       el->el_terminal.t_buf = el_malloc(TC_BUFSIZE *
+           sizeof(*el->el_terminal.t_buf));
+       if (el->el_terminal.t_buf == NULL)
+               return -1;
+       el->el_terminal.t_cap = el_malloc(TC_BUFSIZE *
+           sizeof(*el->el_terminal.t_cap));
+       if (el->el_terminal.t_cap == NULL)
+               return -1;
+       el->el_terminal.t_fkey = el_malloc(A_K_NKEYS *
+           sizeof(*el->el_terminal.t_fkey));
+       if (el->el_terminal.t_fkey == NULL)
+               return -1;
+       el->el_terminal.t_loc = 0;
+       el->el_terminal.t_str = el_malloc(T_str *
+           sizeof(*el->el_terminal.t_str));
+       if (el->el_terminal.t_str == NULL)
+               return -1;
+       (void) memset(el->el_terminal.t_str, 0, T_str *
+           sizeof(*el->el_terminal.t_str));
+       el->el_terminal.t_val = el_malloc(T_val *
+           sizeof(*el->el_terminal.t_val));
+       if (el->el_terminal.t_val == NULL)
+               return -1;
+       (void) memset(el->el_terminal.t_val, 0, T_val *
+           sizeof(*el->el_terminal.t_val));
+       (void) terminal_set(el, NULL);
+       terminal_init_arrow(el);
+       return 0;
+}
+
+/* terminal_end():
+ *     Clean up the terminal stuff
+ */
+protected void
+terminal_end(EditLine *el)
+{
+
+       el_free(el->el_terminal.t_buf);
+       el->el_terminal.t_buf = NULL;
+       el_free(el->el_terminal.t_cap);
+       el->el_terminal.t_cap = NULL;
+       el->el_terminal.t_loc = 0;
+       el_free(el->el_terminal.t_str);
+       el->el_terminal.t_str = NULL;
+       el_free(el->el_terminal.t_val);
+       el->el_terminal.t_val = NULL;
+       el_free(el->el_terminal.t_fkey);
+       el->el_terminal.t_fkey = NULL;
+       terminal_free_display(el);
+}
+
+
+/* terminal_alloc():
+ *     Maintain a string pool for termcap strings
+ */
+private void
+terminal_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
+{
+       char termbuf[TC_BUFSIZE];
+       size_t tlen, clen;
+       char **tlist = el->el_terminal.t_str;
+       char **tmp, **str = &tlist[t - tstr];
+
+       (void) memset(termbuf, 0, sizeof(termbuf));
+       if (cap == NULL || *cap == '\0') {
+               *str = NULL;
+               return;
+       } else
+               clen = strlen(cap);
+
+       tlen = *str == NULL ? 0 : strlen(*str);
+
+       /*
+         * New string is shorter; no need to allocate space
+         */
+       if (clen <= tlen) {
+               if (*str)
+                       (void) strcpy(*str, cap);       /* XXX strcpy is safe */
+               return;
+       }
+       /*
+         * New string is longer; see if we have enough space to append
+         */
+       if (el->el_terminal.t_loc + 3 < TC_BUFSIZE) {
+                                               /* XXX strcpy is safe */
+               (void) strcpy(*str = &el->el_terminal.t_buf[
+                   el->el_terminal.t_loc], cap);
+               el->el_terminal.t_loc += clen + 1;      /* one for \0 */
+               return;
+       }
+       /*
+         * Compact our buffer; no need to check compaction, cause we know it
+         * fits...
+         */
+       tlen = 0;
+       for (tmp = tlist; tmp < &tlist[T_str]; tmp++)
+               if (*tmp != NULL && *tmp != '\0' && *tmp != *str) {
+                       char *ptr;
+
+                       for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++)
+                               continue;
+                       termbuf[tlen++] = '\0';
+               }
+       memcpy(el->el_terminal.t_buf, termbuf, TC_BUFSIZE);
+       el->el_terminal.t_loc = tlen;
+       if (el->el_terminal.t_loc + 3 >= TC_BUFSIZE) {
+               (void) fprintf(el->el_errfile,
+                   "Out of termcap string space.\n");
+               return;
+       }
+                                       /* XXX strcpy is safe */
+       (void) strcpy(*str = &el->el_terminal.t_buf[el->el_terminal.t_loc],
+           cap);
+       el->el_terminal.t_loc += (size_t)clen + 1;      /* one for \0 */
+       return;
+}
+
+
+/* terminal_rebuffer_display():
+ *     Rebuffer the display after the screen changed size
+ */
+private int
+terminal_rebuffer_display(EditLine *el)
+{
+       coord_t *c = &el->el_terminal.t_size;
+
+       terminal_free_display(el);
+
+       c->h = Val(T_co);
+       c->v = Val(T_li);
+
+       if (terminal_alloc_display(el) == -1)
+               return -1;
+       return 0;
+}
+
+
+/* terminal_alloc_display():
+ *     Allocate a new display.
+ */
+private int
+terminal_alloc_display(EditLine *el)
+{
+       int i;
+       Char **b;
+       coord_t *c = &el->el_terminal.t_size;
+
+       b =  el_malloc(sizeof(*b) * (size_t)(c->v + 1));
+       if (b == NULL)
+               return -1;
+       for (i = 0; i < c->v; i++) {
+               b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1));
+               if (b[i] == NULL) {
+                       while (--i >= 0)
+                               el_free(b[i]);
+                       el_free(b);
+                       return -1;
+               }
+       }
+       b[c->v] = NULL;
+       el->el_display = b;
+
+       b = el_malloc(sizeof(*b) * (size_t)(c->v + 1));
+       if (b == NULL)
+               return -1;
+       for (i = 0; i < c->v; i++) {
+               b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1));
+               if (b[i] == NULL) {
+                       while (--i >= 0)
+                               el_free(b[i]);
+                       el_free(b);
+                       return -1;
+               }
+       }
+       b[c->v] = NULL;
+       el->el_vdisplay = b;
+       return 0;
+}
+
+
+/* terminal_free_display():
+ *     Free the display buffers
+ */
+private void
+terminal_free_display(EditLine *el)
+{
+       Char **b;
+       Char **bufp;
+
+       b = el->el_display;
+       el->el_display = NULL;
+       if (b != NULL) {
+               for (bufp = b; *bufp != NULL; bufp++)
+                       el_free(*bufp);
+               el_free(b);
+       }
+       b = el->el_vdisplay;
+       el->el_vdisplay = NULL;
+       if (b != NULL) {
+               for (bufp = b; *bufp != NULL; bufp++)
+                       el_free(*bufp);
+               el_free(b);
+       }
+}
+
+
+/* terminal_move_to_line():
+ *     move to line <where> (first line == 0)
+ *     as efficiently as possible
+ */
+protected void
+terminal_move_to_line(EditLine *el, int where)
+{
+       int del;
+
+       if (where == el->el_cursor.v)
+               return;
+
+       if (where > el->el_terminal.t_size.v) {
+#ifdef DEBUG_SCREEN
+               (void) fprintf(el->el_errfile,
+                   "terminal_move_to_line: where is ridiculous: %d\r\n",
+                   where);
+#endif /* DEBUG_SCREEN */
+               return;
+       }
+       if ((del = where - el->el_cursor.v) > 0) {
+               while (del > 0) {
+                       if (EL_HAS_AUTO_MARGINS &&
+                           el->el_display[el->el_cursor.v][0] != '\0') {
+                                size_t h = (size_t)
+                                   (el->el_terminal.t_size.h - 1);
+#ifdef WIDECHAR
+                                for (; h > 0 &&
+                                         el->el_display[el->el_cursor.v][h] ==
+                                                 MB_FILL_CHAR;
+                                         h--)
+                                                continue;
+#endif
+                               /* move without newline */
+                               terminal_move_to_char(el, (int)h);
+                               terminal_overwrite(el, &el->el_display
+                                   [el->el_cursor.v][el->el_cursor.h],
+                                   (size_t)(el->el_terminal.t_size.h -
+                                   el->el_cursor.h));
+                               /* updates Cursor */
+                               del--;
+                       } else {
+                               if ((del > 1) && GoodStr(T_DO)) {
+                                       terminal_tputs(el, tgoto(Str(T_DO), del,
+                                           del), del);
+                                       del = 0;
+                               } else {
+                                       for (; del > 0; del--)
+                                               terminal__putc(el, '\n');
+                                       /* because the \n will become \r\n */
+                                       el->el_cursor.h = 0;
+                               }
+                       }
+               }
+       } else {                /* del < 0 */
+               if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
+                       terminal_tputs(el, tgoto(Str(T_UP), -del, -del), -del);
+               else {
+                       if (GoodStr(T_up))
+                               for (; del < 0; del++)
+                                       terminal_tputs(el, Str(T_up), 1);
+               }
+       }
+       el->el_cursor.v = where;/* now where is here */
+}
+
+
+/* terminal_move_to_char():
+ *     Move to the character position specified
+ */
+protected void
+terminal_move_to_char(EditLine *el, int where)
+{
+       int del, i;
+
+mc_again:
+       if (where == el->el_cursor.h)
+               return;
+
+       if (where > el->el_terminal.t_size.h) {
+#ifdef DEBUG_SCREEN
+               (void) fprintf(el->el_errfile,
+                   "terminal_move_to_char: where is riduculous: %d\r\n",
+                   where);
+#endif /* DEBUG_SCREEN */
+               return;
+       }
+       if (!where) {           /* if where is first column */
+               terminal__putc(el, '\r');       /* do a CR */
+               el->el_cursor.h = 0;
+               return;
+       }
+       del = where - el->el_cursor.h;
+
+       if ((del < -4 || del > 4) && GoodStr(T_ch))
+               /* go there directly */
+               terminal_tputs(el, tgoto(Str(T_ch), where, where), where);
+       else {
+               if (del > 0) {  /* moving forward */
+                       if ((del > 4) && GoodStr(T_RI))
+                               terminal_tputs(el, tgoto(Str(T_RI), del, del),
+                                   del);
+                       else {
+                                       /* if I can do tabs, use them */
+                               if (EL_CAN_TAB) {
+                                       if ((el->el_cursor.h & 0370) !=
+                                           (where & ~0x7)
+#ifdef WIDECHAR
+                                           && (el->el_display[
+                                           el->el_cursor.v][where & 0370] !=
+                                           MB_FILL_CHAR)
+#endif
+                                           ) {
+                                               /* if not within tab stop */
+                                               for (i =
+                                                   (el->el_cursor.h & 0370);
+                                                   i < (where & ~0x7);
+                                                   i += 8)
+                                                       terminal__putc(el,
+                                                           '\t');      
+                                                       /* then tab over */
+                                               el->el_cursor.h = where & ~0x7;
+                                       }
+                               }
+                               /*
+                                * it's usually cheaper to just write the
+                                * chars, so we do.
+                                */
+                               /*
+                                * NOTE THAT terminal_overwrite() WILL CHANGE
+                                * el->el_cursor.h!!!
+                                */
+                               terminal_overwrite(el, &el->el_display[
+                                   el->el_cursor.v][el->el_cursor.h],
+                                   (size_t)(where - el->el_cursor.h));
+
+                       }
+               } else {        /* del < 0 := moving backward */
+                       if ((-del > 4) && GoodStr(T_LE))
+                               terminal_tputs(el, tgoto(Str(T_LE), -del, -del),
+                                   -del);
+                       else {  /* can't go directly there */
+                               /*
+                                * if the "cost" is greater than the "cost"
+                                * from col 0
+                                */
+                               if (EL_CAN_TAB ?
+                                   ((unsigned int)-del >
+                                   (((unsigned int) where >> 3) +
+                                    (where & 07)))
+                                   : (-del > where)) {
+                                       terminal__putc(el, '\r');/* do a CR */
+                                       el->el_cursor.h = 0;
+                                       goto mc_again;  /* and try again */
+                               }
+                               for (i = 0; i < -del; i++)
+                                       terminal__putc(el, '\b');
+                       }
+               }
+       }
+       el->el_cursor.h = where;                /* now where is here */
+}
+
+
+/* terminal_overwrite():
+ *     Overstrike num characters
+ *     Assumes MB_FILL_CHARs are present to keep the column count correct
+ */
+protected void
+terminal_overwrite(EditLine *el, const Char *cp, size_t n)
+{
+       if (n == 0)
+               return;
+
+       if (n > (size_t)el->el_terminal.t_size.h) {
+#ifdef DEBUG_SCREEN
+               (void) fprintf(el->el_errfile,
+                   "terminal_overwrite: n is riduculous: %d\r\n", n);
+#endif /* DEBUG_SCREEN */
+               return;
+       }
+
+        do {
+                /* terminal__putc() ignores any MB_FILL_CHARs */
+                terminal__putc(el, *cp++);
+                el->el_cursor.h++;
+        } while (--n);
+
+       if (el->el_cursor.h >= el->el_terminal.t_size.h) {      /* wrap? */
+               if (EL_HAS_AUTO_MARGINS) {      /* yes */
+                       el->el_cursor.h = 0;
+                       el->el_cursor.v++;
+                       if (EL_HAS_MAGIC_MARGINS) {
+                               /* force the wrap to avoid the "magic"
+                                * situation */
+                               Char c;
+                               if ((c = el->el_display[el->el_cursor.v]
+                                   [el->el_cursor.h]) != '\0') {
+                                       terminal_overwrite(el, &c, (size_t)1);
+#ifdef WIDECHAR
+                                       while (el->el_display[el->el_cursor.v]
+                                           [el->el_cursor.h] == MB_FILL_CHAR)
+                                               el->el_cursor.h++;
+#endif
+                               } else {
+                                       terminal__putc(el, ' ');
+                                       el->el_cursor.h = 1;
+                               }
+                       }
+               } else          /* no wrap, but cursor stays on screen */
+                       el->el_cursor.h = el->el_terminal.t_size.h - 1;
+       }
+}
+
+
+/* terminal_deletechars():
+ *     Delete num characters
+ */
+protected void
+terminal_deletechars(EditLine *el, int num)
+{
+       if (num <= 0)
+               return;
+
+       if (!EL_CAN_DELETE) {
+#ifdef DEBUG_EDIT
+               (void) fprintf(el->el_errfile, "   ERROR: cannot delete   \n");
+#endif /* DEBUG_EDIT */
+               return;
+       }
+       if (num > el->el_terminal.t_size.h) {
+#ifdef DEBUG_SCREEN
+               (void) fprintf(el->el_errfile,
+                   "terminal_deletechars: num is riduculous: %d\r\n", num);
+#endif /* DEBUG_SCREEN */
+               return;
+       }
+       if (GoodStr(T_DC))      /* if I have multiple delete */
+               if ((num > 1) || !GoodStr(T_dc)) {      /* if dc would be more
+                                                        * expen. */
+                       terminal_tputs(el, tgoto(Str(T_DC), num, num), num);
+                       return;
+               }
+       if (GoodStr(T_dm))      /* if I have delete mode */
+               terminal_tputs(el, Str(T_dm), 1);
+
+       if (GoodStr(T_dc))      /* else do one at a time */
+               while (num--)
+                       terminal_tputs(el, Str(T_dc), 1);
+
+       if (GoodStr(T_ed))      /* if I have delete mode */
+               terminal_tputs(el, Str(T_ed), 1);
+}
+
+
+/* terminal_insertwrite():
+ *     Puts terminal in insert character mode or inserts num
+ *     characters in the line
+ *      Assumes MB_FILL_CHARs are present to keep column count correct
+ */
+protected void
+terminal_insertwrite(EditLine *el, Char *cp, int num)
+{
+       if (num <= 0)
+               return;
+       if (!EL_CAN_INSERT) {
+#ifdef DEBUG_EDIT
+               (void) fprintf(el->el_errfile, "   ERROR: cannot insert   \n");
+#endif /* DEBUG_EDIT */
+               return;
+       }
+       if (num > el->el_terminal.t_size.h) {
+#ifdef DEBUG_SCREEN
+               (void) fprintf(el->el_errfile,
+                   "StartInsert: num is riduculous: %d\r\n", num);
+#endif /* DEBUG_SCREEN */
+               return;
+       }
+       if (GoodStr(T_IC))      /* if I have multiple insert */
+               if ((num > 1) || !GoodStr(T_ic)) {
+                               /* if ic would be more expensive */
+                       terminal_tputs(el, tgoto(Str(T_IC), num, num), num);
+                       terminal_overwrite(el, cp, (size_t)num);
+                               /* this updates el_cursor.h */
+                       return;
+               }
+       if (GoodStr(T_im) && GoodStr(T_ei)) {   /* if I have insert mode */
+               terminal_tputs(el, Str(T_im), 1);
+
+               el->el_cursor.h += num;
+               do
+                       terminal__putc(el, *cp++);
+               while (--num);
+
+               if (GoodStr(T_ip))      /* have to make num chars insert */
+                       terminal_tputs(el, Str(T_ip), 1);
+
+               terminal_tputs(el, Str(T_ei), 1);
+               return;
+       }
+       do {
+               if (GoodStr(T_ic))      /* have to make num chars insert */
+                       terminal_tputs(el, Str(T_ic), 1);
+
+               terminal__putc(el, *cp++);
+
+               el->el_cursor.h++;
+
+               if (GoodStr(T_ip))      /* have to make num chars insert */
+                       terminal_tputs(el, Str(T_ip), 1);
+                                       /* pad the inserted char */
+
+       } while (--num);
+}
+
+
+/* terminal_clear_EOL():
+ *     clear to end of line.  There are num characters to clear
+ */
+protected void
+terminal_clear_EOL(EditLine *el, int num)
+{
+       int i;
+
+       if (EL_CAN_CEOL && GoodStr(T_ce))
+               terminal_tputs(el, Str(T_ce), 1);
+       else {
+               for (i = 0; i < num; i++)
+                       terminal__putc(el, ' ');
+               el->el_cursor.h += num; /* have written num spaces */
+       }
+}
+
+
+/* terminal_clear_screen():
+ *     Clear the screen
+ */
+protected void
+terminal_clear_screen(EditLine *el)
+{                              /* clear the whole screen and home */
+
+       if (GoodStr(T_cl))
+               /* send the clear screen code */
+               terminal_tputs(el, Str(T_cl), Val(T_li));
+       else if (GoodStr(T_ho) && GoodStr(T_cd)) {
+               terminal_tputs(el, Str(T_ho), Val(T_li));       /* home */
+               /* clear to bottom of screen */
+               terminal_tputs(el, Str(T_cd), Val(T_li));
+       } else {
+               terminal__putc(el, '\r');
+               terminal__putc(el, '\n');
+       }
+}
+
+
+/* terminal_beep():
+ *     Beep the way the terminal wants us
+ */
+protected void
+terminal_beep(EditLine *el)
+{
+       if (GoodStr(T_bl))
+               /* what termcap says we should use */
+               terminal_tputs(el, Str(T_bl), 1);
+       else
+               terminal__putc(el, '\007');     /* an ASCII bell; ^G */
+}
+
+
+protected void
+terminal_get(EditLine *el, const char **term)
+{
+       *term = el->el_terminal.t_name;
+}
+
+
+/* terminal_set():
+ *     Read in the terminal capabilities from the requested terminal
+ */
+protected int
+terminal_set(EditLine *el, const char *term)
+{
+       int i;
+       char buf[TC_BUFSIZE];
+       char *area;
+       const struct termcapstr *t;
+       sigset_t oset, nset;
+       int lins, cols;
+
+       (void) sigemptyset(&nset);
+       (void) sigaddset(&nset, SIGWINCH);
+       (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+       area = buf;
+
+
+       if (term == NULL)
+               term = getenv("TERM");
+
+       if (!term || !term[0])
+               term = "dumb";
+
+       if (strcmp(term, "emacs") == 0)
+               el->el_flags |= EDIT_DISABLED;
+
+       (void) memset(el->el_terminal.t_cap, 0, TC_BUFSIZE);
+
+       i = tgetent(el->el_terminal.t_cap, term);
+
+       if (i <= 0) {
+               if (i == -1)
+                       (void) fprintf(el->el_errfile,
+                           "Cannot read termcap database;\n");
+               else if (i == 0)
+                       (void) fprintf(el->el_errfile,
+                           "No entry for terminal type \"%s\";\n", term);
+               (void) fprintf(el->el_errfile,
+                   "using dumb terminal settings.\n");
+               Val(T_co) = 80; /* do a dumb terminal */
+               Val(T_pt) = Val(T_km) = Val(T_li) = 0;
+               Val(T_xt) = Val(T_MT);
+               for (t = tstr; t->name != NULL; t++)
+                       terminal_alloc(el, t, NULL);
+       } else {
+               /* auto/magic margins */
+               Val(T_am) = tgetflag("am");
+               Val(T_xn) = tgetflag("xn");
+               /* Can we tab */
+               Val(T_pt) = tgetflag("pt");
+               Val(T_xt) = tgetflag("xt");
+               /* do we have a meta? */
+               Val(T_km) = tgetflag("km");
+               Val(T_MT) = tgetflag("MT");
+               /* Get the size */
+               Val(T_co) = tgetnum("co");
+               Val(T_li) = tgetnum("li");
+               for (t = tstr; t->name != NULL; t++) {
+                       /* XXX: some systems' tgetstr needs non const */
+                       terminal_alloc(el, t, tgetstr(strchr(t->name, *t->name),
+                           &area));
+               }
+       }
+
+       if (Val(T_co) < 2)
+               Val(T_co) = 80; /* just in case */
+       if (Val(T_li) < 1)
+               Val(T_li) = 24;
+
+       el->el_terminal.t_size.v = Val(T_co);
+       el->el_terminal.t_size.h = Val(T_li);
+
+       terminal_setflags(el);
+
+                               /* get the correct window size */
+       (void) terminal_get_size(el, &lins, &cols);
+       if (terminal_change_size(el, lins, cols) == -1)
+               return -1;
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+       terminal_bind_arrow(el);
+       el->el_terminal.t_name = term;
+       return i <= 0 ? -1 : 0;
+}
+
+
+/* terminal_get_size():
+ *     Return the new window size in lines and cols, and
+ *     true if the size was changed.
+ */
+protected int
+terminal_get_size(EditLine *el, int *lins, int *cols)
+{
+
+       *cols = Val(T_co);
+       *lins = Val(T_li);
+
+#ifdef TIOCGWINSZ
+       {
+               struct winsize ws;
+               if (ioctl(el->el_infd, TIOCGWINSZ, &ws) != -1) {
+                       if (ws.ws_col)
+                               *cols = ws.ws_col;
+                       if (ws.ws_row)
+                               *lins = ws.ws_row;
+               }
+       }
+#endif
+#ifdef TIOCGSIZE
+       {
+               struct ttysize ts;
+               if (ioctl(el->el_infd, TIOCGSIZE, &ts) != -1) {
+                       if (ts.ts_cols)
+                               *cols = ts.ts_cols;
+                       if (ts.ts_lines)
+                               *lins = ts.ts_lines;
+               }
+       }
+#endif
+       return Val(T_co) != *cols || Val(T_li) != *lins;
+}
+
+
+/* terminal_change_size():
+ *     Change the size of the terminal
+ */
+protected int
+terminal_change_size(EditLine *el, int lins, int cols)
+{
+       /*
+         * Just in case
+         */
+       Val(T_co) = (cols < 2) ? 80 : cols;
+       Val(T_li) = (lins < 1) ? 24 : lins;
+
+       /* re-make display buffers */
+       if (terminal_rebuffer_display(el) == -1)
+               return -1;
+       re_clear_display(el);
+       return 0;
+}
+
+
+/* terminal_init_arrow():
+ *     Initialize the arrow key bindings from termcap
+ */
+private void
+terminal_init_arrow(EditLine *el)
+{
+       funckey_t *arrow = el->el_terminal.t_fkey;
+
+       arrow[A_K_DN].name = STR("down");
+       arrow[A_K_DN].key = T_kd;
+       arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY;
+       arrow[A_K_DN].type = XK_CMD;
+
+       arrow[A_K_UP].name = STR("up");
+       arrow[A_K_UP].key = T_ku;
+       arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY;
+       arrow[A_K_UP].type = XK_CMD;
+
+       arrow[A_K_LT].name = STR("left");
+       arrow[A_K_LT].key = T_kl;
+       arrow[A_K_LT].fun.cmd = ED_PREV_CHAR;
+       arrow[A_K_LT].type = XK_CMD;
+
+       arrow[A_K_RT].name = STR("right");
+       arrow[A_K_RT].key = T_kr;
+       arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR;
+       arrow[A_K_RT].type = XK_CMD;
+
+       arrow[A_K_HO].name = STR("home");
+       arrow[A_K_HO].key = T_kh;
+       arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG;
+       arrow[A_K_HO].type = XK_CMD;
+
+       arrow[A_K_EN].name = STR("end");
+       arrow[A_K_EN].key = T_at7;
+       arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END;
+       arrow[A_K_EN].type = XK_CMD;
+
+       arrow[A_K_DE].name = STR("delete");
+       arrow[A_K_DE].key = T_kD;
+       arrow[A_K_DE].fun.cmd = ED_DELETE_NEXT_CHAR;
+       arrow[A_K_DE].type = XK_CMD;
+}
+
+
+/* terminal_reset_arrow():
+ *     Reset arrow key bindings
+ */
+private void
+terminal_reset_arrow(EditLine *el)
+{
+       funckey_t *arrow = el->el_terminal.t_fkey;
+       static const Char strA[] = {033, '[', 'A', '\0'};
+       static const Char strB[] = {033, '[', 'B', '\0'};
+       static const Char strC[] = {033, '[', 'C', '\0'};
+       static const Char strD[] = {033, '[', 'D', '\0'};
+       static const Char strH[] = {033, '[', 'H', '\0'};
+       static const Char strF[] = {033, '[', 'F', '\0'};
+       static const Char stOA[] = {033, 'O', 'A', '\0'};
+       static const Char stOB[] = {033, 'O', 'B', '\0'};
+       static const Char stOC[] = {033, 'O', 'C', '\0'};
+       static const Char stOD[] = {033, 'O', 'D', '\0'};
+       static const Char stOH[] = {033, 'O', 'H', '\0'};
+       static const Char stOF[] = {033, 'O', 'F', '\0'};
+
+       keymacro_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+       keymacro_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+       keymacro_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+       keymacro_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+       keymacro_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+       keymacro_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+       keymacro_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+       keymacro_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+       keymacro_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+       keymacro_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+       keymacro_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+       keymacro_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+
+       if (el->el_map.type != MAP_VI)
+               return;
+       keymacro_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+       keymacro_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+       keymacro_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+       keymacro_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+       keymacro_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+       keymacro_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+       keymacro_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+       keymacro_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+       keymacro_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+       keymacro_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+       keymacro_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type);
+       keymacro_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type);
+}
+
+
+/* terminal_set_arrow():
+ *     Set an arrow key binding
+ */
+protected int
+terminal_set_arrow(EditLine *el, const Char *name, keymacro_value_t *fun,
+    int type)
+{
+       funckey_t *arrow = el->el_terminal.t_fkey;
+       int i;
+
+       for (i = 0; i < A_K_NKEYS; i++)
+               if (Strcmp(name, arrow[i].name) == 0) {
+                       arrow[i].fun = *fun;
+                       arrow[i].type = type;
+                       return 0;
+               }
+       return -1;
+}
+
+
+/* terminal_clear_arrow():
+ *     Clear an arrow key binding
+ */
+protected int
+terminal_clear_arrow(EditLine *el, const Char *name)
+{
+       funckey_t *arrow = el->el_terminal.t_fkey;
+       int i;
+
+       for (i = 0; i < A_K_NKEYS; i++)
+               if (Strcmp(name, arrow[i].name) == 0) {
+                       arrow[i].type = XK_NOD;
+                       return 0;
+               }
+       return -1;
+}
+
+
+/* terminal_print_arrow():
+ *     Print the arrow key bindings
+ */
+protected void
+terminal_print_arrow(EditLine *el, const Char *name)
+{
+       int i;
+       funckey_t *arrow = el->el_terminal.t_fkey;
+
+       for (i = 0; i < A_K_NKEYS; i++)
+               if (*name == '\0' || Strcmp(name, arrow[i].name) == 0)
+                       if (arrow[i].type != XK_NOD)
+                               keymacro_kprint(el, arrow[i].name,
+                                   &arrow[i].fun, arrow[i].type);
+}
+
+
+/* terminal_bind_arrow():
+ *     Bind the arrow keys
+ */
+protected void
+terminal_bind_arrow(EditLine *el)
+{
+       el_action_t *map;
+       const el_action_t *dmap;
+       int i, j;
+       char *p;
+       funckey_t *arrow = el->el_terminal.t_fkey;
+
+       /* Check if the components needed are initialized */
+       if (el->el_terminal.t_buf == NULL || el->el_map.key == NULL)
+               return;
+
+       map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key;
+       dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs;
+
+       terminal_reset_arrow(el);
+
+       for (i = 0; i < A_K_NKEYS; i++) {
+               Char wt_str[VISUAL_WIDTH_MAX];
+               Char *px;
+               size_t n;
+
+               p = el->el_terminal.t_str[arrow[i].key];
+               if (!p || !*p)
+                       continue;
+               for (n = 0; n < VISUAL_WIDTH_MAX && p[n]; ++n)
+                       wt_str[n] = p[n];
+               while (n < VISUAL_WIDTH_MAX)
+                       wt_str[n++] = '\0';
+               px = wt_str;
+               j = (unsigned char) *p;
+               /*
+                * Assign the arrow keys only if:
+                *
+                * 1. They are multi-character arrow keys and the user
+                *    has not re-assigned the leading character, or
+                *    has re-assigned the leading character to be
+                *        ED_SEQUENCE_LEAD_IN
+                * 2. They are single arrow keys pointing to an
+                *    unassigned key.
+                */
+               if (arrow[i].type == XK_NOD)
+                       keymacro_clear(el, map, px);
+               else {
+                       if (p[1] && (dmap[j] == map[j] ||
+                               map[j] == ED_SEQUENCE_LEAD_IN)) {
+                               keymacro_add(el, px, &arrow[i].fun,
+                                   arrow[i].type);
+                               map[j] = ED_SEQUENCE_LEAD_IN;
+                       } else if (map[j] == ED_UNASSIGNED) {
+                               keymacro_clear(el, map, px);
+                               if (arrow[i].type == XK_CMD)
+                                       map[j] = arrow[i].fun.cmd;
+                               else
+                                       keymacro_add(el, px, &arrow[i].fun,
+                                           arrow[i].type);
+                       }
+               }
+       }
+}
+
+/* terminal_putc():
+ *     Add a character
+ */
+private int
+terminal_putc(int c)
+{
+       if (terminal_outfile == NULL)
+               return -1;
+       return fputc(c, terminal_outfile);
+}
+
+private void
+terminal_tputs(EditLine *el, const char *cap, int affcnt)
+{
+#ifdef _REENTRANT
+       pthread_mutex_lock(&terminal_mutex);
+#endif
+       terminal_outfile = el->el_outfile;
+       (void)tputs(cap, affcnt, terminal_putc);
+#ifdef _REENTRANT
+       pthread_mutex_unlock(&terminal_mutex);
+#endif
+}
+
+/* terminal__putc():
+ *     Add a character
+ */
+protected int
+terminal__putc(EditLine *el, Int c)
+{
+       char buf[MB_LEN_MAX +1];
+       ssize_t i;
+       if (c == (Int)MB_FILL_CHAR)
+               return 0;
+       i = ct_encode_char(buf, (size_t)MB_LEN_MAX, c);
+       if (i <= 0)
+               return (int)i;
+       buf[i] = '\0';
+       return fputs(buf, el->el_outfile);
+}
+
+/* terminal__flush():
+ *     Flush output
+ */
+protected void
+terminal__flush(EditLine *el)
+{
+
+       (void) fflush(el->el_outfile);
+}
+
+/* terminal_writec():
+ *     Write the given character out, in a human readable form
+ */
+protected void
+terminal_writec(EditLine *el, Int c)
+{
+       Char visbuf[VISUAL_WIDTH_MAX +1];
+       ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
+       if (vcnt < 0)
+               vcnt = 0;
+       visbuf[vcnt] = '\0';
+       terminal_overwrite(el, visbuf, (size_t)vcnt);
+       terminal__flush(el);
+}
+
+
+/* terminal_telltc():
+ *     Print the current termcap characteristics
+ */
+protected int
+/*ARGSUSED*/
+terminal_telltc(EditLine *el, int argc __attribute__((__unused__)), 
+    const Char **argv __attribute__((__unused__)))
+{
+       const struct termcapstr *t;
+       char **ts;
+
+       (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n");
+       (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n");
+       (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n",
+           Val(T_co), Val(T_li));
+       (void) fprintf(el->el_outfile,
+           "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no");
+       (void) fprintf(el->el_outfile,
+           "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not ");
+       (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n",
+           EL_HAS_AUTO_MARGINS ? "has" : "does not have");
+       if (EL_HAS_AUTO_MARGINS)
+               (void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
+                   EL_HAS_MAGIC_MARGINS ? "has" : "does not have");
+
+       for (t = tstr, ts = el->el_terminal.t_str; t->name != NULL; t++, ts++) {
+               const char *ub;
+               if (*ts && **ts) {
+                       ub = ct_encode_string(ct_visual_string(
+                           ct_decode_string(*ts, &el->el_scratch)),
+                           &el->el_scratch);
+               } else {
+                       ub = "(empty)";
+               }
+               (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n",
+                   t->long_name, t->name, ub);
+       }
+       (void) fputc('\n', el->el_outfile);
+       return 0;
+}
+
+
+/* terminal_settc():
+ *     Change the current terminal characteristics
+ */
+protected int
+/*ARGSUSED*/
+terminal_settc(EditLine *el, int argc __attribute__((__unused__)),
+    const Char **argv)
+{
+       const struct termcapstr *ts;
+       const struct termcapval *tv;
+       char what[8], how[8];
+
+       if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
+               return -1;
+
+       strncpy(what, ct_encode_string(argv[1], &el->el_scratch), sizeof(what));
+       what[sizeof(what) - 1] = '\0';
+       strncpy(how,  ct_encode_string(argv[2], &el->el_scratch), sizeof(how));
+       how[sizeof(how) - 1] = '\0';
+
+       /*
+         * Do the strings first
+         */
+       for (ts = tstr; ts->name != NULL; ts++)
+               if (strcmp(ts->name, what) == 0)
+                       break;
+
+       if (ts->name != NULL) {
+               terminal_alloc(el, ts, how);
+               terminal_setflags(el);
+               return 0;
+       }
+       /*
+         * Do the numeric ones second
+         */
+       for (tv = tval; tv->name != NULL; tv++)
+               if (strcmp(tv->name, what) == 0)
+                       break;
+
+       if (tv->name != NULL)
+               return -1;
+
+       if (tv == &tval[T_pt] || tv == &tval[T_km] ||
+           tv == &tval[T_am] || tv == &tval[T_xn]) {
+               if (strcmp(how, "yes") == 0)
+                       el->el_terminal.t_val[tv - tval] = 1;
+               else if (strcmp(how, "no") == 0)
+                       el->el_terminal.t_val[tv - tval] = 0;
+               else {
+                       (void) fprintf(el->el_errfile,
+                           "" FSTR ": Bad value `%s'.\n", argv[0], how);
+                       return -1;
+               }
+               terminal_setflags(el);
+               if (terminal_change_size(el, Val(T_li), Val(T_co)) == -1)
+                       return -1;
+               return 0;
+       } else {
+               long i;
+               char *ep;
+
+               i = strtol(how, &ep, 10);
+               if (*ep != '\0') {
+                       (void) fprintf(el->el_errfile,
+                           "" FSTR ": Bad value `%s'.\n", argv[0], how);
+                       return -1;
+               }
+               el->el_terminal.t_val[tv - tval] = (int) i;
+               el->el_terminal.t_size.v = Val(T_co);
+               el->el_terminal.t_size.h = Val(T_li);
+               if (tv == &tval[T_co] || tv == &tval[T_li])
+                       if (terminal_change_size(el, Val(T_li), Val(T_co))
+                           == -1)
+                               return -1;
+               return 0;
+       }
+}
+
+
+/* terminal_gettc():
+ *     Get the current terminal characteristics
+ */
+protected int
+/*ARGSUSED*/
+terminal_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv)
+{
+       const struct termcapstr *ts;
+       const struct termcapval *tv;
+       char *what;
+       void *how;
+
+       if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
+               return -1;
+
+       what = argv[1];
+       how = argv[2];
+
+       /*
+         * Do the strings first
+         */
+       for (ts = tstr; ts->name != NULL; ts++)
+               if (strcmp(ts->name, what) == 0)
+                       break;
+
+       if (ts->name != NULL) {
+               *(char **)how = el->el_terminal.t_str[ts - tstr];
+               return 0;
+       }
+       /*
+         * Do the numeric ones second
+         */
+       for (tv = tval; tv->name != NULL; tv++)
+               if (strcmp(tv->name, what) == 0)
+                       break;
+
+       if (tv->name == NULL)
+               return -1;
+
+       if (tv == &tval[T_pt] || tv == &tval[T_km] ||
+           tv == &tval[T_am] || tv == &tval[T_xn]) {
+               static char yes[] = "yes";
+               static char no[] = "no";
+               if (el->el_terminal.t_val[tv - tval])
+                       *(char **)how = yes;
+               else
+                       *(char **)how = no;
+               return 0;
+       } else {
+               *(int *)how = el->el_terminal.t_val[tv - tval];
+               return 0;
+       }
+}
+
+/* terminal_echotc():
+ *     Print the termcap string out with variable substitution
+ */
+protected int
+/*ARGSUSED*/
+terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
+    const Char **argv)
+{
+       char *cap, *scap;
+       Char *ep;
+       int arg_need, arg_cols, arg_rows;
+       int verbose = 0, silent = 0;
+       char *area;
+       static const char fmts[] = "%s\n", fmtd[] = "%d\n";
+       const struct termcapstr *t;
+       char buf[TC_BUFSIZE];
+       long i;
+
+       area = buf;
+
+       if (argv == NULL || argv[1] == NULL)
+               return -1;
+       argv++;
+
+       if (argv[0][0] == '-') {
+               switch (argv[0][1]) {
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 's':
+                       silent = 1;
+                       break;
+               default:
+                       /* stderror(ERR_NAME | ERR_TCUSAGE); */
+                       break;
+               }
+               argv++;
+       }
+       if (!*argv || *argv[0] == '\0')
+               return 0;
+       if (Strcmp(*argv, STR("tabs")) == 0) {
+               (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no");
+               return 0;
+       } else if (Strcmp(*argv, STR("meta")) == 0) {
+               (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no");
+               return 0;
+       } else if (Strcmp(*argv, STR("xn")) == 0) {
+               (void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ?
+                   "yes" : "no");
+               return 0;
+       } else if (Strcmp(*argv, STR("am")) == 0) {
+               (void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ?
+                   "yes" : "no");
+               return 0;
+       } else if (Strcmp(*argv, STR("baud")) == 0) {
+               (void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed);
+               return 0;
+       } else if (Strcmp(*argv, STR("rows")) == 0 ||
+                   Strcmp(*argv, STR("lines")) == 0) {
+               (void) fprintf(el->el_outfile, fmtd, Val(T_li));
+               return 0;
+       } else if (Strcmp(*argv, STR("cols")) == 0) {
+               (void) fprintf(el->el_outfile, fmtd, Val(T_co));
+               return 0;
+       }
+       /*
+         * Try to use our local definition first
+         */
+       scap = NULL;
+       for (t = tstr; t->name != NULL; t++)
+               if (strcmp(t->name,
+                   ct_encode_string(*argv, &el->el_scratch)) == 0) {
+                       scap = el->el_terminal.t_str[t - tstr];
+                       break;
+               }
+       if (t->name == NULL) {
+               /* XXX: some systems' tgetstr needs non const */
+                scap = tgetstr(ct_encode_string(*argv, &el->el_scratch), &area);
+       }
+       if (!scap || scap[0] == '\0') {
+               if (!silent)
+                       (void) fprintf(el->el_errfile,
+                           "echotc: Termcap parameter `" FSTR "' not found.\n",
+                           *argv);
+               return -1;
+       }
+       /*
+         * Count home many values we need for this capability.
+         */
+       for (cap = scap, arg_need = 0; *cap; cap++)
+               if (*cap == '%')
+                       switch (*++cap) {
+                       case 'd':
+                       case '2':
+                       case '3':
+                       case '.':
+                       case '+':
+                               arg_need++;
+                               break;
+                       case '%':
+                       case '>':
+                       case 'i':
+                       case 'r':
+                       case 'n':
+                       case 'B':
+                       case 'D':
+                               break;
+                       default:
+                               /*
+                                * hpux has lot's of them...
+                                */
+                               if (verbose)
+                                       (void) fprintf(el->el_errfile,
+                               "echotc: Warning: unknown termcap %% `%c'.\n",
+                                           *cap);
+                               /* This is bad, but I won't complain */
+                               break;
+                       }
+
+       switch (arg_need) {
+       case 0:
+               argv++;
+               if (*argv && *argv[0]) {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Warning: Extra argument `" FSTR "'.\n",
+                                   *argv);
+                       return -1;
+               }
+               terminal_tputs(el, scap, 1);
+               break;
+       case 1:
+               argv++;
+               if (!*argv || *argv[0] == '\0') {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Warning: Missing argument.\n");
+                       return -1;
+               }
+               arg_cols = 0;
+               i = Strtol(*argv, &ep, 10);
+               if (*ep != '\0' || i < 0) {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Bad value `" FSTR "' for rows.\n",
+                                   *argv);
+                       return -1;
+               }
+               arg_rows = (int) i;
+               argv++;
+               if (*argv && *argv[0]) {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Warning: Extra argument `" FSTR
+                                   "'.\n", *argv);
+                       return -1;
+               }
+               terminal_tputs(el, tgoto(scap, arg_cols, arg_rows), 1);
+               break;
+       default:
+               /* This is wrong, but I will ignore it... */
+               if (verbose)
+                       (void) fprintf(el->el_errfile,
+                        "echotc: Warning: Too many required arguments (%d).\n",
+                           arg_need);
+               /* FALLTHROUGH */
+       case 2:
+               argv++;
+               if (!*argv || *argv[0] == '\0') {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Warning: Missing argument.\n");
+                       return -1;
+               }
+               i = Strtol(*argv, &ep, 10);
+               if (*ep != '\0' || i < 0) {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Bad value `" FSTR "' for cols.\n",
+                                   *argv);
+                       return -1;
+               }
+               arg_cols = (int) i;
+               argv++;
+               if (!*argv || *argv[0] == '\0') {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Warning: Missing argument.\n");
+                       return -1;
+               }
+               i = Strtol(*argv, &ep, 10);
+               if (*ep != '\0' || i < 0) {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Bad value `" FSTR "' for rows.\n",
+                                   *argv);
+                       return -1;
+               }
+               arg_rows = (int) i;
+               if (*ep != '\0') {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Bad value `" FSTR "'.\n", *argv);
+                       return -1;
+               }
+               argv++;
+               if (*argv && *argv[0]) {
+                       if (!silent)
+                               (void) fprintf(el->el_errfile,
+                                   "echotc: Warning: Extra argument `" FSTR
+                                   "'.\n", *argv);
+                       return -1;
+               }
+               terminal_tputs(el, tgoto(scap, arg_cols, arg_rows), arg_rows);
+               break;
+       }
+       return 0;
+}
diff --git a/lib/libedit/terminal.h b/lib/libedit/terminal.h
new file mode 100644 (file)
index 0000000..c507363
--- /dev/null
@@ -0,0 +1,126 @@
+/*     $NetBSD: terminal.h,v 1.4 2012/03/24 20:09:30 christos Exp $    */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)term.h      8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.term.h: Termcap header
+ */
+#ifndef _h_el_terminal
+#define        _h_el_terminal
+
+#include "histedit.h"
+
+typedef struct {               /* Symbolic function key bindings       */
+       const Char      *name;  /* name of the key                      */
+       int              key;   /* Index in termcap table               */
+       keymacro_value_t         fun;   /* Function bound to it                 */
+       int              type;  /* Type of function                     */
+} funckey_t;
+
+typedef struct {
+       const char *t_name;             /* the terminal name    */
+       coord_t   t_size;               /* # lines and cols     */
+       int       t_flags;
+#define        TERM_CAN_INSERT         0x001   /* Has insert cap       */
+#define        TERM_CAN_DELETE         0x002   /* Has delete cap       */
+#define        TERM_CAN_CEOL           0x004   /* Has CEOL cap         */
+#define        TERM_CAN_TAB            0x008   /* Can use tabs         */
+#define        TERM_CAN_ME             0x010   /* Can turn all attrs.  */
+#define        TERM_CAN_UP             0x020   /* Can move up          */
+#define        TERM_HAS_META           0x040   /* Has a meta key       */
+#define        TERM_HAS_AUTO_MARGINS   0x080   /* Has auto margins     */
+#define        TERM_HAS_MAGIC_MARGINS  0x100   /* Has magic margins    */
+       char     *t_buf;                /* Termcap buffer       */
+       size_t    t_loc;                /* location used        */
+       char    **t_str;                /* termcap strings      */
+       int      *t_val;                /* termcap values       */
+       char     *t_cap;                /* Termcap buffer       */
+       funckey_t        *t_fkey;               /* Array of keys        */
+} el_terminal_t;
+
+/*
+ * fKey indexes
+ */
+#define        A_K_DN          0
+#define        A_K_UP          1
+#define        A_K_LT          2
+#define        A_K_RT          3
+#define        A_K_HO          4
+#define        A_K_EN          5
+#define        A_K_DE          6
+#define        A_K_NKEYS       7
+
+protected void terminal_move_to_line(EditLine *, int);
+protected void terminal_move_to_char(EditLine *, int);
+protected void terminal_clear_EOL(EditLine *, int);
+protected void terminal_overwrite(EditLine *, const Char *, size_t);
+protected void terminal_insertwrite(EditLine *, Char *, int);
+protected void terminal_deletechars(EditLine *, int);
+protected void terminal_clear_screen(EditLine *);
+protected void terminal_beep(EditLine *);
+protected int  terminal_change_size(EditLine *, int, int);
+protected int  terminal_get_size(EditLine *, int *, int *);
+protected int  terminal_init(EditLine *);
+protected void terminal_bind_arrow(EditLine *);
+protected void terminal_print_arrow(EditLine *, const Char *);
+protected int  terminal_clear_arrow(EditLine *, const Char *);
+protected int  terminal_set_arrow(EditLine *, const Char *, keymacro_value_t *, int);
+protected void terminal_end(EditLine *);
+protected void terminal_get(EditLine *, const char **);
+protected int  terminal_set(EditLine *, const char *);
+protected int  terminal_settc(EditLine *, int, const Char **);
+protected int  terminal_gettc(EditLine *, int, char **);
+protected int  terminal_telltc(EditLine *, int, const Char **);
+protected int  terminal_echotc(EditLine *, int, const Char **);
+protected void terminal_writec(EditLine *, Int);
+protected int  terminal__putc(EditLine *, Int);
+protected void terminal__flush(EditLine *);
+
+/*
+ * Easy access macros
+ */
+#define        EL_FLAGS        (el)->el_terminal.t_flags
+
+#define        EL_CAN_INSERT           (EL_FLAGS & TERM_CAN_INSERT)
+#define        EL_CAN_DELETE           (EL_FLAGS & TERM_CAN_DELETE)
+#define        EL_CAN_CEOL             (EL_FLAGS & TERM_CAN_CEOL)
+#define        EL_CAN_TAB              (EL_FLAGS & TERM_CAN_TAB)
+#define        EL_CAN_ME               (EL_FLAGS & TERM_CAN_ME)
+#define EL_CAN_UP              (EL_FLAGS & TERM_CAN_UP)
+#define        EL_HAS_META             (EL_FLAGS & TERM_HAS_META)
+#define        EL_HAS_AUTO_MARGINS     (EL_FLAGS & TERM_HAS_AUTO_MARGINS)
+#define        EL_HAS_MAGIC_MARGINS    (EL_FLAGS & TERM_HAS_MAGIC_MARGINS)
+
+#endif /* _h_el_terminal */
diff --git a/lib/libedit/testit.c b/lib/libedit/testit.c
deleted file mode 100644 (file)
index 525436c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-**  A "micro-shell" to test editline library.
-**  If given any arguments, commands aren't executed.
-*/
-#include <stdio.h>
-#if    defined(HAVE_STDLIB)
-#include <stdlib.h>
-#endif /* defined(HAVE_STDLIB) */
-
-extern char    *readline();
-extern void    add_history();
-
-#if    !defined(HAVE_STDLIB)
-extern int     chdir();
-extern int     free();
-extern int     strncmp();
-extern int     system();
-extern void    exit();
-extern char    *getenv();
-#endif /* !defined(HAVE_STDLIB) */
-
-
-#if    defined(NEED_PERROR)
-void
-perror(s)
-    char       *s;
-{
-    extern int errno;
-
-    (voidf)printf(stderr, "%s: error %d\n", s, errno);
-}
-#endif /* defined(NEED_PERROR) */
-
-
-/* ARGSUSED1 */
-int
-main(ac, av)
-    int                ac;
-    char       *av[];
-{
-    char       *prompt;
-    char       *p;
-    int                doit;
-
-    doit = ac == 1;
-    if ((prompt = getenv("TESTPROMPT")) == NULL)
-       prompt = "testit>  ";
-
-    while ((p = readline(prompt)) != NULL) {
-       (void)printf("\t\t\t|%s|\n", p);
-       if (doit)
-           if (strncmp(p, "cd ", 3) == 0) {
-               if (chdir(&p[3]) < 0)
-                   perror(&p[3]);
-           }
-           else if (system(p) != 0)
-               perror(p);
-       add_history(p);
-       free(p);
-    }
-    exit(0);
-    /* NOTREACHED */
-}
-
-/*
- * $PchId: testit.c,v 1.3 1996/02/22 21:18:51 philip Exp $
- */
diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c
new file mode 100644 (file)
index 0000000..7fd842d
--- /dev/null
@@ -0,0 +1,450 @@
+/*     $NetBSD: tokenizer.c,v 1.21 2011/08/16 16:25:15 christos Exp $  */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)tokenizer.c        8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: tokenizer.c,v 1.21 2011/08/16 16:25:15 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/* We build this file twice, once as NARROW, once as WIDE. */
+/*
+ * tokenize.c: Bourne shell like tokenizer
+ */
+#include <string.h>
+#include <stdlib.h>
+#include "histedit.h"
+#include "chartype.h"
+
+typedef enum {
+       Q_none, Q_single, Q_double, Q_one, Q_doubleone
+} quote_t;
+
+#define        TOK_KEEP        1
+#define        TOK_EAT         2
+
+#define        WINCR           20
+#define        AINCR           10
+
+#define        IFS             STR("\t \n")
+
+#define        tok_malloc(a)           malloc(a)
+#define        tok_free(a)             free(a)
+#define        tok_realloc(a, b)       realloc(a, b)
+#define        tok_strdup(a)           Strdup(a)
+
+
+struct TYPE(tokenizer) {
+       Char    *ifs;           /* In field separator                    */
+       size_t   argc, amax;    /* Current and maximum number of args    */
+       Char   **argv;          /* Argument list                         */
+       Char    *wptr, *wmax;   /* Space and limit on the word buffer    */
+       Char    *wstart;        /* Beginning of next word                */
+       Char    *wspace;        /* Space of word buffer                  */
+       quote_t  quote;         /* Quoting state                         */
+       int      flags;         /* flags;                                */
+};
+
+
+private void FUN(tok,finish)(TYPE(Tokenizer) *);
+
+
+/* FUN(tok,finish)():
+ *     Finish a word in the tokenizer.
+ */
+private void
+FUN(tok,finish)(TYPE(Tokenizer) *tok)
+{
+
+       *tok->wptr = '\0';
+       if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) {
+               tok->argv[tok->argc++] = tok->wstart;
+               tok->argv[tok->argc] = NULL;
+               tok->wstart = ++tok->wptr;
+       }
+       tok->flags &= ~TOK_KEEP;
+}
+
+
+/* FUN(tok,init)():
+ *     Initialize the tokenizer
+ */
+public TYPE(Tokenizer) *
+FUN(tok,init)(const Char *ifs)
+{
+       TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok));
+
+       if (tok == NULL)
+               return NULL;
+       tok->ifs = tok_strdup(ifs ? ifs : IFS);
+       if (tok->ifs == NULL) {
+               tok_free(tok);
+               return NULL;
+       }
+       tok->argc = 0;
+       tok->amax = AINCR;
+       tok->argv = tok_malloc(sizeof(*tok->argv) * tok->amax);
+       if (tok->argv == NULL) {
+               tok_free(tok->ifs);
+               tok_free(tok);
+               return NULL;
+       }
+       tok->argv[0] = NULL;
+       tok->wspace = tok_malloc(WINCR * sizeof(*tok->wspace));
+       if (tok->wspace == NULL) {
+               tok_free(tok->argv);
+               tok_free(tok->ifs);
+               tok_free(tok);
+               return NULL;
+       }
+       tok->wmax = tok->wspace + WINCR;
+       tok->wstart = tok->wspace;
+       tok->wptr = tok->wspace;
+       tok->flags = 0;
+       tok->quote = Q_none;
+
+       return tok;
+}
+
+
+/* FUN(tok,reset)():
+ *     Reset the tokenizer
+ */
+public void
+FUN(tok,reset)(TYPE(Tokenizer) *tok)
+{
+
+       tok->argc = 0;
+       tok->wstart = tok->wspace;
+       tok->wptr = tok->wspace;
+       tok->flags = 0;
+       tok->quote = Q_none;
+}
+
+
+/* FUN(tok,end)():
+ *     Clean up
+ */
+public void
+FUN(tok,end)(TYPE(Tokenizer) *tok)
+{
+
+       tok_free(tok->ifs);
+       tok_free(tok->wspace);
+       tok_free(tok->argv);
+       tok_free(tok);
+}
+
+
+
+/* FUN(tok,line)():
+ *     Bourne shell (sh(1)) like tokenizing
+ *     Arguments:
+ *             tok     current tokenizer state (setup with FUN(tok,init)())
+ *             line    line to parse
+ *     Returns:
+ *             -1      Internal error
+ *              3      Quoted return
+ *              2      Unmatched double quote
+ *              1      Unmatched single quote
+ *              0      Ok
+ *     Modifies (if return value is 0):
+ *             argc    number of arguments
+ *             argv    argument array
+ *             cursorc if !NULL, argv element containing cursor
+ *             cursorv if !NULL, offset in argv[cursorc] of cursor
+ */
+public int
+FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line,
+    int *argc, const Char ***argv, int *cursorc, int *cursoro)
+{
+       const Char *ptr;
+       int cc, co;
+
+       cc = co = -1;
+       ptr = line->buffer;
+       for (ptr = line->buffer; ;ptr++) {
+               if (ptr >= line->lastchar)
+                       ptr = STR("");
+               if (ptr == line->cursor) {
+                       cc = (int)tok->argc;
+                       co = (int)(tok->wptr - tok->wstart);
+               }
+               switch (*ptr) {
+               case '\'':
+                       tok->flags |= TOK_KEEP;
+                       tok->flags &= ~TOK_EAT;
+                       switch (tok->quote) {
+                       case Q_none:
+                               tok->quote = Q_single;  /* Enter single quote
+                                                        * mode */
+                               break;
+
+                       case Q_single:  /* Exit single quote mode */
+                               tok->quote = Q_none;
+                               break;
+
+                       case Q_one:     /* Quote this ' */
+                               tok->quote = Q_none;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_double:  /* Stay in double quote mode */
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_doubleone:       /* Quote this ' */
+                               tok->quote = Q_double;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       default:
+                               return -1;
+                       }
+                       break;
+
+               case '"':
+                       tok->flags &= ~TOK_EAT;
+                       tok->flags |= TOK_KEEP;
+                       switch (tok->quote) {
+                       case Q_none:    /* Enter double quote mode */
+                               tok->quote = Q_double;
+                               break;
+
+                       case Q_double:  /* Exit double quote mode */
+                               tok->quote = Q_none;
+                               break;
+
+                       case Q_one:     /* Quote this " */
+                               tok->quote = Q_none;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_single:  /* Stay in single quote mode */
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_doubleone:       /* Quote this " */
+                               tok->quote = Q_double;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       default:
+                               return -1;
+                       }
+                       break;
+
+               case '\\':
+                       tok->flags |= TOK_KEEP;
+                       tok->flags &= ~TOK_EAT;
+                       switch (tok->quote) {
+                       case Q_none:    /* Quote next character */
+                               tok->quote = Q_one;
+                               break;
+
+                       case Q_double:  /* Quote next character */
+                               tok->quote = Q_doubleone;
+                               break;
+
+                       case Q_one:     /* Quote this, restore state */
+                               *tok->wptr++ = *ptr;
+                               tok->quote = Q_none;
+                               break;
+
+                       case Q_single:  /* Stay in single quote mode */
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_doubleone:       /* Quote this \ */
+                               tok->quote = Q_double;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       default:
+                               return -1;
+                       }
+                       break;
+
+               case '\n':
+                       tok->flags &= ~TOK_EAT;
+                       switch (tok->quote) {
+                       case Q_none:
+                               goto tok_line_outok;
+
+                       case Q_single:
+                       case Q_double:
+                               *tok->wptr++ = *ptr;    /* Add the return */
+                               break;
+
+                       case Q_doubleone:   /* Back to double, eat the '\n' */
+                               tok->flags |= TOK_EAT;
+                               tok->quote = Q_double;
+                               break;
+
+                       case Q_one:     /* No quote, more eat the '\n' */
+                               tok->flags |= TOK_EAT;
+                               tok->quote = Q_none;
+                               break;
+
+                       default:
+                               return 0;
+                       }
+                       break;
+
+               case '\0':
+                       switch (tok->quote) {
+                       case Q_none:
+                               /* Finish word and return */
+                               if (tok->flags & TOK_EAT) {
+                                       tok->flags &= ~TOK_EAT;
+                                       return 3;
+                               }
+                               goto tok_line_outok;
+
+                       case Q_single:
+                               return 1;
+
+                       case Q_double:
+                               return 2;
+
+                       case Q_doubleone:
+                               tok->quote = Q_double;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_one:
+                               tok->quote = Q_none;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       default:
+                               return -1;
+                       }
+                       break;
+
+               default:
+                       tok->flags &= ~TOK_EAT;
+                       switch (tok->quote) {
+                       case Q_none:
+                               if (Strchr(tok->ifs, *ptr) != NULL)
+                                       FUN(tok,finish)(tok);
+                               else
+                                       *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_single:
+                       case Q_double:
+                               *tok->wptr++ = *ptr;
+                               break;
+
+
+                       case Q_doubleone:
+                               *tok->wptr++ = '\\';
+                               tok->quote = Q_double;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       case Q_one:
+                               tok->quote = Q_none;
+                               *tok->wptr++ = *ptr;
+                               break;
+
+                       default:
+                               return -1;
+
+                       }
+                       break;
+               }
+
+               if (tok->wptr >= tok->wmax - 4) {
+                       size_t size = (size_t)(tok->wmax - tok->wspace + WINCR);
+                       Char *s = tok_realloc(tok->wspace,
+                           size * sizeof(*s));
+                       if (s == NULL)
+                               return -1;
+
+                       if (s != tok->wspace) {
+                               size_t i;
+                               for (i = 0; i < tok->argc; i++) {
+                                   tok->argv[i] =
+                                       (tok->argv[i] - tok->wspace) + s;
+                               }
+                               tok->wptr = (tok->wptr - tok->wspace) + s;
+                               tok->wstart = (tok->wstart - tok->wspace) + s;
+                               tok->wspace = s;
+                       }
+                       tok->wmax = s + size;
+               }
+               if (tok->argc >= tok->amax - 4) {
+                       Char **p;
+                       tok->amax += AINCR;
+                       p = tok_realloc(tok->argv, tok->amax * sizeof(*p));
+                       if (p == NULL)
+                               return -1;
+                       tok->argv = p;
+               }
+       }
+ tok_line_outok:
+       if (cc == -1 && co == -1) {
+               cc = (int)tok->argc;
+               co = (int)(tok->wptr - tok->wstart);
+       }
+       if (cursorc != NULL)
+               *cursorc = cc;
+       if (cursoro != NULL)
+               *cursoro = co;
+       FUN(tok,finish)(tok);
+       *argv = (const Char **)tok->argv;
+       *argc = (int)tok->argc;
+       return 0;
+}
+
+/* FUN(tok,str)():
+ *     Simpler version of tok_line, taking a NUL terminated line
+ *     and splitting into words, ignoring cursor state.
+ */
+public int
+FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc,
+    const Char ***argv)
+{
+       TYPE(LineInfo) li;
+
+       memset(&li, 0, sizeof(li));
+       li.buffer = line;
+       li.cursor = li.lastchar = Strchr(line, '\0');
+       return FUN(tok,line(tok, &li, argc, argv, NULL, NULL));
+}
diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c
new file mode 100644 (file)
index 0000000..57c8ee8
--- /dev/null
@@ -0,0 +1,1359 @@
+/*     $NetBSD: tty.c,v 1.42 2012/05/15 15:59:01 christos Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)tty.c      8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: tty.c,v 1.42 2012/05/15 15:59:01 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * tty.c: tty interface stuff
+ */
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>    /* for isatty */
+#include <strings.h>   /* for ffs */
+#include "el.h"
+#include "tty.h"
+
+typedef struct ttymodes_t {
+       const char *m_name;
+       unsigned int m_value;
+       int m_type;
+}          ttymodes_t;
+
+typedef struct ttymap_t {
+       Int nch, och;           /* Internal and termio rep of chars */
+       el_action_t bind[3];    /* emacs, vi, and vi-cmd */
+} ttymap_t;
+
+
+private const ttyperm_t ttyperm = {
+       {
+               {"iflag:", ICRNL, (INLCR | IGNCR)},
+               {"oflag:", (OPOST | ONLCR), ONLRET},
+               {"cflag:", 0, 0},
+               {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
+               (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
+               {"chars:", 0, 0},
+       },
+       {
+               {"iflag:", (INLCR | ICRNL), IGNCR},
+               {"oflag:", (OPOST | ONLCR), ONLRET},
+               {"cflag:", 0, 0},
+               {"lflag:", ISIG,
+               (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
+               {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
+                           C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
+                   C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
+       },
+       {
+               {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
+               {"oflag:", 0, 0},
+               {"cflag:", 0, 0},
+               {"lflag:", 0, ISIG | IEXTEN},
+               {"chars:", 0, 0},
+       }
+};
+
+private const ttychar_t ttychar = {
+       {
+               CINTR, CQUIT, CERASE, CKILL,
+               CEOF, CEOL, CEOL2, CSWTCH,
+               CDSWTCH, CERASE2, CSTART, CSTOP,
+               CWERASE, CSUSP, CDSUSP, CREPRINT,
+               CDISCARD, CLNEXT, CSTATUS, CPAGE,
+               CPGOFF, CKILL2, CBRK, CMIN,
+               CTIME
+       },
+       {
+               CINTR, CQUIT, CERASE, CKILL,
+               _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+               _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
+               _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
+               CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+               _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
+               0
+       },
+       {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0
+       }
+};
+
+private const ttymap_t tty_map[] = {
+#ifdef VERASE
+       {C_ERASE, VERASE,
+       {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+#endif /* VERASE */
+#ifdef VERASE2
+       {C_ERASE2, VERASE2,
+       {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
+#endif /* VERASE2 */
+#ifdef VKILL
+       {C_KILL, VKILL,
+       {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
+#endif /* VKILL */
+#ifdef VKILL2
+       {C_KILL2, VKILL2,
+       {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
+#endif /* VKILL2 */
+#ifdef VEOF
+       {C_EOF, VEOF,
+       {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
+#endif /* VEOF */
+#ifdef VWERASE
+       {C_WERASE, VWERASE,
+       {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
+#endif /* VWERASE */
+#ifdef VREPRINT
+       {C_REPRINT, VREPRINT,
+       {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
+#endif /* VREPRINT */
+#ifdef VLNEXT
+       {C_LNEXT, VLNEXT,
+       {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
+#endif /* VLNEXT */
+       {(Int)-1, (Int)-1,
+       {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
+};
+
+private const ttymodes_t ttymodes[] = {
+#ifdef IGNBRK
+       {"ignbrk", IGNBRK, MD_INP},
+#endif /* IGNBRK */
+#ifdef BRKINT
+       {"brkint", BRKINT, MD_INP},
+#endif /* BRKINT */
+#ifdef IGNPAR
+       {"ignpar", IGNPAR, MD_INP},
+#endif /* IGNPAR */
+#ifdef PARMRK
+       {"parmrk", PARMRK, MD_INP},
+#endif /* PARMRK */
+#ifdef INPCK
+       {"inpck", INPCK, MD_INP},
+#endif /* INPCK */
+#ifdef ISTRIP
+       {"istrip", ISTRIP, MD_INP},
+#endif /* ISTRIP */
+#ifdef INLCR
+       {"inlcr", INLCR, MD_INP},
+#endif /* INLCR */
+#ifdef IGNCR
+       {"igncr", IGNCR, MD_INP},
+#endif /* IGNCR */
+#ifdef ICRNL
+       {"icrnl", ICRNL, MD_INP},
+#endif /* ICRNL */
+#ifdef IUCLC
+       {"iuclc", IUCLC, MD_INP},
+#endif /* IUCLC */
+#ifdef IXON
+       {"ixon", IXON, MD_INP},
+#endif /* IXON */
+#ifdef IXANY
+       {"ixany", IXANY, MD_INP},
+#endif /* IXANY */
+#ifdef IXOFF
+       {"ixoff", IXOFF, MD_INP},
+#endif /* IXOFF */
+#ifdef  IMAXBEL
+       {"imaxbel", IMAXBEL, MD_INP},
+#endif /* IMAXBEL */
+
+#ifdef OPOST
+       {"opost", OPOST, MD_OUT},
+#endif /* OPOST */
+#ifdef OLCUC
+       {"olcuc", OLCUC, MD_OUT},
+#endif /* OLCUC */
+#ifdef ONLCR
+       {"onlcr", ONLCR, MD_OUT},
+#endif /* ONLCR */
+#ifdef OCRNL
+       {"ocrnl", OCRNL, MD_OUT},
+#endif /* OCRNL */
+#ifdef ONOCR
+       {"onocr", ONOCR, MD_OUT},
+#endif /* ONOCR */
+#ifdef ONOEOT
+       {"onoeot", ONOEOT, MD_OUT},
+#endif /* ONOEOT */
+#ifdef ONLRET
+       {"onlret", ONLRET, MD_OUT},
+#endif /* ONLRET */
+#ifdef OFILL
+       {"ofill", OFILL, MD_OUT},
+#endif /* OFILL */
+#ifdef OFDEL
+       {"ofdel", OFDEL, MD_OUT},
+#endif /* OFDEL */
+#ifdef NLDLY
+       {"nldly", NLDLY, MD_OUT},
+#endif /* NLDLY */
+#ifdef CRDLY
+       {"crdly", CRDLY, MD_OUT},
+#endif /* CRDLY */
+#ifdef TABDLY
+       {"tabdly", TABDLY, MD_OUT},
+#endif /* TABDLY */
+#ifdef XTABS
+       {"xtabs", XTABS, MD_OUT},
+#endif /* XTABS */
+#ifdef BSDLY
+       {"bsdly", BSDLY, MD_OUT},
+#endif /* BSDLY */
+#ifdef VTDLY
+       {"vtdly", VTDLY, MD_OUT},
+#endif /* VTDLY */
+#ifdef FFDLY
+       {"ffdly", FFDLY, MD_OUT},
+#endif /* FFDLY */
+#ifdef PAGEOUT
+       {"pageout", PAGEOUT, MD_OUT},
+#endif /* PAGEOUT */
+#ifdef WRAP
+       {"wrap", WRAP, MD_OUT},
+#endif /* WRAP */
+
+#ifdef CIGNORE
+       {"cignore", CIGNORE, MD_CTL},
+#endif /* CBAUD */
+#ifdef CBAUD
+       {"cbaud", CBAUD, MD_CTL},
+#endif /* CBAUD */
+#ifdef CSTOPB
+       {"cstopb", CSTOPB, MD_CTL},
+#endif /* CSTOPB */
+#ifdef CREAD
+       {"cread", CREAD, MD_CTL},
+#endif /* CREAD */
+#ifdef PARENB
+       {"parenb", PARENB, MD_CTL},
+#endif /* PARENB */
+#ifdef PARODD
+       {"parodd", PARODD, MD_CTL},
+#endif /* PARODD */
+#ifdef HUPCL
+       {"hupcl", HUPCL, MD_CTL},
+#endif /* HUPCL */
+#ifdef CLOCAL
+       {"clocal", CLOCAL, MD_CTL},
+#endif /* CLOCAL */
+#ifdef LOBLK
+       {"loblk", LOBLK, MD_CTL},
+#endif /* LOBLK */
+#ifdef CIBAUD
+       {"cibaud", CIBAUD, MD_CTL},
+#endif /* CIBAUD */
+#ifdef CRTSCTS
+#ifdef CCTS_OFLOW
+       {"ccts_oflow", CCTS_OFLOW, MD_CTL},
+#else
+       {"crtscts", CRTSCTS, MD_CTL},
+#endif /* CCTS_OFLOW */
+#endif /* CRTSCTS */
+#ifdef CRTS_IFLOW
+       {"crts_iflow", CRTS_IFLOW, MD_CTL},
+#endif /* CRTS_IFLOW */
+#ifdef CDTRCTS
+       {"cdtrcts", CDTRCTS, MD_CTL},
+#endif /* CDTRCTS */
+#ifdef MDMBUF
+       {"mdmbuf", MDMBUF, MD_CTL},
+#endif /* MDMBUF */
+#ifdef RCV1EN
+       {"rcv1en", RCV1EN, MD_CTL},
+#endif /* RCV1EN */
+#ifdef XMT1EN
+       {"xmt1en", XMT1EN, MD_CTL},
+#endif /* XMT1EN */
+
+#ifdef ISIG
+       {"isig", ISIG, MD_LIN},
+#endif /* ISIG */
+#ifdef ICANON
+       {"icanon", ICANON, MD_LIN},
+#endif /* ICANON */
+#ifdef XCASE
+       {"xcase", XCASE, MD_LIN},
+#endif /* XCASE */
+#ifdef ECHO
+       {"echo", ECHO, MD_LIN},
+#endif /* ECHO */
+#ifdef ECHOE
+       {"echoe", ECHOE, MD_LIN},
+#endif /* ECHOE */
+#ifdef ECHOK
+       {"echok", ECHOK, MD_LIN},
+#endif /* ECHOK */
+#ifdef ECHONL
+       {"echonl", ECHONL, MD_LIN},
+#endif /* ECHONL */
+#ifdef NOFLSH
+       {"noflsh", NOFLSH, MD_LIN},
+#endif /* NOFLSH */
+#ifdef TOSTOP
+       {"tostop", TOSTOP, MD_LIN},
+#endif /* TOSTOP */
+#ifdef ECHOCTL
+       {"echoctl", ECHOCTL, MD_LIN},
+#endif /* ECHOCTL */
+#ifdef ECHOPRT
+       {"echoprt", ECHOPRT, MD_LIN},
+#endif /* ECHOPRT */
+#ifdef ECHOKE
+       {"echoke", ECHOKE, MD_LIN},
+#endif /* ECHOKE */
+#ifdef DEFECHO
+       {"defecho", DEFECHO, MD_LIN},
+#endif /* DEFECHO */
+#ifdef FLUSHO
+       {"flusho", FLUSHO, MD_LIN},
+#endif /* FLUSHO */
+#ifdef PENDIN
+       {"pendin", PENDIN, MD_LIN},
+#endif /* PENDIN */
+#ifdef IEXTEN
+       {"iexten", IEXTEN, MD_LIN},
+#endif /* IEXTEN */
+#ifdef NOKERNINFO
+       {"nokerninfo", NOKERNINFO, MD_LIN},
+#endif /* NOKERNINFO */
+#ifdef ALTWERASE
+       {"altwerase", ALTWERASE, MD_LIN},
+#endif /* ALTWERASE */
+#ifdef EXTPROC
+       {"extproc", EXTPROC, MD_LIN},
+#endif /* EXTPROC */
+
+#if defined(VINTR)
+       {"intr", C_SH(C_INTR), MD_CHAR},
+#endif /* VINTR */
+#if defined(VQUIT)
+       {"quit", C_SH(C_QUIT), MD_CHAR},
+#endif /* VQUIT */
+#if defined(VERASE)
+       {"erase", C_SH(C_ERASE), MD_CHAR},
+#endif /* VERASE */
+#if defined(VKILL)
+       {"kill", C_SH(C_KILL), MD_CHAR},
+#endif /* VKILL */
+#if defined(VEOF)
+       {"eof", C_SH(C_EOF), MD_CHAR},
+#endif /* VEOF */
+#if defined(VEOL)
+       {"eol", C_SH(C_EOL), MD_CHAR},
+#endif /* VEOL */
+#if defined(VEOL2)
+       {"eol2", C_SH(C_EOL2), MD_CHAR},
+#endif /* VEOL2 */
+#if defined(VSWTCH)
+       {"swtch", C_SH(C_SWTCH), MD_CHAR},
+#endif /* VSWTCH */
+#if defined(VDSWTCH)
+       {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
+#endif /* VDSWTCH */
+#if defined(VERASE2)
+       {"erase2", C_SH(C_ERASE2), MD_CHAR},
+#endif /* VERASE2 */
+#if defined(VSTART)
+       {"start", C_SH(C_START), MD_CHAR},
+#endif /* VSTART */
+#if defined(VSTOP)
+       {"stop", C_SH(C_STOP), MD_CHAR},
+#endif /* VSTOP */
+#if defined(VWERASE)
+       {"werase", C_SH(C_WERASE), MD_CHAR},
+#endif /* VWERASE */
+#if defined(VSUSP)
+       {"susp", C_SH(C_SUSP), MD_CHAR},
+#endif /* VSUSP */
+#if defined(VDSUSP)
+       {"dsusp", C_SH(C_DSUSP), MD_CHAR},
+#endif /* VDSUSP */
+#if defined(VREPRINT)
+       {"reprint", C_SH(C_REPRINT), MD_CHAR},
+#endif /* VREPRINT */
+#if defined(VDISCARD)
+       {"discard", C_SH(C_DISCARD), MD_CHAR},
+#endif /* VDISCARD */
+#if defined(VLNEXT)
+       {"lnext", C_SH(C_LNEXT), MD_CHAR},
+#endif /* VLNEXT */
+#if defined(VSTATUS)
+       {"status", C_SH(C_STATUS), MD_CHAR},
+#endif /* VSTATUS */
+#if defined(VPAGE)
+       {"page", C_SH(C_PAGE), MD_CHAR},
+#endif /* VPAGE */
+#if defined(VPGOFF)
+       {"pgoff", C_SH(C_PGOFF), MD_CHAR},
+#endif /* VPGOFF */
+#if defined(VKILL2)
+       {"kill2", C_SH(C_KILL2), MD_CHAR},
+#endif /* VKILL2 */
+#if defined(VBRK)
+       {"brk", C_SH(C_BRK), MD_CHAR},
+#endif /* VBRK */
+#if defined(VMIN)
+       {"min", C_SH(C_MIN), MD_CHAR},
+#endif /* VMIN */
+#if defined(VTIME)
+       {"time", C_SH(C_TIME), MD_CHAR},
+#endif /* VTIME */
+       {NULL, 0, -1},
+};
+
+
+
+#define        tty__gettabs(td)        ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
+#define        tty__geteightbit(td)    (((td)->c_cflag & CSIZE) == CS8)
+#define        tty__cooked_mode(td)    ((td)->c_lflag & ICANON)
+
+private int    tty_getty(EditLine *, struct termios *);
+private int    tty_setty(EditLine *, int, const struct termios *);
+private int    tty__getcharindex(int);
+private void   tty__getchar(struct termios *, unsigned char *);
+private void   tty__setchar(struct termios *, unsigned char *);
+private speed_t        tty__getspeed(struct termios *);
+private int    tty_setup(EditLine *);
+
+#define        t_qu    t_ts
+
+/* tty_getty():
+ *     Wrapper for tcgetattr to handle EINTR
+ */
+private int
+tty_getty(EditLine *el, struct termios *t)
+{
+       int rv;
+       while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
+               continue;
+       return rv;
+}
+
+/* tty_setty():
+ *     Wrapper for tcsetattr to handle EINTR
+ */
+private int
+tty_setty(EditLine *el, int action, const struct termios *t)
+{
+       int rv;
+       while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
+               continue;
+       return rv;
+}
+
+/* tty_setup():
+ *     Get the tty parameters and initialize the editing state
+ */
+private int
+tty_setup(EditLine *el)
+{
+       int rst = 1;
+
+       if (el->el_flags & EDIT_DISABLED)
+               return 0;
+
+       if (!isatty(el->el_outfd)) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       if (tty_getty(el, &el->el_tty.t_or) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
+
+       el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
+       el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
+       el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
+
+       el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
+       el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
+
+       el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
+       el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
+
+       el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
+       el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
+
+       el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
+       el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
+
+       /*
+         * Reset the tty chars to reasonable defaults
+         * If they are disabled, then enable them.
+         */
+       if (rst) {
+               if (tty__cooked_mode(&el->el_tty.t_ts)) {
+                       tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+                       /*
+                        * Don't affect CMIN and CTIME for the editor mode
+                        */
+                       for (rst = 0; rst < C_NCC - 2; rst++)
+                               if (el->el_tty.t_c[TS_IO][rst] !=
+                                     el->el_tty.t_vdisable
+                                   && el->el_tty.t_c[ED_IO][rst] !=
+                                     el->el_tty.t_vdisable)
+                                       el->el_tty.t_c[ED_IO][rst] =
+                                           el->el_tty.t_c[TS_IO][rst];
+                       for (rst = 0; rst < C_NCC; rst++)
+                               if (el->el_tty.t_c[TS_IO][rst] !=
+                                   el->el_tty.t_vdisable)
+                                       el->el_tty.t_c[EX_IO][rst] =
+                                           el->el_tty.t_c[TS_IO][rst];
+               }
+               tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+               if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+                       (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
+                           __func__, strerror(errno));
+#endif /* DEBUG_TTY */
+                       return -1;
+               }
+       }
+
+       el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
+       el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
+
+       el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
+       el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
+
+       el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
+       el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
+
+       el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
+       el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
+
+       tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+       tty_bind_char(el, 1);
+       return 0;
+}
+
+protected int
+tty_init(EditLine *el)
+{
+
+       el->el_tty.t_mode = EX_IO;
+       el->el_tty.t_vdisable = _POSIX_VDISABLE;
+       (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
+       (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
+       return tty_setup(el);
+}
+
+
+/* tty_end():
+ *     Restore the tty to its original settings
+ */
+protected void
+/*ARGSUSED*/
+tty_end(EditLine *el)
+{
+       if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile,
+                   "%s: tty_setty: %s\n", __func__, strerror(errno));
+#endif /* DEBUG_TTY */
+       }
+}
+
+
+/* tty__getspeed():
+ *     Get the tty speed
+ */
+private speed_t
+tty__getspeed(struct termios *td)
+{
+       speed_t spd;
+
+       if ((spd = cfgetispeed(td)) == 0)
+               spd = cfgetospeed(td);
+       return spd;
+}
+
+/* tty__getspeed():
+ *     Return the index of the asked char in the c_cc array
+ */
+private int
+tty__getcharindex(int i)
+{
+       switch (i) {
+#ifdef VINTR
+       case C_INTR:
+               return VINTR;
+#endif /* VINTR */
+#ifdef VQUIT
+       case C_QUIT:
+               return VQUIT;
+#endif /* VQUIT */
+#ifdef VERASE
+       case C_ERASE:
+               return VERASE;
+#endif /* VERASE */
+#ifdef VKILL
+       case C_KILL:
+               return VKILL;
+#endif /* VKILL */
+#ifdef VEOF
+       case C_EOF:
+               return VEOF;
+#endif /* VEOF */
+#ifdef VEOL
+       case C_EOL:
+               return VEOL;
+#endif /* VEOL */
+#ifdef VEOL2
+       case C_EOL2:
+               return VEOL2;
+#endif /* VEOL2 */
+#ifdef VSWTCH
+       case C_SWTCH:
+               return VSWTCH;
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+       case C_DSWTCH:
+               return VDSWTCH;
+#endif /* VDSWTCH */
+#ifdef VERASE2
+       case C_ERASE2:
+               return VERASE2;
+#endif /* VERASE2 */
+#ifdef VSTART
+       case C_START:
+               return VSTART;
+#endif /* VSTART */
+#ifdef VSTOP
+       case C_STOP:
+               return VSTOP;
+#endif /* VSTOP */
+#ifdef VWERASE
+       case C_WERASE:
+               return VWERASE;
+#endif /* VWERASE */
+#ifdef VSUSP
+       case C_SUSP:
+               return VSUSP;
+#endif /* VSUSP */
+#ifdef VDSUSP
+       case C_DSUSP:
+               return VDSUSP;
+#endif /* VDSUSP */
+#ifdef VREPRINT
+       case C_REPRINT:
+               return VREPRINT;
+#endif /* VREPRINT */
+#ifdef VDISCARD
+       case C_DISCARD:
+               return VDISCARD;
+#endif /* VDISCARD */
+#ifdef VLNEXT
+       case C_LNEXT:
+               return VLNEXT;
+#endif /* VLNEXT */
+#ifdef VSTATUS
+       case C_STATUS:
+               return VSTATUS;
+#endif /* VSTATUS */
+#ifdef VPAGE
+       case C_PAGE:
+               return VPAGE;
+#endif /* VPAGE */
+#ifdef VPGOFF
+       case C_PGOFF:
+               return VPGOFF;
+#endif /* VPGOFF */
+#ifdef VKILL2
+       case C_KILL2:
+               return VKILL2;
+#endif /* KILL2 */
+#ifdef VMIN
+       case C_MIN:
+               return VMIN;
+#endif /* VMIN */
+#ifdef VTIME
+       case C_TIME:
+               return VTIME;
+#endif /* VTIME */
+       default:
+               return -1;
+       }
+}
+
+/* tty__getchar():
+ *     Get the tty characters
+ */
+private void
+tty__getchar(struct termios *td, unsigned char *s)
+{
+
+#ifdef VINTR
+       s[C_INTR] = td->c_cc[VINTR];
+#endif /* VINTR */
+#ifdef VQUIT
+       s[C_QUIT] = td->c_cc[VQUIT];
+#endif /* VQUIT */
+#ifdef VERASE
+       s[C_ERASE] = td->c_cc[VERASE];
+#endif /* VERASE */
+#ifdef VKILL
+       s[C_KILL] = td->c_cc[VKILL];
+#endif /* VKILL */
+#ifdef VEOF
+       s[C_EOF] = td->c_cc[VEOF];
+#endif /* VEOF */
+#ifdef VEOL
+       s[C_EOL] = td->c_cc[VEOL];
+#endif /* VEOL */
+#ifdef VEOL2
+       s[C_EOL2] = td->c_cc[VEOL2];
+#endif /* VEOL2 */
+#ifdef VSWTCH
+       s[C_SWTCH] = td->c_cc[VSWTCH];
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+       s[C_DSWTCH] = td->c_cc[VDSWTCH];
+#endif /* VDSWTCH */
+#ifdef VERASE2
+       s[C_ERASE2] = td->c_cc[VERASE2];
+#endif /* VERASE2 */
+#ifdef VSTART
+       s[C_START] = td->c_cc[VSTART];
+#endif /* VSTART */
+#ifdef VSTOP
+       s[C_STOP] = td->c_cc[VSTOP];
+#endif /* VSTOP */
+#ifdef VWERASE
+       s[C_WERASE] = td->c_cc[VWERASE];
+#endif /* VWERASE */
+#ifdef VSUSP
+       s[C_SUSP] = td->c_cc[VSUSP];
+#endif /* VSUSP */
+#ifdef VDSUSP
+       s[C_DSUSP] = td->c_cc[VDSUSP];
+#endif /* VDSUSP */
+#ifdef VREPRINT
+       s[C_REPRINT] = td->c_cc[VREPRINT];
+#endif /* VREPRINT */
+#ifdef VDISCARD
+       s[C_DISCARD] = td->c_cc[VDISCARD];
+#endif /* VDISCARD */
+#ifdef VLNEXT
+       s[C_LNEXT] = td->c_cc[VLNEXT];
+#endif /* VLNEXT */
+#ifdef VSTATUS
+       s[C_STATUS] = td->c_cc[VSTATUS];
+#endif /* VSTATUS */
+#ifdef VPAGE
+       s[C_PAGE] = td->c_cc[VPAGE];
+#endif /* VPAGE */
+#ifdef VPGOFF
+       s[C_PGOFF] = td->c_cc[VPGOFF];
+#endif /* VPGOFF */
+#ifdef VKILL2
+       s[C_KILL2] = td->c_cc[VKILL2];
+#endif /* KILL2 */
+#ifdef VMIN
+       s[C_MIN] = td->c_cc[VMIN];
+#endif /* VMIN */
+#ifdef VTIME
+       s[C_TIME] = td->c_cc[VTIME];
+#endif /* VTIME */
+}                              /* tty__getchar */
+
+
+/* tty__setchar():
+ *     Set the tty characters
+ */
+private void
+tty__setchar(struct termios *td, unsigned char *s)
+{
+
+#ifdef VINTR
+       td->c_cc[VINTR] = s[C_INTR];
+#endif /* VINTR */
+#ifdef VQUIT
+       td->c_cc[VQUIT] = s[C_QUIT];
+#endif /* VQUIT */
+#ifdef VERASE
+       td->c_cc[VERASE] = s[C_ERASE];
+#endif /* VERASE */
+#ifdef VKILL
+       td->c_cc[VKILL] = s[C_KILL];
+#endif /* VKILL */
+#ifdef VEOF
+       td->c_cc[VEOF] = s[C_EOF];
+#endif /* VEOF */
+#ifdef VEOL
+       td->c_cc[VEOL] = s[C_EOL];
+#endif /* VEOL */
+#ifdef VEOL2
+       td->c_cc[VEOL2] = s[C_EOL2];
+#endif /* VEOL2 */
+#ifdef VSWTCH
+       td->c_cc[VSWTCH] = s[C_SWTCH];
+#endif /* VSWTCH */
+#ifdef VDSWTCH
+       td->c_cc[VDSWTCH] = s[C_DSWTCH];
+#endif /* VDSWTCH */
+#ifdef VERASE2
+       td->c_cc[VERASE2] = s[C_ERASE2];
+#endif /* VERASE2 */
+#ifdef VSTART
+       td->c_cc[VSTART] = s[C_START];
+#endif /* VSTART */
+#ifdef VSTOP
+       td->c_cc[VSTOP] = s[C_STOP];
+#endif /* VSTOP */
+#ifdef VWERASE
+       td->c_cc[VWERASE] = s[C_WERASE];
+#endif /* VWERASE */
+#ifdef VSUSP
+       td->c_cc[VSUSP] = s[C_SUSP];
+#endif /* VSUSP */
+#ifdef VDSUSP
+       td->c_cc[VDSUSP] = s[C_DSUSP];
+#endif /* VDSUSP */
+#ifdef VREPRINT
+       td->c_cc[VREPRINT] = s[C_REPRINT];
+#endif /* VREPRINT */
+#ifdef VDISCARD
+       td->c_cc[VDISCARD] = s[C_DISCARD];
+#endif /* VDISCARD */
+#ifdef VLNEXT
+       td->c_cc[VLNEXT] = s[C_LNEXT];
+#endif /* VLNEXT */
+#ifdef VSTATUS
+       td->c_cc[VSTATUS] = s[C_STATUS];
+#endif /* VSTATUS */
+#ifdef VPAGE
+       td->c_cc[VPAGE] = s[C_PAGE];
+#endif /* VPAGE */
+#ifdef VPGOFF
+       td->c_cc[VPGOFF] = s[C_PGOFF];
+#endif /* VPGOFF */
+#ifdef VKILL2
+       td->c_cc[VKILL2] = s[C_KILL2];
+#endif /* VKILL2 */
+#ifdef VMIN
+       td->c_cc[VMIN] = s[C_MIN];
+#endif /* VMIN */
+#ifdef VTIME
+       td->c_cc[VTIME] = s[C_TIME];
+#endif /* VTIME */
+}                              /* tty__setchar */
+
+
+/* tty_bind_char():
+ *     Rebind the editline functions
+ */
+protected void
+tty_bind_char(EditLine *el, int force)
+{
+
+       unsigned char *t_n = el->el_tty.t_c[ED_IO];
+       unsigned char *t_o = el->el_tty.t_ed.c_cc;
+       Char new[2], old[2];
+       const ttymap_t *tp;
+       el_action_t *map, *alt;
+       const el_action_t *dmap, *dalt;
+       new[1] = old[1] = '\0';
+
+       map = el->el_map.key;
+       alt = el->el_map.alt;
+       if (el->el_map.type == MAP_VI) {
+               dmap = el->el_map.vii;
+               dalt = el->el_map.vic;
+       } else {
+               dmap = el->el_map.emacs;
+               dalt = NULL;
+       }
+
+       for (tp = tty_map; tp->nch != (Int)-1; tp++) {
+               new[0] = t_n[tp->nch];
+               old[0] = t_o[tp->och];
+               if (new[0] == old[0] && !force)
+                       continue;
+               /* Put the old default binding back, and set the new binding */
+               keymacro_clear(el, map, old);
+               map[UC(old[0])] = dmap[UC(old[0])];
+               keymacro_clear(el, map, new);
+               /* MAP_VI == 1, MAP_EMACS == 0... */
+               map[UC(new[0])] = tp->bind[el->el_map.type];
+               if (dalt) {
+                       keymacro_clear(el, alt, old);
+                       alt[UC(old[0])] = dalt[UC(old[0])];
+                       keymacro_clear(el, alt, new);
+                       alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
+               }
+       }
+}
+
+
+/* tty_rawmode():
+ *     Set terminal into 1 character at a time mode.
+ */
+protected int
+tty_rawmode(EditLine *el)
+{
+
+       if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
+               return 0;
+
+       if (el->el_flags & EDIT_DISABLED)
+               return 0;
+
+       if (tty_getty(el, &el->el_tty.t_ts) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       /*
+         * We always keep up with the eight bit setting and the speed of the
+         * tty. But we only believe changes that are made to cooked mode!
+         */
+       el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
+       el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
+
+       if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
+           tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
+               (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+               (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+               (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+               (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+       }
+       if (tty__cooked_mode(&el->el_tty.t_ts)) {
+               if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
+                       el->el_tty.t_ex.c_cflag =
+                           el->el_tty.t_ts.c_cflag;
+                       el->el_tty.t_ex.c_cflag &=
+                           ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
+                       el->el_tty.t_ex.c_cflag |=
+                           el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
+
+                       el->el_tty.t_ed.c_cflag =
+                           el->el_tty.t_ts.c_cflag;
+                       el->el_tty.t_ed.c_cflag &=
+                           ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
+                       el->el_tty.t_ed.c_cflag |=
+                           el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
+               }
+               if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
+                   (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
+                       el->el_tty.t_ex.c_lflag =
+                           el->el_tty.t_ts.c_lflag;
+                       el->el_tty.t_ex.c_lflag &=
+                           ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
+                       el->el_tty.t_ex.c_lflag |=
+                           el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
+
+                       el->el_tty.t_ed.c_lflag =
+                           el->el_tty.t_ts.c_lflag;
+                       el->el_tty.t_ed.c_lflag &=
+                           ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
+                       el->el_tty.t_ed.c_lflag |=
+                           el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
+               }
+               if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
+                   (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
+                       el->el_tty.t_ex.c_iflag =
+                           el->el_tty.t_ts.c_iflag;
+                       el->el_tty.t_ex.c_iflag &=
+                           ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
+                       el->el_tty.t_ex.c_iflag |=
+                           el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
+
+                       el->el_tty.t_ed.c_iflag =
+                           el->el_tty.t_ts.c_iflag;
+                       el->el_tty.t_ed.c_iflag &=
+                           ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
+                       el->el_tty.t_ed.c_iflag |=
+                           el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
+               }
+               if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
+                   (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
+                       el->el_tty.t_ex.c_oflag =
+                           el->el_tty.t_ts.c_oflag;
+                       el->el_tty.t_ex.c_oflag &=
+                           ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
+                       el->el_tty.t_ex.c_oflag |=
+                           el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
+
+                       el->el_tty.t_ed.c_oflag =
+                           el->el_tty.t_ts.c_oflag;
+                       el->el_tty.t_ed.c_oflag &=
+                           ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
+                       el->el_tty.t_ed.c_oflag |=
+                           el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
+               }
+               if (tty__gettabs(&el->el_tty.t_ex) == 0)
+                       el->el_tty.t_tabs = 0;
+               else
+                       el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
+
+               {
+                       int i;
+
+                       tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+                       /*
+                        * Check if the user made any changes.
+                        * If he did, then propagate the changes to the
+                        * edit and execute data structures.
+                        */
+                       for (i = 0; i < C_NCC; i++)
+                               if (el->el_tty.t_c[TS_IO][i] !=
+                                   el->el_tty.t_c[EX_IO][i])
+                                       break;
+
+                       if (i != C_NCC) {
+                               /*
+                                * Propagate changes only to the unprotected
+                                * chars that have been modified just now.
+                                */
+                               for (i = 0; i < C_NCC; i++) {
+                                       if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
+                                           && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
+                                               el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
+                                       if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
+                                               el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
+                               }
+                               tty_bind_char(el, 0);
+                               tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+
+                               for (i = 0; i < C_NCC; i++) {
+                                       if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
+                                           && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
+                                               el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
+                                       if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
+                                               el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
+                               }
+                               tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+                       }
+               }
+       }
+       if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       el->el_tty.t_mode = ED_IO;
+       return 0;
+}
+
+
+/* tty_cookedmode():
+ *     Set the tty back to normal mode
+ */
+protected int
+tty_cookedmode(EditLine *el)
+{                              /* set tty in normal setup */
+
+       if (el->el_tty.t_mode == EX_IO)
+               return 0;
+
+       if (el->el_flags & EDIT_DISABLED)
+               return 0;
+
+       if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       el->el_tty.t_mode = EX_IO;
+       return 0;
+}
+
+
+/* tty_quotemode():
+ *     Turn on quote mode
+ */
+protected int
+tty_quotemode(EditLine *el)
+{
+       if (el->el_tty.t_mode == QU_IO)
+               return 0;
+
+       el->el_tty.t_qu = el->el_tty.t_ed;
+
+       el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
+       el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
+
+       el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
+       el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
+
+       el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
+       el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
+
+       el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
+       el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
+
+       if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       el->el_tty.t_mode = QU_IO;
+       return 0;
+}
+
+
+/* tty_noquotemode():
+ *     Turn off quote mode
+ */
+protected int
+tty_noquotemode(EditLine *el)
+{
+
+       if (el->el_tty.t_mode != QU_IO)
+               return 0;
+       if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+               (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
+                   strerror(errno));
+#endif /* DEBUG_TTY */
+               return -1;
+       }
+       el->el_tty.t_mode = ED_IO;
+       return 0;
+}
+
+
+/* tty_stty():
+ *     Stty builtin
+ */
+protected int
+/*ARGSUSED*/
+tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
+{
+       const ttymodes_t *m;
+       char x;
+       int aflag = 0;
+       const Char *s, *d;
+        char name[EL_BUFSIZ];
+       struct termios *tios = &el->el_tty.t_ex;
+       int z = EX_IO;
+
+       if (argv == NULL)
+               return -1;
+       strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
+        name[sizeof(name) - 1] = '\0';
+
+       while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
+               switch (argv[0][1]) {
+               case 'a':
+                       aflag++;
+                       argv++;
+                       break;
+               case 'd':
+                       argv++;
+                       tios = &el->el_tty.t_ed;
+                       z = ED_IO;
+                       break;
+               case 'x':
+                       argv++;
+                       tios = &el->el_tty.t_ex;
+                       z = EX_IO;
+                       break;
+               case 'q':
+                       argv++;
+                       tios = &el->el_tty.t_ts;
+                       z = QU_IO;
+                       break;
+               default:
+                       (void) fprintf(el->el_errfile,
+                           "%s: Unknown switch `%c'.\n",
+                           name, argv[0][1]);
+                       return -1;
+               }
+
+       if (!argv || !*argv) {
+               int i = -1;
+               size_t len = 0, st = 0, cu;
+               for (m = ttymodes; m->m_name; m++) {
+                       if (m->m_type != i) {
+                               (void) fprintf(el->el_outfile, "%s%s",
+                                   i != -1 ? "\n" : "",
+                                   el->el_tty.t_t[z][m->m_type].t_name);
+                               i = m->m_type;
+                               st = len =
+                                   strlen(el->el_tty.t_t[z][m->m_type].t_name);
+                       }
+                       if (i != -1) {
+                           x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
+                               ?  '+' : '\0';
+
+                           if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
+                               x = '-';
+                       } else {
+                           x = '\0';
+                       }
+
+                       if (x != '\0' || aflag) {
+
+                               cu = strlen(m->m_name) + (x != '\0') + 1;
+
+                               if (len + cu >=
+                                   (size_t)el->el_terminal.t_size.h) {
+                                       (void) fprintf(el->el_outfile, "\n%*s",
+                                           (int)st, "");
+                                       len = st + cu;
+                               } else
+                                       len += cu;
+
+                               if (x != '\0')
+                                       (void) fprintf(el->el_outfile, "%c%s ",
+                                           x, m->m_name);
+                               else
+                                       (void) fprintf(el->el_outfile, "%s ",
+                                           m->m_name);
+                       }
+               }
+               (void) fprintf(el->el_outfile, "\n");
+               return 0;
+       }
+       while (argv && (s = *argv++)) {
+               const Char *p;
+               switch (*s) {
+               case '+':
+               case '-':
+                       x = (char)*s++;
+                       break;
+               default:
+                       x = '\0';
+                       break;
+               }
+               d = s;
+               p = Strchr(s, '=');
+               for (m = ttymodes; m->m_name; m++)
+                       if ((p ? strncmp(m->m_name, ct_encode_string(d,
+                           &el->el_scratch), (size_t)(p - d)) :
+                           strcmp(m->m_name, ct_encode_string(d,
+                           &el->el_scratch))) == 0 &&
+                           (p == NULL || m->m_type == MD_CHAR))
+                               break;
+
+               if (!m->m_name) {
+                       (void) fprintf(el->el_errfile,
+                           "%s: Invalid argument `" FSTR "'.\n", name, d);
+                       return -1;
+               }
+               if (p) {
+                       int c = ffs((int)m->m_value);
+                       int v = *++p ? parse__escape(&p) :
+                           el->el_tty.t_vdisable;
+                       assert(c != 0);
+                       c--;
+                       c = tty__getcharindex(c);
+                       assert(c != -1);
+                       tios->c_cc[c] = (cc_t)v;
+                       continue;
+               }
+               switch (x) {
+               case '+':
+                       el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
+                       el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+                       break;
+               case '-':
+                       el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+                       el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
+                       break;
+               default:
+                       el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+                       el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+                       break;
+               }
+       }
+
+       if (el->el_tty.t_mode == z) {
+               if (tty_setty(el, TCSADRAIN, tios) == -1) {
+#ifdef DEBUG_TTY
+                       (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
+                           __func__, strerror(errno));
+#endif /* DEBUG_TTY */
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+
+#ifdef notyet
+/* tty_printchar():
+ *     DEbugging routine to print the tty characters
+ */
+private void
+tty_printchar(EditLine *el, unsigned char *s)
+{
+       ttyperm_t *m;
+       int i;
+
+       for (i = 0; i < C_NCC; i++) {
+               for (m = el->el_tty.t_t; m->m_name; m++)
+                       if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
+                               break;
+               if (m->m_name)
+                       (void) fprintf(el->el_errfile, "%s ^%c ",
+                           m->m_name, s[i] + 'A' - 1);
+               if (i % 5 == 0)
+                       (void) fprintf(el->el_errfile, "\n");
+       }
+       (void) fprintf(el->el_errfile, "\n");
+}
+#endif /* notyet */
diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h
new file mode 100644 (file)
index 0000000..7bdb0b2
--- /dev/null
@@ -0,0 +1,481 @@
+/*     $NetBSD: tty.h,v 1.14 2012/05/15 15:59:01 christos Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tty.h       8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.tty.h: Local terminal header
+ */
+#ifndef _h_el_tty
+#define        _h_el_tty
+
+#include "sys.h"
+#include "histedit.h"
+#include <termios.h>
+#include <unistd.h>
+
+/* Define our own since everyone gets it wrong! */
+#define        CONTROL(A)      ((A) & 037)
+
+/*
+ * Aix compatible names
+ */
+# if defined(VWERSE) && !defined(VWERASE)
+#  define VWERASE VWERSE
+# endif /* VWERSE && !VWERASE */
+
+# if defined(VDISCRD) && !defined(VDISCARD)
+#  define VDISCARD VDISCRD
+# endif /* VDISCRD && !VDISCARD */
+
+# if defined(VFLUSHO) && !defined(VDISCARD)
+#  define VDISCARD VFLUSHO
+# endif  /* VFLUSHO && VDISCARD */
+
+# if defined(VSTRT) && !defined(VSTART)
+#  define VSTART VSTRT
+# endif /* VSTRT && ! VSTART */
+
+# if defined(VSTAT) && !defined(VSTATUS)
+#  define VSTATUS VSTAT
+# endif /* VSTAT && ! VSTATUS */
+
+# ifndef ONLRET
+#  define ONLRET 0
+# endif /* ONLRET */
+
+# ifndef TAB3
+#  ifdef OXTABS
+#   define TAB3 OXTABS
+#  else
+#   define TAB3 0
+#  endif /* OXTABS */
+# endif /* !TAB3 */
+
+# if defined(OXTABS) && !defined(XTABS)
+#  define XTABS OXTABS
+# endif /* OXTABS && !XTABS */
+
+# ifndef ONLCR
+#  define ONLCR 0
+# endif /* ONLCR */
+
+# ifndef IEXTEN
+#  define IEXTEN 0
+# endif /* IEXTEN */
+
+# ifndef ECHOCTL
+#  define ECHOCTL 0
+# endif /* ECHOCTL */
+
+# ifndef PARENB
+#  define PARENB 0
+# endif /* PARENB */
+
+# ifndef EXTPROC
+#  define EXTPROC 0
+# endif /* EXTPROC */
+
+# ifndef FLUSHO
+#  define FLUSHO  0
+# endif /* FLUSHO */
+
+
+# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
+#  define _POSIX_VDISABLE VDISABLE
+# endif /* VDISABLE && ! _POSIX_VDISABLE */
+
+/*
+ * Work around ISC's definition of IEXTEN which is
+ * XCASE!
+ */
+# ifdef ISC
+#  if defined(IEXTEN) && defined(XCASE)
+#   if IEXTEN == XCASE
+#    undef IEXTEN
+#    define IEXTEN 0
+#   endif /* IEXTEN == XCASE */
+#  endif /* IEXTEN && XCASE */
+#  if defined(IEXTEN) && !defined(XCASE)
+#   define XCASE IEXTEN
+#   undef IEXTEN
+#   define IEXTEN 0
+#  endif /* IEXTEN && !XCASE */
+# endif /* ISC */
+
+/*
+ * Work around convex weirdness where turning off IEXTEN makes us
+ * lose all postprocessing!
+ */
+#if defined(convex) || defined(__convex__)
+# if defined(IEXTEN) && IEXTEN != 0
+#  undef IEXTEN
+#  define IEXTEN 0
+# endif /* IEXTEN != 0 */
+#endif /* convex || __convex__ */
+
+/*
+ * So that we don't lose job control.
+ */
+#ifdef __SVR4
+# undef CSWTCH
+#endif
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE ((unsigned char) -1)
+#endif /* _POSIX_VDISABLE */
+
+#if !defined(CREPRINT) && defined(CRPRNT)
+# define CREPRINT CRPRNT
+#endif /* !CREPRINT && CRPRNT */
+#if !defined(CDISCARD) && defined(CFLUSH)
+# define CDISCARD CFLUSH
+#endif /* !CDISCARD && CFLUSH */
+
+#ifndef CINTR
+# define CINTR         CONTROL('c')
+#endif /* CINTR */
+#ifndef CQUIT
+# define CQUIT         034     /* ^\ */
+#endif /* CQUIT */
+#ifndef CERASE
+# define CERASE                0177    /* ^? */
+#endif /* CERASE */
+#ifndef CKILL
+# define CKILL         CONTROL('u')
+#endif /* CKILL */
+#ifndef CEOF
+# define CEOF          CONTROL('d')
+#endif /* CEOF */
+#ifndef CEOL
+# define CEOL          _POSIX_VDISABLE
+#endif /* CEOL */
+#ifndef CEOL2
+# define CEOL2         _POSIX_VDISABLE
+#endif /* CEOL2 */
+#ifndef CSWTCH
+# define CSWTCH                _POSIX_VDISABLE
+#endif /* CSWTCH */
+#ifndef CDSWTCH
+# define CDSWTCH       _POSIX_VDISABLE
+#endif /* CDSWTCH */
+#ifndef CERASE2
+# define CERASE2       _POSIX_VDISABLE
+#endif /* CERASE2 */
+#ifndef CSTART
+# define CSTART                CONTROL('q')
+#endif /* CSTART */
+#ifndef CSTOP
+# define CSTOP         CONTROL('s')
+#endif /* CSTOP */
+#ifndef CSUSP
+# define CSUSP         CONTROL('z')
+#endif /* CSUSP */
+#ifndef CDSUSP
+# define CDSUSP                CONTROL('y')
+#endif /* CDSUSP */
+
+#ifdef hpux
+
+# ifndef CREPRINT
+#  define CREPRINT     _POSIX_VDISABLE
+# endif /* CREPRINT */
+# ifndef CDISCARD
+#  define CDISCARD     _POSIX_VDISABLE
+# endif /* CDISCARD */
+# ifndef CLNEXT
+#  define CLNEXT       _POSIX_VDISABLE
+# endif /* CLNEXT */
+# ifndef CWERASE
+#  define CWERASE      _POSIX_VDISABLE
+# endif /* CWERASE */
+
+#else /* !hpux */
+
+# ifndef CREPRINT
+#  define CREPRINT     CONTROL('r')
+# endif /* CREPRINT */
+# ifndef CDISCARD
+#  define CDISCARD     CONTROL('o')
+# endif /* CDISCARD */
+# ifndef CLNEXT
+#  define CLNEXT       CONTROL('v')
+# endif /* CLNEXT */
+# ifndef CWERASE
+#  define CWERASE      CONTROL('w')
+# endif /* CWERASE */
+
+#endif /* hpux */
+
+#ifndef CSTATUS
+# define CSTATUS       CONTROL('t')
+#endif /* CSTATUS */
+#ifndef CPAGE
+# define CPAGE         ' '
+#endif /* CPAGE */
+#ifndef CPGOFF
+# define CPGOFF                CONTROL('m')
+#endif /* CPGOFF */
+#ifndef CKILL2
+# define CKILL2                _POSIX_VDISABLE
+#endif /* CKILL2 */
+#ifndef CBRK
+# ifndef masscomp
+#  define CBRK         0377
+# else
+#  define CBRK         '\0'
+# endif /* masscomp */
+#endif /* CBRK */
+#ifndef CMIN
+# define CMIN          CEOF
+#endif /* CMIN */
+#ifndef CTIME
+# define CTIME         CEOL
+#endif /* CTIME */
+
+/*
+ * Fix for sun inconsistency. On termio VSUSP and the rest of the
+ * ttychars > NCC are defined. So we undefine them.
+ */
+#if defined(TERMIO) || defined(POSIX)
+# if defined(POSIX) && defined(NCCS)
+#  define NUMCC                NCCS
+# else
+#  ifdef NCC
+#   define NUMCC       NCC
+#  endif /* NCC */
+# endif /* POSIX && NCCS */
+# ifdef NUMCC
+#  ifdef VINTR
+#   if NUMCC <= VINTR
+#    undef VINTR
+#   endif /* NUMCC <= VINTR */
+#  endif /* VINTR */
+#  ifdef VQUIT
+#   if NUMCC <= VQUIT
+#    undef VQUIT
+#   endif /* NUMCC <= VQUIT */
+#  endif /* VQUIT */
+#  ifdef VERASE
+#   if NUMCC <= VERASE
+#    undef VERASE
+#   endif /* NUMCC <= VERASE */
+#  endif /* VERASE */
+#  ifdef VKILL
+#   if NUMCC <= VKILL
+#    undef VKILL
+#   endif /* NUMCC <= VKILL */
+#  endif /* VKILL */
+#  ifdef VEOF
+#   if NUMCC <= VEOF
+#    undef VEOF
+#   endif /* NUMCC <= VEOF */
+#  endif /* VEOF */
+#  ifdef VEOL
+#   if NUMCC <= VEOL
+#    undef VEOL
+#   endif /* NUMCC <= VEOL */
+#  endif /* VEOL */
+#  ifdef VEOL2
+#   if NUMCC <= VEOL2
+#    undef VEOL2
+#   endif /* NUMCC <= VEOL2 */
+#  endif /* VEOL2 */
+#  ifdef VSWTCH
+#   if NUMCC <= VSWTCH
+#    undef VSWTCH
+#   endif /* NUMCC <= VSWTCH */
+#  endif /* VSWTCH */
+#  ifdef VDSWTCH
+#   if NUMCC <= VDSWTCH
+#    undef VDSWTCH
+#   endif /* NUMCC <= VDSWTCH */
+#  endif /* VDSWTCH */
+#  ifdef VERASE2
+#   if NUMCC <= VERASE2
+#    undef VERASE2
+#   endif /* NUMCC <= VERASE2 */
+#  endif /* VERASE2 */
+#  ifdef VSTART
+#   if NUMCC <= VSTART
+#    undef VSTART
+#   endif /* NUMCC <= VSTART */
+#  endif /* VSTART */
+#  ifdef VSTOP
+#   if NUMCC <= VSTOP
+#    undef VSTOP
+#   endif /* NUMCC <= VSTOP */
+#  endif /* VSTOP */
+#  ifdef VWERASE
+#   if NUMCC <= VWERASE
+#    undef VWERASE
+#   endif /* NUMCC <= VWERASE */
+#  endif /* VWERASE */
+#  ifdef VSUSP
+#   if NUMCC <= VSUSP
+#    undef VSUSP
+#   endif /* NUMCC <= VSUSP */
+#  endif /* VSUSP */
+#  ifdef VDSUSP
+#   if NUMCC <= VDSUSP
+#    undef VDSUSP
+#   endif /* NUMCC <= VDSUSP */
+#  endif /* VDSUSP */
+#  ifdef VREPRINT
+#   if NUMCC <= VREPRINT
+#    undef VREPRINT
+#   endif /* NUMCC <= VREPRINT */
+#  endif /* VREPRINT */
+#  ifdef VDISCARD
+#   if NUMCC <= VDISCARD
+#    undef VDISCARD
+#   endif /* NUMCC <= VDISCARD */
+#  endif /* VDISCARD */
+#  ifdef VLNEXT
+#   if NUMCC <= VLNEXT
+#    undef VLNEXT
+#   endif /* NUMCC <= VLNEXT */
+#  endif /* VLNEXT */
+#  ifdef VSTATUS
+#   if NUMCC <= VSTATUS
+#    undef VSTATUS
+#   endif /* NUMCC <= VSTATUS */
+#  endif /* VSTATUS */
+#  ifdef VPAGE
+#   if NUMCC <= VPAGE
+#    undef VPAGE
+#   endif /* NUMCC <= VPAGE */
+#  endif /* VPAGE */
+#  ifdef VPGOFF
+#   if NUMCC <= VPGOFF
+#    undef VPGOFF
+#   endif /* NUMCC <= VPGOFF */
+#  endif /* VPGOFF */
+#  ifdef VKILL2
+#   if NUMCC <= VKILL2
+#    undef VKILL2
+#   endif /* NUMCC <= VKILL2 */
+#  endif /* VKILL2 */
+#  ifdef VBRK
+#   if NUMCC <= VBRK
+#    undef VBRK
+#   endif /* NUMCC <= VBRK */
+#  endif /* VBRK */
+#  ifdef VMIN
+#   if NUMCC <= VMIN
+#    undef VMIN
+#   endif /* NUMCC <= VMIN */
+#  endif /* VMIN */
+#  ifdef VTIME
+#   if NUMCC <= VTIME
+#    undef VTIME
+#   endif /* NUMCC <= VTIME */
+#  endif /* VTIME */
+# endif /* NUMCC */
+#endif /* !POSIX */
+
+#define        C_INTR           0
+#define        C_QUIT           1
+#define        C_ERASE          2
+#define        C_KILL           3
+#define        C_EOF            4
+#define        C_EOL            5
+#define        C_EOL2           6
+#define        C_SWTCH          7
+#define        C_DSWTCH         8
+#define        C_ERASE2         9
+#define        C_START         10
+#define        C_STOP          11
+#define        C_WERASE        12
+#define        C_SUSP          13
+#define        C_DSUSP         14
+#define        C_REPRINT       15
+#define        C_DISCARD       16
+#define        C_LNEXT         17
+#define        C_STATUS        18
+#define        C_PAGE          19
+#define        C_PGOFF         20
+#define        C_KILL2         21
+#define        C_BRK           22
+#define        C_MIN           23
+#define        C_TIME          24
+#define        C_NCC           25
+#define        C_SH(A)         ((unsigned int)(1 << (A)))
+
+/*
+ * Terminal dependend data structures
+ */
+#define        EX_IO   0       /* while we are executing       */
+#define        ED_IO   1       /* while we are editing         */
+#define        TS_IO   2       /* new mode from terminal       */
+#define        QU_IO   2       /* used only for quoted chars   */
+#define        NN_IO   3       /* The number of entries        */
+
+#define        MD_INP  0
+#define        MD_OUT  1
+#define        MD_CTL  2
+#define        MD_LIN  3
+#define        MD_CHAR 4
+#define        MD_NN   5
+
+typedef struct {
+       const char      *t_name;
+       unsigned int     t_setmask;
+       unsigned int     t_clrmask;
+} ttyperm_t[NN_IO][MD_NN];
+
+typedef unsigned char ttychar_t[NN_IO][C_NCC];
+
+protected int  tty_init(EditLine *);
+protected void tty_end(EditLine *);
+protected int  tty_stty(EditLine *, int, const Char **);
+protected int  tty_rawmode(EditLine *);
+protected int  tty_cookedmode(EditLine *);
+protected int  tty_quotemode(EditLine *);
+protected int  tty_noquotemode(EditLine *);
+protected void tty_bind_char(EditLine *, int);
+
+typedef struct {
+    ttyperm_t t_t;
+    ttychar_t t_c;
+    struct termios t_or, t_ex, t_ed, t_ts;
+    int t_tabs;
+    int t_eight;
+    speed_t t_speed;
+    int t_mode;
+    unsigned char t_vdisable;
+} el_tty_t;
+
+
+#endif /* _h_el_tty */
diff --git a/lib/libedit/unix.h b/lib/libedit/unix.h
deleted file mode 100644 (file)
index e387b2d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-**  Editline system header file for Unix.
-*/
-
-#define CRLF           "\r\n"
-#define FORWARD                STATIC
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if    defined(USE_DIRENT)
-#include <dirent.h>
-typedef struct dirent  DIRENTRY;
-#else
-#include <sys/dir.h>
-typedef struct direct  DIRENTRY;
-#endif /* defined(USE_DIRENT) */
-
-#if    !defined(S_ISDIR)
-#define S_ISDIR(m)             (((m) & S_IFMT) == S_IFDIR)
-#endif /* !defined(S_ISDIR) */
-
-/*
- * $PchId: unix.h,v 1.3 1996/02/22 21:18:51 philip Exp $
- */
diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c
new file mode 100644 (file)
index 0000000..ec9abbd
--- /dev/null
@@ -0,0 +1,1158 @@
+/*     $NetBSD: vi.c,v 1.43 2012/01/16 14:57:45 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/wait.h>
+
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)vi.c       8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: vi.c,v 1.43 2012/01/16 14:57:45 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * vi.c: Vi mode commands.
+ */
+#include "el.h"
+
+private el_action_t    cv_action(EditLine *, Int);
+private el_action_t    cv_paste(EditLine *, Int);
+
+/* cv_action():
+ *     Handle vi actions.
+ */
+private el_action_t
+cv_action(EditLine *el, Int c)
+{
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               /* 'cc', 'dd' and (possibly) friends */
+               if (c != (Int)el->el_chared.c_vcmd.action)
+                       return CC_ERROR;
+
+               if (!(c & YANK))
+                       cv_undo(el);
+               cv_yank(el, el->el_line.buffer,
+                   (int)(el->el_line.lastchar - el->el_line.buffer));
+               el->el_chared.c_vcmd.action = NOP;
+               el->el_chared.c_vcmd.pos = 0;
+               if (!(c & YANK)) {
+                       el->el_line.lastchar = el->el_line.buffer;
+                       el->el_line.cursor = el->el_line.buffer;
+               }
+               if (c & INSERT)
+                       el->el_map.current = el->el_map.key;
+
+               return CC_REFRESH;
+       }
+       el->el_chared.c_vcmd.pos = el->el_line.cursor;
+       el->el_chared.c_vcmd.action = c;
+       return CC_ARGHACK;
+}
+
+/* cv_paste():
+ *     Paste previous deletion before or after the cursor
+ */
+private el_action_t
+cv_paste(EditLine *el, Int c)
+{
+       c_kill_t *k = &el->el_chared.c_kill;
+       size_t len = (size_t)(k->last - k->buf);
+
+       if (k->buf == NULL || len == 0)
+               return CC_ERROR;
+#ifdef DEBUG_PASTE
+       (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf);
+#endif
+
+       cv_undo(el);
+
+       if (!c && el->el_line.cursor < el->el_line.lastchar)
+               el->el_line.cursor++;
+
+       c_insert(el, (int)len);
+       if (el->el_line.cursor + len > el->el_line.lastchar)
+               return CC_ERROR;
+       (void) memcpy(el->el_line.cursor, k->buf, len *
+           sizeof(*el->el_line.cursor));
+
+       return CC_REFRESH;
+}
+
+
+/* vi_paste_next():
+ *     Vi paste previous deletion to the right of the cursor
+ *     [p]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_paste_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_paste(el, 0);
+}
+
+
+/* vi_paste_prev():
+ *     Vi paste previous deletion to the left of the cursor
+ *     [P]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_paste_prev(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_paste(el, 1);
+}
+
+
+/* vi_prev_big_word():
+ *     Vi move to the previous space delimited word
+ *     [B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_big_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       el->el_line.cursor = cv_prev_word(el->el_line.cursor,
+           el->el_line.buffer,
+           el->el_state.argument,
+           cv__isWord);
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
+
+
+/* vi_prev_word():
+ *     Vi move to the previous word
+ *     [b]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       el->el_line.cursor = cv_prev_word(el->el_line.cursor,
+           el->el_line.buffer,
+           el->el_state.argument,
+           cv__isword);
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
+
+
+/* vi_next_big_word():
+ *     Vi move to the next space delimited word
+ *     [W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_big_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor >= el->el_line.lastchar - 1)
+               return CC_ERROR;
+
+       el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
+           el->el_line.lastchar, el->el_state.argument, cv__isWord);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* vi_next_word():
+ *     Vi move to the next word
+ *     [w]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor >= el->el_line.lastchar - 1)
+               return CC_ERROR;
+
+       el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
+           el->el_line.lastchar, el->el_state.argument, cv__isword);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* vi_change_case():
+ *     Vi change case of character under the cursor and advance one character
+ *     [~]
+ */
+protected el_action_t
+vi_change_case(EditLine *el, Int c)
+{
+       int i;
+
+       if (el->el_line.cursor >= el->el_line.lastchar)
+               return CC_ERROR;
+       cv_undo(el);
+       for (i = 0; i < el->el_state.argument; i++) {
+
+               c = *el->el_line.cursor;
+               if (Isupper(c))
+                       *el->el_line.cursor = Tolower(c);
+               else if (Islower(c))
+                       *el->el_line.cursor = Toupper(c);
+
+               if (++el->el_line.cursor >= el->el_line.lastchar) {
+                       el->el_line.cursor--;
+                       re_fastaddc(el);
+                       break;
+               }
+               re_fastaddc(el);
+       }
+       return CC_NORM;
+}
+
+
+/* vi_change_meta():
+ *     Vi change prefix command
+ *     [c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_change_meta(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       /*
+         * Delete with insert == change: first we delete and then we leave in
+         * insert mode.
+         */
+       return cv_action(el, DELETE | INSERT);
+}
+
+
+/* vi_insert_at_bol():
+ *     Vi enter insert mode at the beginning of line
+ *     [I]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_insert_at_bol(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.buffer;
+       cv_undo(el);
+       el->el_map.current = el->el_map.key;
+       return CC_CURSOR;
+}
+
+
+/* vi_replace_char():
+ *     Vi replace character under the cursor with the next character typed
+ *     [r]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_replace_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor >= el->el_line.lastchar)
+               return CC_ERROR;
+
+       el->el_map.current = el->el_map.key;
+       el->el_state.inputmode = MODE_REPLACE_1;
+       cv_undo(el);
+       return CC_ARGHACK;
+}
+
+
+/* vi_replace_mode():
+ *     Vi enter replace mode
+ *     [R]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_replace_mode(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_map.current = el->el_map.key;
+       el->el_state.inputmode = MODE_REPLACE;
+       cv_undo(el);
+       return CC_NORM;
+}
+
+
+/* vi_substitute_char():
+ *     Vi replace character under the cursor and enter insert mode
+ *     [s]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_substitute_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       c_delafter(el, el->el_state.argument);
+       el->el_map.current = el->el_map.key;
+       return CC_REFRESH;
+}
+
+
+/* vi_substitute_line():
+ *     Vi substitute entire line
+ *     [S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_substitute_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       cv_undo(el);
+       cv_yank(el, el->el_line.buffer,
+           (int)(el->el_line.lastchar - el->el_line.buffer));
+       (void) em_kill_line(el, 0);
+       el->el_map.current = el->el_map.key;
+       return CC_REFRESH;
+}
+
+
+/* vi_change_to_eol():
+ *     Vi change to end of line
+ *     [C]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_change_to_eol(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       cv_undo(el);
+       cv_yank(el, el->el_line.cursor,
+           (int)(el->el_line.lastchar - el->el_line.cursor));
+       (void) ed_kill_line(el, 0);
+       el->el_map.current = el->el_map.key;
+       return CC_REFRESH;
+}
+
+
+/* vi_insert():
+ *     Vi enter insert mode
+ *     [i]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_insert(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_map.current = el->el_map.key;
+       cv_undo(el);
+       return CC_NORM;
+}
+
+
+/* vi_add():
+ *     Vi enter insert mode after the cursor
+ *     [a]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_add(EditLine *el, Int c __attribute__((__unused__)))
+{
+       int ret;
+
+       el->el_map.current = el->el_map.key;
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               el->el_line.cursor++;
+               if (el->el_line.cursor > el->el_line.lastchar)
+                       el->el_line.cursor = el->el_line.lastchar;
+               ret = CC_CURSOR;
+       } else
+               ret = CC_NORM;
+
+       cv_undo(el);
+
+       return (el_action_t)ret;
+}
+
+
+/* vi_add_at_eol():
+ *     Vi enter insert mode at end of line
+ *     [A]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_add_at_eol(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_map.current = el->el_map.key;
+       el->el_line.cursor = el->el_line.lastchar;
+       cv_undo(el);
+       return CC_CURSOR;
+}
+
+
+/* vi_delete_meta():
+ *     Vi delete prefix command
+ *     [d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_delete_meta(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_action(el, DELETE);
+}
+
+
+/* vi_end_big_word():
+ *     Vi move to the end of the current space delimited word
+ *     [E]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_end_big_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return CC_ERROR;
+
+       el->el_line.cursor = cv__endword(el->el_line.cursor,
+           el->el_line.lastchar, el->el_state.argument, cv__isWord);
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               el->el_line.cursor++;
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
+
+
+/* vi_end_word():
+ *     Vi move to the end of the current word
+ *     [e]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_end_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return CC_ERROR;
+
+       el->el_line.cursor = cv__endword(el->el_line.cursor,
+           el->el_line.lastchar, el->el_state.argument, cv__isword);
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               el->el_line.cursor++;
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
+
+
+/* vi_undo():
+ *     Vi undo last change
+ *     [u]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_undo(EditLine *el, Int c __attribute__((__unused__)))
+{
+       c_undo_t un = el->el_chared.c_undo;
+
+       if (un.len == -1)
+               return CC_ERROR;
+
+       /* switch line buffer and undo buffer */
+       el->el_chared.c_undo.buf = el->el_line.buffer;
+       el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
+       el->el_chared.c_undo.cursor =
+           (int)(el->el_line.cursor - el->el_line.buffer);
+       el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
+       el->el_line.buffer = un.buf;
+       el->el_line.cursor = un.buf + un.cursor;
+       el->el_line.lastchar = un.buf + un.len;
+
+       return CC_REFRESH;
+}
+
+
+/* vi_command_mode():
+ *     Vi enter command mode (use alternative key bindings)
+ *     [<ESC>]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_command_mode(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       /* [Esc] cancels pending action */
+       el->el_chared.c_vcmd.action = NOP;
+       el->el_chared.c_vcmd.pos = 0;
+
+       el->el_state.doingarg = 0;
+
+       el->el_state.inputmode = MODE_INSERT;
+       el->el_map.current = el->el_map.alt;
+#ifdef VI_MOVE
+       if (el->el_line.cursor > el->el_line.buffer)
+               el->el_line.cursor--;
+#endif
+       return CC_CURSOR;
+}
+
+
+/* vi_zero():
+ *     Vi move to the beginning of line
+ *     [0]
+ */
+protected el_action_t
+vi_zero(EditLine *el, Int c)
+{
+
+       if (el->el_state.doingarg)
+               return ed_argument_digit(el, c);
+
+       el->el_line.cursor = el->el_line.buffer;
+       if (el->el_chared.c_vcmd.action != NOP) {
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
+
+
+/* vi_delete_prev_char():
+ *     Vi move to previous character (backspace)
+ *     [^H] in insert mode only
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor <= el->el_line.buffer)
+               return CC_ERROR;
+
+       c_delbefore1(el);
+       el->el_line.cursor--;
+       return CC_REFRESH;
+}
+
+
+/* vi_list_or_eof():
+ *     Vi list choices for completion or indicate end of file if empty line
+ *     [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_list_or_eof(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor == el->el_line.lastchar) {
+               if (el->el_line.cursor == el->el_line.buffer) {
+                       terminal_writec(el, c); /* then do a EOF */
+                       return CC_EOF;
+               } else {
+                       /*
+                        * Here we could list completions, but it is an
+                        * error right now
+                        */
+                       terminal_beep(el);
+                       return CC_ERROR;
+               }
+       } else {
+#ifdef notyet
+               re_goto_bottom(el);
+               *el->el_line.lastchar = '\0';   /* just in case */
+               return CC_LIST_CHOICES;
+#else
+               /*
+                * Just complain for now.
+                */
+               terminal_beep(el);
+               return CC_ERROR;
+#endif
+       }
+}
+
+
+/* vi_kill_line_prev():
+ *     Vi cut from beginning of line to cursor
+ *     [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_kill_line_prev(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       cp = el->el_line.buffer;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.cursor)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+       c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer));
+       el->el_line.cursor = el->el_line.buffer;        /* zap! */
+       return CC_REFRESH;
+}
+
+
+/* vi_search_prev():
+ *     Vi search history previous
+ *     [?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_search_prev(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_search(el, ED_SEARCH_PREV_HISTORY);
+}
+
+
+/* vi_search_next():
+ *     Vi search history next
+ *     [/]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_search_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_search(el, ED_SEARCH_NEXT_HISTORY);
+}
+
+
+/* vi_repeat_search_next():
+ *     Vi repeat current search in the same search direction
+ *     [n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_search_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_search.patlen == 0)
+               return CC_ERROR;
+       else
+               return cv_repeat_srch(el, el->el_search.patdir);
+}
+
+
+/* vi_repeat_search_prev():
+ *     Vi repeat current search in the opposite search direction
+ *     [N]
+ */
+/*ARGSUSED*/
+protected el_action_t
+vi_repeat_search_prev(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_search.patlen == 0)
+               return CC_ERROR;
+       else
+               return (cv_repeat_srch(el,
+                   el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
+                   ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
+}
+
+
+/* vi_next_char():
+ *     Vi move to the character specified next
+ *     [f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
+}
+
+
+/* vi_prev_char():
+ *     Vi move to the character specified previous
+ *     [F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
+}
+
+
+/* vi_to_next_char():
+ *     Vi move up to the character specified next
+ *     [t]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
+}
+
+
+/* vi_to_prev_char():
+ *     Vi move up to the character specified previous
+ *     [T]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
+}
+
+
+/* vi_repeat_next_char():
+ *     Vi repeat current character search in the same search direction
+ *     [;]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
+               el->el_state.argument, el->el_search.chatflg);
+}
+
+
+/* vi_repeat_prev_char():
+ *     Vi repeat current character search in the opposite search direction
+ *     [,]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_repeat_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       el_action_t r;
+       int dir = el->el_search.chadir;
+
+       r = cv_csearch(el, -dir, el->el_search.chacha,
+               el->el_state.argument, el->el_search.chatflg);
+       el->el_search.chadir = dir;
+       return r;
+}
+
+
+/* vi_match():
+ *     Vi go to matching () {} or []
+ *     [%]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_match(EditLine *el, Int c __attribute__((__unused__)))
+{
+       const Char match_chars[] = STR("()[]{}");
+       Char *cp;
+       size_t delta, i, count;
+       Char o_ch, c_ch;
+
+       *el->el_line.lastchar = '\0';           /* just in case */
+
+       i = Strcspn(el->el_line.cursor, match_chars);
+       o_ch = el->el_line.cursor[i];
+       if (o_ch == 0)
+               return CC_ERROR;
+       delta = (size_t)(Strchr(match_chars, o_ch) - match_chars);
+       c_ch = match_chars[delta ^ 1];
+       count = 1;
+       delta = 1 - (delta & 1) * 2;
+
+       for (cp = &el->el_line.cursor[i]; count; ) {
+               cp += delta;
+               if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
+                       return CC_ERROR;
+               if (*cp == o_ch)
+                       count++;
+               else if (*cp == c_ch)
+                       count--;
+       }
+
+       el->el_line.cursor = cp;
+
+       if (el->el_chared.c_vcmd.action != NOP) {
+               /* NB posix says char under cursor should NOT be deleted
+                  for -ve delta - this is different to netbsd vi. */
+               if (delta > 0)
+                       el->el_line.cursor++;
+               cv_delfini(el);
+               return CC_REFRESH;
+       }
+       return CC_CURSOR;
+}
+
+/* vi_undo_line():
+ *     Vi undo all changes to line
+ *     [U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_undo_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       cv_undo(el);
+       return hist_get(el);
+}
+
+/* vi_to_column():
+ *     Vi go to specified column
+ *     [|]
+ * NB netbsd vi goes to screen column 'n', posix says nth character
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_column(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.buffer;
+       el->el_state.argument--;
+       return ed_next_char(el, 0);
+}
+
+/* vi_yank_end():
+ *     Vi yank to end of line
+ *     [Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_yank_end(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       cv_yank(el, el->el_line.cursor,
+           (int)(el->el_line.lastchar - el->el_line.cursor));
+       return CC_REFRESH;
+}
+
+/* vi_yank():
+ *     Vi yank
+ *     [y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_yank(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       return cv_action(el, YANK);
+}
+
+/* vi_comment_out():
+ *     Vi comment out current command
+ *     [#]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_comment_out(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.buffer;
+       c_insert(el, 1);
+       *el->el_line.cursor = '#';
+       re_refresh(el);
+       return ed_newline(el, 0);
+}
+
+/* vi_alias():
+ *     Vi include shell alias
+ *     [@]
+ * NB: posix implies that we should enter insert mode, however
+ * this is against historical precedent...
+ */
+#ifdef __weak_reference
+__weakref_visible char *my_get_alias_text(const char *)
+    __weak_reference(get_alias_text);
+#endif
+protected el_action_t
+/*ARGSUSED*/
+vi_alias(EditLine *el, Int c __attribute__((__unused__)))
+{
+#ifdef __weak_reference
+       char alias_name[3];
+       char *alias_text;
+
+       if (my_get_alias_text == 0) {
+               return CC_ERROR;
+       }
+
+       alias_name[0] = '_';
+       alias_name[2] = 0;
+       if (el_getc(el, &alias_name[1]) != 1)
+               return CC_ERROR;
+
+       alias_text = my_get_alias_text(alias_name);
+       if (alias_text != NULL)
+               FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch));
+       return CC_NORM;
+#else
+       return CC_ERROR;
+#endif
+}
+
+/* vi_to_history_line():
+ *     Vi go to specified history file line.
+ *     [G]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_to_history_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       int sv_event_no = el->el_history.eventno;
+       el_action_t rval;
+
+
+       if (el->el_history.eventno == 0) {
+                (void) Strncpy(el->el_history.buf, el->el_line.buffer,
+                    EL_BUFSIZ);
+                el->el_history.last = el->el_history.buf +
+                        (el->el_line.lastchar - el->el_line.buffer);
+       }
+
+       /* Lack of a 'count' means oldest, not 1 */
+       if (!el->el_state.doingarg) {
+               el->el_history.eventno = 0x7fffffff;
+               hist_get(el);
+       } else {
+               /* This is brain dead, all the rest of this code counts
+                * upwards going into the past.  Here we need count in the
+                * other direction (to match the output of fc -l).
+                * I could change the world, but this seems to suffice.
+                */
+               el->el_history.eventno = 1;
+               if (hist_get(el) == CC_ERROR)
+                       return CC_ERROR;
+               el->el_history.eventno = 1 + el->el_history.ev.num 
+                                       - el->el_state.argument;
+               if (el->el_history.eventno < 0) {
+                       el->el_history.eventno = sv_event_no;
+                       return CC_ERROR;
+               }
+       }
+       rval = hist_get(el);
+       if (rval == CC_ERROR)
+               el->el_history.eventno = sv_event_no;
+       return rval;
+}
+
+/* vi_histedit():
+ *     Vi edit history line with vi
+ *     [v]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_histedit(EditLine *el, Int c __attribute__((__unused__)))
+{
+       int fd;
+       pid_t pid;
+       ssize_t st;
+       int status;
+       char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
+       char *cp = NULL;
+       size_t len;
+       Char *line = NULL;
+
+       if (el->el_state.doingarg) {
+               if (vi_to_history_line(el, 0) == CC_ERROR)
+                       return CC_ERROR;
+       }
+
+       fd = mkstemp(tempfile);
+       if (fd < 0)
+               return CC_ERROR;
+       len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
+#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
+       cp = el_malloc(TMP_BUFSIZ * sizeof(*cp));
+       if (cp == NULL)
+               goto error;
+       line = el_malloc(len * sizeof(*line) + 1);
+       if (line == NULL)
+               goto error;
+       Strncpy(line, el->el_line.buffer, len);
+       line[len] = '\0';
+       ct_wcstombs(cp, line, TMP_BUFSIZ - 1);
+       cp[TMP_BUFSIZ - 1] = '\0';
+       len = strlen(cp);
+       write(fd, cp, len);
+       write(fd, "\n", (size_t)1);
+       pid = fork();
+       switch (pid) {
+       case -1:
+               goto error;
+       case 0:
+               close(fd);
+               execlp("vi", "vi", tempfile, (char *)NULL);
+               exit(0);
+               /*NOTREACHED*/
+       default:
+               while (waitpid(pid, &status, 0) != pid)
+                       continue;
+               lseek(fd, (off_t)0, SEEK_SET);
+               st = read(fd, cp, TMP_BUFSIZ);
+               if (st > 0) {
+                       len = (size_t)(el->el_line.lastchar -
+                           el->el_line.buffer);
+                       len = ct_mbstowcs(el->el_line.buffer, cp, len);
+                       if (len > 0 && el->el_line.buffer[len -1] == '\n')
+                               --len;
+               }
+               else
+                       len = 0;
+                el->el_line.cursor = el->el_line.buffer;
+                el->el_line.lastchar = el->el_line.buffer + len;
+               el_free(cp);
+                el_free(line);
+               break;
+       }
+
+       close(fd);
+       unlink(tempfile);
+       /* return CC_REFRESH; */
+       return ed_newline(el, 0);
+error:
+       el_free(line);
+       el_free(cp);
+       close(fd);
+       unlink(tempfile);
+       return CC_ERROR;
+}
+
+/* vi_history_word():
+ *     Vi append word from previous input line
+ *     [_]
+ * Who knows where this one came from!
+ * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_history_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       const Char *wp = HIST_FIRST(el);
+       const Char *wep, *wsp;
+       int len;
+       Char *cp;
+       const Char *lim;
+
+       if (wp == NULL)
+               return CC_ERROR;
+
+       wep = wsp = 0;
+       do {
+               while (Isspace(*wp))
+                       wp++;
+               if (*wp == 0)
+                       break;
+               wsp = wp;
+               while (*wp && !Isspace(*wp))
+                       wp++;
+               wep = wp;
+       } while ((!el->el_state.doingarg || --el->el_state.argument > 0)
+           && *wp != 0);
+
+       if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
+               return CC_ERROR;
+
+       cv_undo(el);
+       len = (int)(wep - wsp);
+       if (el->el_line.cursor < el->el_line.lastchar)
+               el->el_line.cursor++;
+       c_insert(el, len + 1);
+       cp = el->el_line.cursor;
+       lim = el->el_line.limit;
+       if (cp < lim)
+               *cp++ = ' ';
+       while (wsp < wep && cp < lim)
+               *cp++ = *wsp++;
+       el->el_line.cursor = cp;
+
+       el->el_map.current = el->el_map.key;
+       return CC_REFRESH;
+}
+
+/* vi_redo():
+ *     Vi redo last non-motion command
+ *     [.]
+ */
+protected el_action_t
+/*ARGSUSED*/
+vi_redo(EditLine *el, Int c __attribute__((__unused__)))
+{
+       c_redo_t *r = &el->el_chared.c_redo;
+
+       if (!el->el_state.doingarg && r->count) {
+               el->el_state.doingarg = 1;
+               el->el_state.argument = r->count;
+       }
+
+       el->el_chared.c_vcmd.pos = el->el_line.cursor;
+       el->el_chared.c_vcmd.action = r->action;
+       if (r->pos != r->buf) {
+               if (r->pos + 1 > r->lim)
+                       /* sanity */
+                       r->pos = r->lim - 1;
+               r->pos[0] = 0;
+               FUN(el,push)(el, r->buf);
+       }
+
+       el->el_state.thiscmd = r->cmd;
+       el->el_state.thisch = r->ch;
+       return (*el->el_map.func[r->cmd])(el, r->ch);
+}
index 342b8686f8ad8d9f112c4fd2b4a88ecd9c488ef5..a194be171f2faa5c3c8f4b2f216cb79bdece8cc9 100644 (file)
@@ -1,11 +1,11 @@
 MAN=   ash.1 at.1 banner.1 basename.1 \
        bsfilt.1 cal.1 cawf.1 chgrp.1 \
        chmod.1 clear.1 cmp.1 comm.1 compress.1 \
-       cp.1 crc.1 crontab.1 ctags.1 dd.1 \
+       cp.1 crc.1 crontab.1 dd.1 \
        df.1 dhrystone.1 dosdir.1 dosread.1 doswrite.1 \
-       dumpcore.1 echo.1 eject.1 elvis.1 elvrec.1 \
+       dumpcore.1 echo.1 eject.1 \
        env.1 expand.1 expr.1 factor.1 \
-       finger.1 flexdoc.1 fmt.1 fold.1 format.1 fortune.1 \
+       finger.1 flexdoc.1 fold.1 format.1 fortune.1 \
        fsck.mfs.1 head.1 host.1 hostaddr.1 ifdef.1 \
        isodir.1 isoinfo.1 isoread.1 kill.1 \
        last.1 loadfont.1 loadkeys.1 logger.1 \
@@ -14,7 +14,7 @@ MAN=  ash.1 at.1 banner.1 basename.1 \
        mkproto.1 mount.1 mt.1 nice.1 nm.1 nohup.1 od.1 \
        paste.1 ping.1 playwave.1 pr.1 prep.1 \
        profile.1 ps.1 pwd.1 rcp.1 recwave.1 \
-       ref.1 remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
+       remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
        shar.1 acksize.1 sleep.1 spell.1 \
        split.1 stty.1 svc.1 svrctl.1 \
        synctree.1 sysenv.1 sz.1 tail.1 tee.1 telnet.1 template.1 \
@@ -54,7 +54,6 @@ MLINKS += compress.1 uncompress.1
 MLINKS += cp.1 mv.1
 MLINKS += cp.1 ln.1
 MLINKS += cp.1 cpdir.1
-MLINKS += elvis.1 ex.1
 MLINKS += expr.1 test.1
 MLINKS += expr.1 [.1
 MLINKS += svc.1 ci.1
diff --git a/man/man1/ctags.1 b/man/man1/ctags.1
deleted file mode 100644 (file)
index 7aa3175..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-.TH CTAGS 1
-.SH NAME
-ctags - Generates "tags" and (optionally) "refs" files
-.SH SYNOPSIS
-\fBctags\fP [\fB-stvra\fP] \fIfilesnames\fP...
-.SH DESCRIPTION
-\fIctags\fP generates the "tags" and "refs" files
-from a group of C source files.
-The "tags" file is used by Elvis' ":tag" command,
-control-] command,
-and -t option.
-The "refs" file is sometimes used by the \fIref(1)\fP program.
-.PP
-Each C source file is scanned for #define statements and
-global function definitions.
-The name of the macro or function becomes the name of a tag.
-For each tag, a line is added to the "tags" file which contains:
-.RS
-.nf
-       - the name of the tag
-       - a tab character
-       - the name of the file containing the tag
-       - a tab character
-       - a way to find the particular line within the file.
-.RE
-.fi
-.PP
-The filenames list will typically be the names of all C source
-files in the current directory, like this:
-.RS
-.nf
-$ ctags -stv *.[ch]
-.RE
-.fi
-.SH OPTIONS
-.IP \fB-t\fR
-Include typedefs.
-A tag will be generated for each user-defined type.
-Also tags will be generated for struct and enum names.
-Types are considered to be global if they are defined in a header file,
-and static if they are defined in a C source file.
-.IP \fB-v\fR
-Include variable declarations.
-A tag will be generated for each variable, except for those that are declared
-inside the body of a function.
-.IP \fB-s\fR
-Include static tags.
-\fICtags\fR will normally put global tags in the "tags" file, and silently ignore
-the static tags.
-This flag causes both global and static tags to be added.
-The name of a static tag is generated by prefixing the name of the declared
-item with the name of the file where it is defined, with a colon in between.
-For example, "static foo(){}" in "bar.c" results in a tag named "bar.c:foo".
-.IP \fB-r\fP
-This causes \fIctags\fP to generate both "tags" and "refs".
-Without \fB-r\fP, it would only generate "tags".
-.IP \fB-a\fR
-Append to "tags", and maybe "refs".
-Normally, \fIctags\fR overwrites these files each time it is invoked.
-This flag is useful when you have to many files in the current directory
-for you to list them on a single command-line;
-it allows you to split the arguments among several invocations.
-.SH FILES
-.IP tags
-A cross-reference that lists each tag name, the name of the source file that
-contains it, and a way to locate a particular line in the source file.
-.IP refs
-The "refs" file contains the definitions for each tag in the "tags" file,
-and very little else.
-This file can be useful, for example, when licensing restrictions prevent
-you from making the source code to the standard C library readable by everybody,
-but you still everybody to know what arguments the library functions need.
-.SH BUGS
-.PP
-\fIctags\fR is sensitive to indenting and line breaks.
-Consequently, it might not discover all of the tags in a file that
-is formatted in an unusual way.
-.SH "SEE ALSO"
-elvis(1), refs(1)
-.SH AUTHOR
-.nf
-Steve Kirkendall
-kirkenda@cs.pdx.edu
-.fi
diff --git a/man/man1/elvis.1 b/man/man1/elvis.1
deleted file mode 100644 (file)
index 504ac93..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-.TH ELVIS 1
-.SH NAME
-elvis, ex, vi \- The editor
-.SH SYNOPSIS
-\fBelvis\fP [\fIflags\fP] [\fB+\fP\fIcmd\fP] [\fIfiles\fP...]
-.SH DESCRIPTION
-\fBElvis\fP is a text editor which emulates \fBvi\fP/\fBex\fP.
-.PP
-On systems which pass the program name as an argument, such as UNIX and MINIX 3,
-you may also install \fBelvis\fP under the names "ex", "vi", "view", and "input".
-These extra names would normally be links to elvis;
-see the "ln" shell command.
-.PP
-When \fBelvis\fP is invoked as "vi",
-it behaves exactly as though it was invoked as "elvis".
-However, if you invoke \fBelvis\fP as "view",
-then the readonly option is set as though you had given it the "-R" flag.
-If you invoke \fBelvis\fP as "ex",
-then \fBelvis\fP will start up in the colon command mode
-instead of the visual command mode,
-as though you had given it the "-e" flag.
-If you invoke \fBelvis\fP as "input" or "edit",
-then \fBelvis\fP will start up in input mode,
-as though the "-i" flag was given.
-.SH OPTIONS
-.IP \fB-r\fP
-To the real vi, this flag means that a previous edit should be recovered.
-\fBElvis\fP, though, has a separate program, called \fIelvrec\fP(1), for recovering
-files.
-When you invoke \fBelvis\fP with -r, \fBelvis\fP will tell you to run \fBelvrec\fP.
-.IP \fB-R\fP
-This sets the "readonly" option,
-so you won't accidentally overwrite a file.
-.IP "\fB-t\fP \fItag\fP"
-This causes \fBelvis\fP to start editing at the given tag.
-.IP "\fB-m\fP [\fIfile\fP]"
-\fBElvis\fP will search through \fIfile\fP for something that looks like
-an error message from a compiler.
-It will then begin editing the source file that caused the error,
-with the cursor sitting on the line where the error was detected.
-If you don't explicitly name a \fIfile\fP, then "errlist" is assumed.
-.IP \fB-e\fP
-\fBElvis\fP will start up in colon command mode.
-.IP \fB-v\fP
-\fBElvis\fP will start up in visual command mode.
-.IP \fB-i\fP
-\fBElvis\fP will start up in input mode.
-.IP "\fB-w\fR \fIwinsize\fR"
-Sets the "window" option's value to \fIwinsize\fR.
-.IP "\fB+\fP\fIcommand\fP or \fB-c\fP \fIcommand\fP"
-If you use the +\fIcommand\fP parameter,
-then after the first file is loaded
-\fIcommand\fP is executed as an EX command.
-A typical example would be "elvis +237 foo",
-which would cause \fBelvis\fP to start editing foo and
-then move directly to line 237.
-The "-c \fIcommand\fP" variant was added for UNIX SysV compatibility.
-.SH FILES
-.IP /tmp/elv*
-During editing,
-\fBelvis\fP stores text in a temporary file.
-For UNIX, this file will usually be stored in the /tmp directory,
-and the first three characters will be "elv".
-For other systems, the temporary files may be stored someplace else;
-see the version-specific section of the documentation.
-.IP tags
-This is the database used by the \fB:tags\fP command and the \fB-t\fP option.
-It is usually created by the \fBctags\fP(1) program.
-.IP ".exrc or elvis.rc"
-On UNIX-like systems, a file called ".exrc" in your home directory
-is executed as a series of \fBex\fR commands.
-A file by the same name may be executed in the current directory, too.
-On non-UNIX systems, ".exrc" is usually an invalid file name;
-there, the initialization file is called "elvis.rc" instead.
-.SH "SEE ALSO"
-.BR ctags (1),
-.BR ref (1),
-.BR elvrec (1),
-.BR elvis (1x).
-.PP
-\fIElvis - A Clone of Vi/Ex\fP, the complete \fBelvis\fP documentation.
-.SH BUGS
-There is no LISP support.
-Certain other features are missing, too.
-.PP
-Auto-indent mode is not quite compatible with the real vi.
-Among other things, 0^D and ^^D don't do what you might expect.
-.PP
-Long lines are displayed differently.
-The real vi wraps long lines onto multiple rows of the screen,
-but \fBelvis\fP scrolls sideways.
-.SH AUTHOR
-.nf
-Steve Kirkendall
-kirkenda@cs.pdx.edu
-.fi
-.PP
-Many other people have worked to port \fBelvis\fP to various operating systems.
-To see who deserves credit, run the \fB:version\fP command from within \fBelvis\fP,
-or look in the system-specific section of the complete documentation.
-.\" ref to virec chnaged to elvrec -- ASW 2004-12-13
diff --git a/man/man1/elvrec.1 b/man/man1/elvrec.1
deleted file mode 100644 (file)
index b541c2e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-.TH ELVREC 1
-.SH NAME
-elvrec - Recover the modified version of a file after a crash
-.SH SYNOPSIS
-.nf
-\fBelvrec\fP [\fIpreservedfile\fP [\fInewfile\fR]]
-.fi
-.SH DESCRIPTION
-.PP
-If you're editing a file when \fIelvis\fP dies, the system crashes, or power fails,
-the most recent version of your text will be preserved.
-The preserved text is stored in a special directory; it does NOT overwrite
-your text file automatically.
-.PP
-The \fIelvrec\fP program locates the preserved version of a given file,
-and writes it over the top of your text file -- or to a new file, if you prefer.
-The recovered file will have nearly all of your changes.
-.PP
-To see a list of all recoverable files, run \fIelvrec\fP with no arguments.
-.SH FILES
-.IP /usr/preserve/p*
-The text that was preserved when \fIelvis\fP died.
-.IP /usr/preserve/Index
-A text file which lists the names of all preserved files, and the names
-of the /usr/preserve/p* files which contain their preserved text.
-.SH BUGS
-.PP
-\fIelvrec\fP is very picky about filenames.
-You must tell it to recover the file using exactly the same pathname as
-when you were editing it.
-The simplest way to do this is to go into the same directory that you were
-editing, and invoke \fIelvrec\fP with the same filename as \fIelvis\fP.
-If that doesn't work, then try running \fIelvrec\fP with no arguments,
-to see exactly which pathname it is using for the desired file.
-.PP
-Due to the permissions on the /usr/preserve directory, on UNIX systems
-\fIelvrec\fP must be run as superuser.
-This is accomplished by making the \fIelvrec\fP executable be owned by "root"
-and setting its "set user id" bit.
-.PP
-If you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvrec\fP
-will pretend that the file was named "foo".
-.SH AUTHOR
-.nf
-Steve Kirkendall
-kirkenda@cs.pdx.edu
-.fi
diff --git a/man/man1/fmt.1 b/man/man1/fmt.1
deleted file mode 100644 (file)
index 3c731fa..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-.TH FMT 1
-.SH NAME
-fmt - adjust line-length for paragraphs of text
-.SH SYNOPSIS
-\fBfmt\fP [\-\fIwidth\fP] [\fIfiles\fP]...
-.SH DESCRIPTION
-\fIfmt\fR is a simple text formatter.
-It inserts or deletes newlines, as necessary, to make all lines in a
-paragraph be approximately the same width.
-It preserves indentation and word spacing.
-.PP
-The default line width is 72 characters.
-You can override this with the \-\fIwidth\fR flag.
-If you don't name any files on the command line,
-then \fIfmt\fR will read from stdin.
-.PP
-It is typically used from within \fIvi\fR to adjust the line breaks
-in a single paragraph.
-To do this, move the cursor to the top of the paragraph,
-type "!}fmt", and
-hit <Return>.
-.SH AUTHOR
-.nf
-Steve Kirkendall
-kirkenda@cs.pdx.edu
-.fi
diff --git a/man/man1/ref.1 b/man/man1/ref.1
deleted file mode 100644 (file)
index e7d2e17..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-.TH REF 1
-.SH NAME
-ref - Display a C function header
-.SH SYNOPSIS
-\fBref\fR [-t] [-c \fIclass\fR]... [-f \fIfile\fR]... \fItag\fR
-.SH DESCRIPTION
-\fIref\fP quickly locates and displays the header of a function.
-To do this, \fIref\fR
-looks in the "tags" file for the line that describes the function, and then 
-scans the source file for the function.
-When it locates the function, it displays an introductory comment
-(if there is one), the function's declaration, and the declarations of all
-arguments.
-.SH "SEARCH METHOD"
-.PP
-\fIref\fR uses a fairly sophisticated tag look-up algorithm.
-If you supply a filename via \fB-f\fR \fIfile\fR, then elvis first scans
-the tags file for a static tag from that file.
-This search is limited to the tags file in the current directory.
-.PP
-If you supply a classname via \fB-c\fR \fIclass\fR, then elvis searches
-for a tag from that class.
-This search is not limited to the current directory;
-You can supply a list of directories in the environment variable \fITAGPATH\fR,
-and \fIref\fR will search through the "tags" file in each directory until it finds
-a tag in the desired class.
-.PP
-If that fails, \fIref\fR will then try to look up an ordinary global tag.
-This search checks all of the directories listed in \fITAGPATH\fR, too.
-.PP
-If you've given the \fB-t\fR flag, then \fIref\fR will simply output the tag line that
-it found, and then exit.
-Without \fB-t\fR, though, \fIref\fR will search for the tag line.
-It will try to open the source file, which should be in the same directory
-as the tags file where the tag was discovered.
-If the source file doesn't exist, or is unreadable, then \fIref\fR will try to open
-a file called "\fIrefs\fR" in that directory.
-Either way, \fIref\fR will try to locate the tag, and display whatever it finds.
-.SH "INTERACTION WITH ELVIS"
-.PP
-\fIref\fP is used by \fIelvis\fR' shift-K command.
-If the cursor is located on a word such as "splat", in the file "foo.c",
-then \fIelvis\fR will invoke \fIref\fR with the command "ref -f foo.c splat".
-.PP
-If \fIelvis\fR has been compiled with the -DEXTERNAL_TAGS flag, then \fIelvis\fR will
-use \fIref\fR \fB\fRto scan the tags files.
-This is slower than the built-in tag searching, but it allows \fIelvis\fR to access
-the more sophisticated tag lookup provided by \fIref\fR.
-Other than that, external tags should act exactly like internal tags.
-.SH OPTIONS
-.IP \fB-t\fR
-Output tag info, instead of the function header.
-.IP "\fB-f\fR \fIfile\fR"
-The tag might be a static function in \fIfile\fR.
-You can use several -f flags to have \fIref\fR consider static tags from more than one file.
-.IP "\fB-c\fR \fIclass\fR"
-The tag might be a member of class \fIclass\fR.
-You can use several -c flags to have \fIref\fR consider tags from more than one class.
-.SH FILES
-.IP \fBtags\fR
-List of function names and their locations, generated by \fIctags\fR.
-.IP \fBrefs\fR
-Function headers extracted from source files (optional).
-.SH ENVIRONMENT
-.IP \fBTAGPATH\fR
-List of directories to be searched.
-The elements in the list are separated by either
-semicolons (for MS-DOS, Atari TOS, and AmigaDos), or
-by colons (every other operating system).
-For each operating system, \fIref\fR has a built-in default which is probably
-adequate.
-.SH NOTES
-.PP
-You might want to generate a "tags" file the directory that contains the
-source code for standard C library on your system.
-If licensing restrictions prevent you from making the library source readable
-by everybody, then you can have \fIctags\fR generate a "refs" file,
-and make "refs" readable by everybody.
-.PP
-If your system doesn't come with the library source code, then perhaps you
-can produce something workable from the \fIlint\fR libraries.
-.SH "SEE ALSO"
-elvis(1), ctags(1)
-.SH AUTHOR
-.nf
-Steve Kirkendall
-kirkenda@cs.pdx.edu
-.fi
index a70b7a4346f7d687cabac44e1983b679beac7140..d251e19059c9fed4179e04cf868ab79b8c3fa445 100644 (file)
@@ -1,4 +1,4 @@
-MAN=   awk.1x elvis.1x kermit.1x \
+MAN=   awk.1x kermit.1x \
        macros.1x mined.1x
 
 .include <bsd.man.mk>
diff --git a/man/man1x/elvis.1x b/man/man1x/elvis.1x
deleted file mode 100644 (file)
index 2714692..0000000
+++ /dev/null
@@ -1,1272 +0,0 @@
-.so mnx.mac
-.TH ELVIS 1x
-.CD "elvis \(en clone of the Berkeley vi editor"
-.SX "elvis \fR[\fB\(enRerv\fR] [\fB\(ent \fItag\fR] \fR[\fIfile\fR] ..."
-.TP 5
-.B \(enR
-# Set the read-only option
-.TP 5
-.B \(ene
-# Start up emulating \fIex\fR
-.TP 5
-.B \(enr
-# Tell the user to use \fIelvrec\fR instead
-.TP 5
-.B \(ent
-# Start editing at the given tag
-.TP 5
-.B \(env
-# Start up emulating \fIvi\fR
-.TP 20
-.B elvis
-# Call the editor
-.TP 20
-.B elvis prog.c
-# edit \fIprog.c\fR
-.PP
-\fIElvis\fR is a full-screen editor closely modeled on the famous Berkeley
-\fIvi\fR editor.
-It provides essentially the same interface to the user as \fIvi\fR, but the 
-code is completely new, written from scratch.
-This document provides a brief introduction to \fIvi\fR.
-It is not intended as a tutorial for beginners.
-Most books on
-.Ux
-cover \fIvi\fR.
-.PP
-Like \fIvi\fR, \fIelvis\fR can operate as a screen editor
-(\fIvi\fR mode) or as a line editor (\fIex\fR) mode.  
-It can be called either as \fIelvis\fR \fIvi\fR,or as \fIex\fR, 
-depending on which is desired.
-They are all links to the same file.
-.SS "Vi Commands"
-.PP
-Below is a list of the \fIvi\fR commands supported.
-The following symbols are used in the table:
-.HS
-.in +1.25i
-.ta +1.0i
-.ti -1.0i
-count  Integer parameter telling how many or how much
-.ti -1.0i
-key    One character parameter to the command
-.ti -1.0i
-inp    Interactive input expected
-.ti -1.0i
-mv     Indicates how much for commands like \fIdelete\fR and \fIchange\fR:
-.in +0.8i
-.ta +0.3i
-.ti -0.3i
-(      Previous sentence
-.ti -0.3i
-)      Next sentence
-.ti -0.3i
-{      Previous paragraph
-.ti -0.3i
-}      Next paragraph (delimited by blank line, \fI.PP, .LP, .IP\fR etc.)
-.ti -0.3i
-[      Previous section (delimited by \fI.SH\fR or \fI.NH\fR)
-.br
-A repeated command character means the scope is this line
-.in -0.8i
-.ta +1.0i
-.ti -1.0i
-MOVE   Indicates commands that may also be used where \fImv\fR is specified
-.ti -1.0i
-EDIT   These commands affect text and may be repeated by the \fI.\fR command
-.in -1.25i
-.HS
-In addition to the above notation, the caret (^) is used as an abbreviation
-for CTRL.
-For example, ^A means CTRL-A.
-.HS
-.in +2i
-.ta +1i +1i +3.3i
-.ti -2i
-\fBCount~~~~   Command Description     Type\fR
-.ti -2i
-       ^A      (Not defined)
-.ti -2i
-       ^B      Move toward the top of the file by 1 screenful
-.ti -2i
-       ^C      (Not defined)
-.ti -2i
-count  ^D      Scroll down \fIcount\fR lines (default 1/2 screen)
-.ti -2i
-count  ^E      Scroll up \fIcount\fR lines
-.ti -2i
-       ^F      Move toward the bottom of the file by 1 screenful
-.ti -2i
-       ^G      Show file status, and the current line 
-.ti -2i
-count  ^H      Move left, like \fIh\fR MOVE
-.ti -2i
-       ^I      (Not defined)
-.ti -2i
-count  ^J      Move down       MOVE
-.ti -2i
-       ^K      (Not defined)
-.ti -2i
-       ^l      Redraw the screen
-.ti -2i
-count  ^M      Move to the front of the next line      MOVE
-.ti -2i
-count  ^N      Move down       MOVE
-.ti -2i
-       ^O      (Not defined)
-.ti -2i
-count  ^P      Move up MOVE
-.ti -2i
-       ^Q      (Not defined)
-.ti -2i
-       ^R      Redraw the screen
-.ti -2i
-       ^S      (Not defined)
-.ti -2i
-       ^T      (Not defined)
-.ti -2i
-count  ^U      Scroll up \fIcount\fR lines (default 1/2 screen)
-.ti -2i
-       ^V      (Not defined)
-.ti -2i
-       ^W      (Not defined)
-.ti -2i
-       ^X      (Not defined)
-.ti -2i
-count  ^Y      Scroll down \fIcount\fR lines
-.ti -2i
-       ^Z      (Not defined)
-.ti -2i
-       ESC     (Not defined)
-.ti -2i
-       ^\e     (Not defined)
-.ti -2i
-       ^]      If the cursor is on a tag name, go to that tag
-.ti -2i
-       ^^      Save this file and edit the previous file
-.ti -2i
-       ^_      (Not defined)
-.ti -2i
-count  SPACE   Move right,like \fIl\fR MOVE
-.ti -2i
-       ! mv    Run the selected lines thru an external filter program
-.ti -2i
-       " key   Select which cut buffer to use next
-.ti -2i
-       #       (Not defined)
-.ti -2i
-       $       Move to the rear of the current line    MOVE
-.ti -2i
-       %       move to the matching (){}[] character   MOVE
-.ti -2i
-       &       (Not defined)
-.ti -2i
-       ' key   Move to a marked line   MOVE
-.ti -2i
-count  (       Move backward \fIcount\fR sentences     MOVE
-.ti -2i
-count  )       Move forward \fIcount\fR sentences      MOVE
-.ti -2i
-       *       (Not defined)
-.ti -2i
-count  +       Move to the front of the next line      MOVE
-.ti -2i
-count  ,       Repeat the previous [\fIfFtT\fR] but the other way      MOVE
-.ti -2i
-count  \(en    Move to the front of the preceding line MOVE
-.ti -2i
-       .       Repeat the previous \*(OQedit\*(CQ command
-.ti -2i
-        /      Text search forward for a given regular expr    MOVE
-.ti -2i
-       0       If not part of count, move to 1st char of this line     MOVE
-.ti -2i
-       1       Part of count
-.ti -2i
-       2       Part of count
-.ti -2i
-       3       Part of count
-.ti -2i
-       4       Part of count
-.ti -2i
-       5       Part of count
-.ti -2i
-       6       Part of count
-.ti -2i
-       7       Part of count
-.ti -2i
-       8       Part of count
-.ti -2i
-       9       Part of count
-.ti -2i
-       :       Text. Run single \fIex\fR cmd
-.ti -2i
-count  ;       Repeat the previous [fFtT] cmd  MOVE
-.ti -2i
-count  < mv    Shift text left EDIT
-.ti -2i
-       =       (Not defined)
-.ti -2i
-count  > mv    Shift text right        EDIT
-.ti -2i
-       ? text  Search backward for a given regular expression  MOVE
-.ti -2i
-       @       (Not defined)
-.ti -2i
-count  A inp   Append at end of the line       EDIT
-.ti -2i
-count  B       Move back Word  MOVE
-.ti -2i
-       C inp   Change text from cursor through end of line     EDIT
-.ti -2i
-       D       Delete text from  cursor through end of line    EDIT
-.ti -2i
-count  E       Move end of Word        MOVE
-.ti -2i
-count  F key   Move leftward to a given character      MOVE
-.ti -2i
-count  G       Move to line #\fIcount\fR (default is the bottom line)  MOVE
-.ti -2i
-count  H       Move to home row (the line at the top of the screen)
-.ti -2i
-count  I inp   Insert at the front of the line (after indents) EDIT
-.ti -2i
-count  J       Join lines, to form one big line        EDIT
-.ti -2i
-       K       Look up keyword
-.ti -2i
-count  L       Move to last row (the line at the bottom of the screen)
-.ti -2i
-       M       Move to middle row (the line in the middle)
-.ti -2i
-       N       Repeat previous search, but the opposite way    MOVE
-.ti -2i
-count  O inp   Open up a new line above the current line       EDIT
-.ti -2i
-       P       Paste text before the cursor
-.ti -2i
-       Q       Quit to EX mode
-.ti -2i
-       R inp   Overtype        EDIT
-.ti -2i
-count  S inp   Change lines, like \fIcount\fRcc
-.ti -2i
-count  T key   Move leftward \fIalmost\fR to a given character MOVE
-.ti -2i
-       U       Undo all recent changes to the current line
-.ti -2i
-       V       (Not defined)
-.ti -2i
-count  W       Move forward \fIcount\fR Words  MOVE
-.ti -2i
-count  X       Delete the character(s) to the left of the cursor       EDIT
-.ti -2i
-count  Y       Yank text line(s) (copy them into a cut buffer)
-.ti -2i
-       Z Z     Save the file & exit
-.ti -2i
-       [ [     Move back 1 section     MOVE
-.ti -2i
-       \e      (Not defined)
-.ti -2i
-       ] ]     Move forward 1 section                                  MOVE
-.ti -2i
-       ^       Move to the front of the current line (after indent)    MOVE
-.ti -2i
-       \(ul    (Not defined)
-.ti -2i
-       ` key   Move to a marked character      MOVE
-.ti -2i
-count  a inp   Insert text after the cursor    EDIT
-.ti -2i
-count  b       Move back \fIcount\fR words     MOVE
-.ti -2i
-       c mv    Change text     EDIT
-.ti -2i
-       d mv    Delete text     EDIT
-.ti -2i
-count  e       Move forward to the end of the current word     MOVE
-.ti -2i
-count  f key   Move rightward to a given character     MOVE
-.ti -2i
-       g       (Not defined)
-.ti -2i
-count  h       Move left       MOVE
-.ti -2i
-count  i inp   Insert text at the cursor       EDIT
-.ti -2i
-count  j       Move down       MOVE
-.ti -2i
-count  k       Move up MOVE
-.ti -2i
-count  l       Move right      MOVE
-.ti -2i
-       m key   Mark a line or character
-.ti -2i
-       n       Repeat the previous search      MOVE
-.ti -2i
-count  o inp   Open a new line below the current line  EDIT
-.ti -2i
-       p       Paste text after the cursor
-.ti -2i
-       q       (Not defined)
-.ti -2i
-count  r key   Replace \fIcount\fR chars by a given character  EDIT
-.ti -2i
-count  s inp   Replace \fIcount\fR chars with text from the user       EDIT
-.ti -2i
-count  t key   Move rightward \fIalmost\fR to a given character        MOVE
-.ti -2i
-       u       Undo the previous edit command
-.ti -2i
-       v       (Not defined)
-.ti -2i
-count  w       Move forward \fIcount\fR words  MOVE
-.ti -2i
-count  x       Delete the character that the cursor's on       EDIT
-.ti -2i
-       y mv    Yank text (copy it into a cut buffer)
-.ti -2i
-       z key   Scroll current line to the screen's +=top -=bottom .=middle
-.ti -2i
-count  {       Move back \fIcount\fR paragraphs        MOVE
-.ti -2i
-count  |       Move to column \fIcount\fR (the leftmost column is 1)
-.ti -2i
-count  }       Move forward \fIcount\fR paragraphs     MOVE
-.ti -2i
-.tr ~~
-count  \(ap    Switch a character between upper & lower case   EDIT
-.tr ~
-.ti -2i
-       DEL     (Not defined)
-.in -2i
-.SS "Ex Commands"
-.PP
-Below is a list of the \fIex\fR commands supported.  All can be abbreviated.
-.UU "General"
-.LP
-.nf
-.ta 1.2i 2.4i
-[line] append
-       args    [files]
-       cd      [directory]
-       chdir   [directory]
-[line][,line]  change
-[line][,line]  copy    line
-[line][,line]  debug[!]
-[line][,line]  Delete  [\*(CQx]
-       edit[!] [file]
-       ex[!]   [file]
-       file
-[line][,line]  global  /regexp/ command
-[line] Insert
-[line][,line]  join
-[line][,line]  list
-       map[!]  key mapped_to
-[line] mark    x
-       mkexrc
-[line][,line]  Move    line
-       next[!] [files]
-       Next[!]
-       previous[!]
-[line][,line]  print
-[line] put     [\*(CQx]
-       quit[!]
-[line] read    file
-       rewind[!]
-       set     [options]
-[line][,line]  substitute      /regexp/replacement/[p][g]
-       tag[!]  tagname
-[line][,line]  to      line
-       Undo
-       unmap[!]        key
-       validate[!]
-       version
-[line][,line]  vglobal /regexp/ command
-       visual
-       wq
-[line][,line]  write[!]        [[>>]file]
-       xit[!]
-[line][,line]  yank    [\*(CQx]
-[line][,line]  !       command
-[line][,line]  <
-[line][,line]  =
-[line][,line]  >
-.SP 0.25
-.UU "Text Entry"
-.SP 0.25
-.LP
-.ta 1.2i 2.4i
-.nf
-[line] append
-[line][,line]  change [\*(CQx]
-[line] Insert
-.fi
-
-The (a)ppend command inserts text after the specified line.
-
-The (i)nsert command inserts text before the specified line.
-
-The (c)hange command copies the range of lines into a cut buffer,
-deletes them, and inserts new text where the old text used to be.
-
-For all of these commands, you indicate the end of the text you're
-inserting by hitting ^D or by entering a line which contains only
-a period.
-.SP 0.25
-.UU "Cut & Paste"
-.SP 0.25
-.LP
-.ta 1.2i 2.4i
-.nf
-[line][,line]  Delete [\*(CQx]
-[line][,line]  yank [\*(CQx]
-[line] put[!] [\*(CQx]
-[line][,line]  copy line
-[line][,line]  to line
-[line][,line]  Move line
-
-.fi
-The (d)elete command copies the specified range of lines into a
-cut buffer, and then deletes them.
-
-The (y)ank command copies the specified range of lines into a cut
-buffer, but does \fInot\fR delete them.
-
-The (pu)t command inserts text from a cut buffer after the specified
-line\(emor before it if the ! is present.
-
-The (co)py and (t)o commands yank the specified range of lines and then
-immediately paste them after some other line.
-
-The (m)ove command deletes the specified range of lines and then
-immediately pastes them after some other line.  If the destination
-line comes after the deleted text, then it will be adjusted
-automatically to account for the deleted lines.
-.UU "Displaying Text"
-.LP
-.ta 1.2i 2.4i
-.nf
-[line][,line]  print
-[line][,line]  list
-
-.fi
-The (p)rint command displays the specified range of lines.
-
-The (l)ist command also displays them, but it is careful to make
-control characters visible.
-.UU "Global Operations"
-.LP
-.ta 1.2i 2.4i
-.nf
-[line][,line]  global /regexp/ command
-[line][,line]  vglobal /regexp/ command
-
-.fi
-The (g)lobal command searches through the lines of the specified range
-(or through the whole file if no range is specified) for lines that
-contain a given regular expression.  It then moves the cursor to each
-of these lines and runs some other command on them.
-
-The (v)global command is similar, but it searches for lines that
-\fIdo not\fR contain the regular expression.
-.UU "Line Editing"
-.LP
-.ta 1.2i 2.4i
-.nf
-[line][,line]  join
-[line][,line]  ! program
-[line][,line]  <
-[line][,line]  >
-[line][,line]  substitute /regexp/replacement/[p][g]
-
-.fi
-The (j)oin command concatenates all lines in the specified range together
-to form one big line.  If only a single line is specified, then the
-following line is catenated onto it.
-
-The ! command runs an external filter program, and feeds the specified
-range of lines to it's stdin.  The lines are then replaced by the
-output of the filter.  A typical example would be \*(OQ:'a,'z!sort -n\*(CQ to
-sort the lines 'a,'z according to their numeric values.
-
-The < and > commands shift the specified range of lines left or right,
-normally by the width of 1 tab character.  The \*(OQshiftwidth\*(CQ option
-determines the shifting amount.
-
-The (s)ubstitute command finds the regular expression in each line,
-and replaces it with the replacement text.  The \*(OQp\*(CQ option causes
-the altered lines to be printed, and the \*(OQg\*(CQ option permits all
-instances of the regular expression to be found & replaced.  (Without
-\*(OQg\*(CQ, only the first occurrence is replaced.)
-.SP 0.25
-.UU "Undo"
-.SP 0.25
-.LP
-.ta 1.2i 2.4i
-.nf
-       undo
-
-.fi
-The (u)ndo command restores the file to the state it was in before your
-most recent command which changed text.
-.SP 0.25
-.UU "Configuration & Status"
-.SP 0.25
-.LP
-.ta 1.2i 2.4i
-.nf
-       map[!] [key mapped_to]
-       unmap[!] key
-       set [options]
-       mkexrc
-[line] mark x
-       visual
-       version
-[line][,line]  =
-       file
-
-.fi
-The (ma)p command allows you to configure \fIelvis\fR to recognize your
-function keys, and treat them as though they transmitted some other
-sequence of characters.  Normally this mapping is done only when in
-the visual command mode, but with the [!]      present it will map keys
-under all contexts.  When this command is given with no arguments,
-it prints a table showing all mappings currently in effect.  When
-called with two arguments, the first is the sequence that your
-function key really sends, and the second is the sequence that you
-want \fIelvis\fR to treat it as having sent.
-
-The (unm)ap command removes key definitions that were made via the
-map command.
-
-The (se)t command allows you examine or set various options.  With
-no arguments, it displays the values of options that have been
-changed.  With the single argument \*(OQall\*(CQ it displays the values of
-all options, regardless of whether they've been explicitly set or
-not.  Otherwise, the arguments are treated as options to be set.
-
-The (mk)exrc command saves the current configuration to a file
-called \fI.exrc\fR in the current directory.
-
-The mar(k) command defines a named mark to refer to a specific place
-in the file.  This mark may be used later to specify lines for other
-commands.
-
-The (vi)sual command puts the editor into visual mode.  Instead of
-emulating ex, \fIelvis\fR will start emulating vi.
-
-The (ve)rsion command tells you that what version of \fIelvis\fR this is.
-
-The = command tells you what line you specified, or, if you specified
-a range of lines, it will tell you both endpoints and the number of
-lines included in the range.
-
-The file command tells you the name of the file, whether it has been
-modified, the number of lines in the file, and the current line number.
-.UU "Multiple Files"
-.LP
-.ta 1.2i 2.4i
-.nf
-       args [files]
-       next[!] [files]
-       Next[!]
-       previous[!]
-       rewind[!]
-
-.fi
-When you invoke \fIelvis\fR from your shell's command line, any filenames
-that you give to \fIelvis\fR as arguments are stored in the args list.  The
-(ar)gs command will display this list, or define a new one.
-
-The (n)ext command switches from the current file to the next one in
-the args list.  You may specify a new args list here, too.
-
-The (N)ext and (pre)vious commands (they're really aliases for the same
-command) switch from the current file to the preceding file in the
-args list.
-
-The (rew)ind command switches from the current file to the first file
-in the args list.
-.SP 1
-.UU "Switching Files"
-.SP 1
-.LP
-.ta 1.2i 2.4i
-.nf
-       edit[!] [file]
-       tag[!] tagname
-
-.fi
-The (e)dit command allows to switch from the current file to some other
-file.  This has nothing to do with the args list, by the way.
-
-The (ta)g command looks up a given tagname in a file called \*(OQtags".
-This tells it which file the tag is in, and how to find it in that file.
-\fIElvis\fR then switches to the tag's file and finds the tag.
-.SP 1
-.UU "Exiting"
-.SP 1
-.LP
-.ta 1.2i 2.4i
-.nf
-       quit[!]
-       wq
-       xit
-
-.fi
-The (q)uit command exits from the editor without saving your file.
-
-The (wq) and (x)it commands (really two names for the same command)
-both write the file before exiting.
-.UU "File I/O"
-.LP
-.ta 1.2i 2.4i
-.nf
-[line] read file
-[line][,line]  write[!][[>>]file]
-
-.fi
-The (r)ead command gets text from another file and inserts it after
-the specified line.
-
-.fi
-The (w)rite command writes the whole file, or just part of it, to
-some other file.  The !, if present, will permit the lines to be
-written even if you've set the readonly option.  If you precede the
-filename by >> then the lies will be appended to the file.
-.UU "Directory"
-.LP
-.ta 1.2i 2.4i
-.nf
-       cd [directory]
-       chdir [directory]
-       shell
-
-.fi
-The (cd) and (chd)ir commands (really two names for one command)
-switch the current working directory.
-
-The (sh)ell command starts an interactive shell.
-.SP 0.5
-.UU "Debugging"
-.SP 0.5
-.LP
-.ta 1.2i 2.4i
-.nf
-[line][,line]  debug[!]
-       validate[!]
-
-.fi
-These commands are only available if you compile \fIelvis\fR with the
-\fB-DDEBUG\fR flag.
-
-The de(b)ug command lists stats for the blocks which contain the
-specified range of lines.  If the ! is present, then the contents
-of those blocks is displayed, too.
-
-The (va)lidate command checks certain variables for internal
-consistency.  Normally it does not output anything unless it detects
-a problem.  With the !, though, it will always produce *some*
-output.
-.SP 0.5
-.SS "Extensions"
-.SP 0.5
-.PP.
-.ta 1i
-.in +0.25i
-In addition to the standard commands, a variety of extra features are
-present in \fIelvis\fR that are not present in \fIvi\fR.
-They are described below.
-
-.ti -0.25i
-.B .exrc
-.br
-\fIElvis\fR first runs a \fI.exrc\fR file (if there is one) from your $HOME
-directory. After that, it runs a \fI.exrc\fR (if there is one) from the
-current directory.  The one in the current directory may override
-settings made by the one in the $HOME directory.
-
-.ti -0.25i
-.B :mkexrc
-.ti -0.25i
-.B :mk
-.br
-This EX command saves the current :set and :map configurations in
-the \*(OQ.exrc\*(CQ file in your current directory.
-
-.ti -0.25i
-.B :args
-.ti -0.25i
-.B :ar
-.br
-You can use the :args command to define a new args list, as in:
-
-       :args *.h
-
-After you have defined a new args list, the next time you issue a
-:next command \fIelvis\fR will switch to the first file of the new list.
-
-.ti -0.25i
-.B :Next
-.ti -0.25i
-.B :previous
-.ti -0.25i
-.B :N
-.ti -0.25i
-.B :pre
-.br
-These commands move backwards through the args list.
-
-.ti -0.25i
-.B zz
-.br
-In VI, the (lowercase) \*(OQzz\*(CQ command will center the current line on
-the screen, like \*(OQz="
-
-.ti -0.25i
-.B .
-.br
-The default count value for . is the same as the previous command
-which . is meant to repeat.  However, you can supply a new count
-if you wish.  
-For example, after \*(OQ3dw\*(CQ, \*(OQ.\*(CQ will delete 3 words,
-but \*(OQ5.\*(CQ will delete 5 words.
-
-.ti -0.25i
-\fB"\fR
-.br
-The text which was most recently input (via a \*(OQcw\*(CQ command, or
-something similar) is saved in a cut buffer called ". (which is a
-pretty hard name to write in an English sentence).  You can use this
-with the \*(OQp\*(CQ or \*(OQP\*(CQ commands thusly:
-.HS
-       ".p
-.HS
-.ti -0.25i
-.B K
-.br
-You can move the cursor onto a word and press shift-K to have \fIelvis\fR
-run a reference program to look that word up.  This command alone is
-worth the price of admission!  See the ctags and ref programs.
-
-.ti -0.25i
-.B input
-.br
-You can backspace back past the beginning of the line.
-If you type CTRL-A, then the text that you input last time is
-inserted.  You will remain in input mode, so you can backspace over
-part of it, or add more to it.  (This is sort of like CTRL-@ on
-the real vi, except that CTRL-A really works.)
-
-Real \fIvi\fR can only remember up to 128 characters of input, but \fIelvis\fR
-can remember any amount.
-
-.ti -0.25i
-.B :set
-charattr
-.ti -0.25i
-.B :se
-ca
-.br
-\fIElvis\fR can display \*(OQbackslash-f\*(CQ style character attributes on the
-screen as you edit.  The following example shows the recognized
-attributes:
-
-       normal \fBboldface\fR \fIitalics\fR 
-
-NOTE: you must compile \fIelvis\fR without the \(enDSET_NOCHARATTR flag for
-this to work.
-.in -0.25i
-.SS "Omissions"
-.PP
-A few \fIvi\fR features are missing.
-The replace mode is a hack.  It does not save the text that it overwrites.
-.PP
-Long lines are displayed differently\(emwhere the real vi would wrap a long
-line onto several rows of the screen, \fIelvis\fR simply displays part of the line,
-and allows you to scroll the screen sideways to see the rest of it.
-.PP
-The \*(OQ:preserve\*(CQ and \*(OQ:recover\*(CQ commands are missing, as 
-is the \fB\(enr\fR flag.
-\*(OQ:Preserve" is practically never used and since use of \*(OQ:recover\\*(CQ
-is so rare, it was decided to implement it as a separate program.  There's no
-need to load the recovery code into memory every time you edit a file.
-.PP
-LISP support is missing.
-The \*(OQ@\*(CQ and \*(OQ:@\*(CQ commands are missing.
-You cannot APPEND to a cut buffer.
-.SS "Options"
-.PP
-A variety of options can be set as described below:
-.HS
-.nf
-.in +0.25i
-.ta 0.9i 1.35i 2.1i 3.0i
-\fBName        Abbr    Type    Default Description\fR
-autoindent     as      Bool    FALSE   autoindent during input?
-autowrite      aw      Bool    FALSE   write file for :n command?
-charattr       ca      Bool    FALSE   display bold & underline chars?
-columns        co      Number  80      width of screen, in characters
-directory      dir     String  /usr/tmp        where tmp files are kept
-errorbells     eb      Bool    TRUE    ring bell on error?
-exrefresh      er      Bool    TRUE    EX mode calls write() often?
-ignorecase     ic      Bool    FALSE   searches: upper/lowercase OK?
-keytime        kt      Number  1       allow slow receipt of ESC seq?
-keywordprg     kp      String  /usr/bin/ref    program to run for shift-K
-lines  ln      Number  25      height of screen, in lines
-list   li      Bool    FALSE   show tabs as \*(OQ^I\*(CQ?
-magic  ma      Bool    TRUE    searches: allow metacharacters?
-paragraphs     pa      String  PPppPApa        paragraphs start with .PP, etc.
-readonly       ro      Bool    FALSE   no file should be written back?
-report re      Number  5       report changes to X lines?
-scroll sc      Number  12      default #lines for ^U and ^D
-sections       se      String  SEseSHsh        sections start with .SE, etc.
-shell  sh      String  \fI/bin/sh\fR   shell program, from environment
-shiftwidth     sw      Number  8       width of < or > commands
-sidescroll     ss      Number  8       #chars to scroll sideways by
-sync   sy      Bool    FALSE   call sync() after each change?
-tabstop        ts      Number  8       width of a tab character
-term   te      String  "?"     terminal type, from environment
-vbell  vb      Bool    TRUE    use visible bell if possible?
-warn   wa      Bool    TRUE    warn if file not saved for :!cmd
-wrapmargin     wm      Number  0       Insert newline after which col?
-wrapscan       ws      Bool    TRUE    searches: wrap at EOF?
-
-.fi
-.ti -0.25i
-.B autoindent
-.br
-During input mode, the autoindent option will cause each added line
-to begin with the same amount of leading whitespace as the line above
-it.  Without autoindent, added lines are initially empty.
-
-.ti -0.25i
-.B autowrite
-.br
-When you're editing one file and decide to switch to another\(emvia
-the :tag command, or :next command, perhaps\(emif your current
-file has been modified, then \fIelvis\fR will normally print an error
-message and refuse to switch.
-
-However, if the autowrite option is on, then \fIelvis\fR will write the
-modified version of the current file and successfully switch to the
-new file.
-
-.ti -0.25i
-.B charattr
-.br
-Many text formatting programs allow you to designate portions of
-your text to be underlined, italicized, or boldface by embedding
-the special strings \\fU, \\fI, and \\fB in your text.  The special
-string \\fR marks the end of underlined or boldface text.
-
-\fIElvis\fR normally treats those special strings just like any other
-text.
-However, if the \fIcharattr\fR option is on, then \fIelvis\fR will interpret
-those special strings correctly, to display underlined or boldface
-text on the screen.  (This only works, of course, if your terminal
-can display underlined and boldface, and if the TERMCAP entry says
-how to do it.)
-
-.ti -0.25i
-.B columns
-.br
-This is a \*(OQread only\*(CQ option.  You cannot change its value, but you
-can have \fIelvis\fR print it.  It shows how wide your screen is.
-
-.ti -0.25i
-.B directory
-.br
-Elvis uses temporary files to store changed text.
-This option allows you to control where those temporary files will be.
-Ideally, you should store them on in fast non-volatile memory,
-such as a hard disk.
-
-This option can only be set in the ".exrc" file.
-
-.ti -0.25i
-.B errorbells
-.br
-Normally, \fIelvis\fR will ring your terminal's bell if you make an error.
-However, in noerrorbells mode, your terminal will remain silent.
-
-.ti -0.25i
-.B exrefresh
-.br
-The EX mode of \fIelvis\fR writes many lines to the screen.  You can make
-\fIelvis\fR either write each line to the screen separately, or save up
-many lines and write them all at once.
-
-The exrefresh option is normally on, so each line is written to the
-screen separately.
-
-You may wish to turn the exrefresh option off (:se noer) if the
-\*(OQwrite\*(CQ system call is costly on your machine, or if you're using a
-windowing environment.  (Windowing environments scroll text a lot
-faster when you write many lines at once.)
-
-This option has no effect in \fIvi\fR mode.
-
-.ti -0.25i
-.B ignorecase
-.br
-Normally, when \fIelvis\fR searches for text, it treats uppercase letters
-as being different for lowercase letters.
-
-When the ignorecase option is on, uppercase and lowercase are treated
-as equal.
-
-.ti -0.25i
-.B keytime
-.br
-The arrow keys of most terminals send a multi-character sequence.
-It takes a measurable amount of time for these sequences to be
-transmitted.  The keytime option allows you to control the maximum
-amount of time to allow for an arrow key (or other mapped key) to
-be received in full.
-
-The default keytime value is 2.  Because of the way 
-.Ux
-timekeeping works, the actual amount of time allowed will vary slightly, but it
-will always be between 1 and 2 seconds.
-
-If you set keytime to 1, then the actual amount of time allowed will
-be between 0 and 1 second.  This will generally make the keyboard's
-response be a little faster (mostly for the ESC key), but on those
-occasions where the time allowed happens to be closer to 0 than 1
-second, \fIelvis\fR may fail to allow enough time for an arrow key's
-sequence to be received fully.  Ugh.
-
-As a special case, you can set keytime to 0 to disable this time
-limit stuff altogether.  The big problem here is:  If your arrow
-keys' sequences start with an ESC, then every time you hit your ESC
-key \fIelvis\fR will wait... and wait... to see if maybe that ESC was
-part of an arrow key's sequence.
-
-NOTE: this option is a generalization of the timeout option of the
-real vi.
-
-.ti -0.25i
-.B keywordprg
-.br
-\fIElvis\fR has a special keyword lookup feature.  You move the cursor
-onto a word, and hit shift-K, and \fIelvis\fR uses another program to
-look up the word and display information about it.
-
-This option says which program gets run.  It should contain the full
-pathname of the program; your whole execution path is \fInot\fR checked.
-
-The default value of this option is \fI/usr/bin/ref\fR, which is a
-program that looks up the definition of a function in C.  It looks
-up the function name in a file called \*(OQrefs\*(CQ which is created by
-ctags.
-
-You can substitute other programs, such as an English dictionary
-program or the online manual.  \fIelvis\fR runs the program, using the
-keyword as its only argument.  The program should write information
-to stdout.  The program's exit status should be 0, unless you want
-\fIelvis\fR to print \*(OQ<<< failed >>>".
-
-.ti -0.25i
-.B lines
-.br
-This \*(OQread only\*(CQ option shows how many lines you screen has.
-
-.ti -0.25i
-.B list
-.br
-Normally (in \*(OQnolist" mode) \fIelvis\fR will expand tabs to the proper
-number of spaces on the screen, so that the file appears the same would it would
-be if you printed it or looked at it with \fImore\fR.
-
-Sometimes, though, it can be handy to have the tabs displayed as \*(OQ^I".
-In \*(OQlist" mode, \fIelvis\fR does this, and also displays a \*(OQ$"
-after the end of the line.
-
-.ti -0.25i
-.B magic
-.br
-The search mechanism in \fIelvis\fR can accept \*(OQregular 
-expressions\*(CQ\(emstrings in which certain characters have special meaning.
-The magic option is normally on, which causes these characters to
-be treated specially.
-If you turn the magic option off (:se noma), then all characters
-except ^ and $ are treated literally.   ^ and $ retain their special
-meanings regardless of the setting of magic.
-
-.ti -0.25i
-.B paragraphs
-.br
-The { and } commands move the cursor forward or backward in increments
-of one paragraph.  Paragraphs may be separated by blank lines, or by
-a \*(OQdot\*(CQ command of a text formatter.  Different text formatters use
-different \*(OQdot\*(CQ commands.  This option allows you to configure \fIelvis\fR
-to work with your text formatter.
-
-It is assumed that your formatter uses commands that start with a
-".\*(CQ character at the front of a line, and then have a one- or
-two-character command name.
-
-The value of the paragraphs option is a string in which each pair
-of characters is one possible form of your text formatter's paragraph
-command.
-
-.ti -0.25i
-.B readonly
-.br
-Normally, \fIelvis\fR will let you write back any file to which you have
-write permission.  If you do not have write permission, then you
-can only write the changed version of the file to a \fIdifferent\fR
-file.
-
-If you set the readonly option, then \fIelvis\fR will pretend you do not
-have write permission to \fIany\fR file you edit.  It is useful when
-you really only mean to use \fIelvis\fR to look at a file, not to change
-it.  This way you cannot change it accidentally.
-
-This option is normally off, unless you use the \*(OQview\*(CQ alias of \fIelvis\fR.
-\*(OQView\*(CQ is like \fIvi\fR except that the readonly option is on.
-
-.ti -0.25i
-.B report
-.br
-Commands in \fIelvis\fR may affect many lines.  For commands that affect
-a lot of lines, \fIelvis\fR will output a message saying what was done and
-how many lines were affected.  This option allows you to define
-what \*(OQa lot of lines\*(CQ means.  The default is 5, so any command which
-affects 5 or more lines will cause a message to be shown.
-
-.ti -0.25i
-.B scroll
-.br
-The CTRL-U and CTRL-D keys normally scroll backward or forward
-by half a screenful, but this is adjustable.  The value of this option
-says how many lines those keys should scroll by.
-
-.ti -0.25i
-.B sections
-.br
-The [[ and ]] commands move the cursor backward or forward in
-increment of 1 section.  Sections may be delimited by a { character
-in column 1 (which is useful for C source code) or by means of
-a text formatter's \*(OQdot\*(CQ commands.
-
-This option allows you to configure \fIelvis\fR to work with your text
-formatter's \*(OQsection\*(CQ command, in exactly the same way that the
-paragraphs option makes it work with the formatter's \*(OQparagraphs"
-command.
-
-.ti -0.25i
-.B shell
-.br
-When \fIelvis\fR forks a shell (perhaps for the :! or :shell commands)
-this is the program that is uses as a shell.  This is \fI/bin/sh\fR
-by default, unless you have set the SHELL environment variable,
-it which case the default value is copied from the environment.
-
-.ti -0.25i
-.B shiftwidth
-.br
-The < and > commands shift text left or right by some uniform number
-of columns.  The shiftwidth option defines that uniform number.
-The default is 8.
-
-.ti -0.25i
-.B sidescroll
-.br
-For long lines, \fIelvis\fR scrolls sideways.  (This is different from
-the real \fIvi\fR, which wraps a single long line onto several rows of
-the screen.)
-To minimize the number of scrolls needed, \fIelvis\fR moves the screen
-sideways by several characters at a time.  The value of this option
-says how many characters' widths to scroll at a time.
-Generally, the faster your screen can be redrawn, the lower the value
-you will want in this option.
-
-.ti -0.25i
-.B sync
-.br
-If the system crashes during an edit session, then most of your work
-can be recovered from the temporary file that \fIelvis\fR uses to store
-changes.  However, sometimes 
-.MX
-will not copy changes to the
-hard disk immediately, so recovery might not be possible.  The [no]sync
-option lets you control this.
-In nosync mode (which is the default), \fIelvis\fR lets the operating system
-control when data is written to the disk.  This is generally faster.
-In sync mode, \fIelvis\fR forces all changes out to disk every time you make
-a change.  This is generally safer, but slower.
-
-.ti -0.25i
-.B tabstop
-.br
-Tab characters are normally 8 characters wide, but you can change
-their widths by means of this option.
-
-.ti -0.25i
-.B term
-.br
-This \*(OQread only\*(CQ option shows the name of the termcap entry that
-\fIelvis\fR is using for your terminal.
-
-.ti -0.25i
-.B vbell
-.br
-If your termcap entry describes a visible alternative to ringing
-your terminal's bell, then this option will say whether the visible
-version gets used or not.  Normally it will be.
-
-If your termcap does NOT include a visible bell capability, then
-the vbell option will be off, and you cannot turn it on.
-
-.ti -0.25i
-.B warn
-.br
-\fIElvis\fR will normally warn you if you run a shell command without saving
-your changed version of a file.
-The \*(OQnowarn" option prevents this warning.
-
-.ti -0.25i
-.B wrapmargin
-.br
-Normally (with wrapmargin=0) \fIelvis\fR will let you type in extremely long
-lines, if you wish.
-However, with wrapmargin set to something other that 0 (wrapmargin=65
-is nice), \fIelvis\fR will automatically cause long lines to be \*(OQwrapped"
-on a word break for lines longer than wrapmargin's setting.
-
-.ti -0.25i
-.B wrapscan
-.br
-Normally, when you search for something, \fIelvis\fR will find it no matter
-where it is in the file.  \fIelvis\fR starts at the cursor position, and
-searches forward.  If \fIelvis\fR hits EOF without finding what you're
-looking for, then it wraps around to continue searching from line 1.
-
-If you turn off the wrapscan option (:se nows), then when \fIelvis\fR hits
-EOF during a search, it will stop and say so.
-.in -0.25i
-.SS "Cflags"
-.PP
-\fIElvis\fR uses many preprocessor symbols to control compilation.
-Most of these flags allow you to disable small sets of features.
-\s-2MINIX\s0-ST users will probably want all features enabled, but
-\s-2MINIX\s0-PC users will have to disable one or two feature sets
-because otherwise \fIelvis\fR would be too large to compile and run.
-
-These symbols can be defined via flags passed to the compiler.
-The best way to do this is to edit the Makefile, and append the flag
-to the \*(OQCFLAGS=\*(CQ line.
-After you do that, you must recompile elvis completely by saying
-.HS
-.Cx "make  clean"
-.br
-.Cx "make"
-.HS
-.in +0.25i
-.ti -0.25i
-.B \(enDM_SYSV
-.br
-This flag causes \fIelvis\fR to use System-V ioctl() calls for controlling
-your terminal; normally it uses v7/BSD/\s-2MINIX\s0 ioctl() calls.
-
-.ti -0.25i
-.B \(enDDATE
-.br
-The symbol DATE should be defined to look like a string constant,
-giving the date when \fIelvis\fR was compiled.
-This date is reported by the \*(OQ:version\*(CQ command.
-
-You can also leave DATE undefined, in which case \*(OQ:version\*(CQ will not
-report the compilation date.
-
-.ti -0.25i
-.B \(enDCRUNCH
-.br
-This flag causes several large often-used macros to be replaced by
-equivalent functions.
-This saves about 4K of space in the \*(OQ.text\*(CQ segment, and it does not
-cost you any features.
-
-.ti -0.25i
-.B \(enDDEBUG
-.br
-This adds many internal consistency checks and the \*(OQ:debug\*(CQ 
-and \*(OQ:validate\*(CQ
-commands.  It increases the size of \*(OQtext\*(CQ by about 5K bytes.
-
-.ti -0.25i
-.B \(enDNO_CHARATTR
-.br
-This permanenently disables the \*(OQcharattr\*(CQ option.
-It reduces the size of \*(OQ.text\*(CQ by about 850 bytes.
-
-.ti -0.25i
-.B \(enDNO_RECYCLE
-.br
-Normally, \fIelvis\fR will recycle space in the temporary file which contains
-totally obsolete text.
-The \fB\(enDNO_RECYCLE\fR option disables this, making your \*(OQ.text\*(CQ  segment 
-smaller by about 1K but also permitting the temporary file to grow very 
-quickly.
-If you have less than two megabytes of free space on your disk,
-then do not even consider using this flag.
-
-.ti -0.25i
-.B \(enDNO_SENTENCE
-.br
-This leaves out the \*(OQ(\*(CQ and \*(OQ)\*(CQ visual commands, and 
-removes the code that allows the \*(OQ[[\*(CQ, \*(OQ]]\*(CQ, \*(OQ{\*(CQ, 
-and \*(OQ}\*(CQ commands to recognize \fRnroff\fR macros.
-The \*(OQ[[\*(CQ and \*(OQ]]\*(CQ commands will still move to the start of 
-the previous/next C function source code, though, and \*(OQ{\*(CQ 
-and \*(OQ}\*(CQ will move to the previous/next blank line.
-This saves about 650 bytes from the \*(OQ.text\*(CQ segment.
-
-.ti -0.25i
-.B \(enDNO_CHARSEARCH
-.br
-This leaves out the visual commands which locate a given character in the
-current line: \*(OQf\*(CQ, \*(OQt\*(CQ, \*(OQF\*(CQ, \*(OQT\*(CQ, \*(OQ;\*(CQ, and \*(OQ,\*(CQ.
-This saves about 900 bytes.
-
-.ti -0.25i
-.B \(enDNO_EXTENSIONS
-.br
-This leaves out the \*(OQ:mkexrc\*(CQ command, and the \*(OQK\*(CQ and \*(OQ#\*(CQ visual commands.
-Other extensions are either inherent in the design of \fIelvis\fR,
-or are too tiny to be worth removing.
-This saves about 500 bytes.
-
-.ti -0.25i
-.B \(enDNO_MAGIC
-.br
-This permanently disables the \*(OQmagic\*(CQ option, so that most 
-meta-characters in a regular expression are not recognized.  
-This saves about 3K bytes from the \*(OQ.text\*(CQ segment.
-.HS
-.in -0.25i
-.SS "Termcap"
-\fIElvis\fR can use standard termcap entries,
-but it also recognizes and uses several extra capabilities, if you give them.
-All of these are optional.
-.nf
-.in +0.25i
-.ta 1.5i
-.HS
-\fBCapability  Description\fR
-:PU=:  sequence received from the <PgUp> key
-:PD=:  sequence received from the <PgDn> key
-:HM=:  sequence received from the <Home> key
-:EN=:  sequence received from the <End> key
-:VB=:  sequence sent to start bold printing
-:Vb=:  sequence sent to end bold printing
-.in -0.25i
-.SS "Author"
-.PP
-\fIElvis\fR was written by Steve Kirkendall.
-He can be reached by email at: kirkenda@cs.pdx.edu
-for comments regarding \fIelvis\fR.
index ac6cc6cf20864b41e145f3b5f4789a845832e47b..e07795717669463b4dd4bc12e68d87de41f49a91 100644 (file)
@@ -1,6 +1,6 @@
 MAN=   add_route.8 backup.8 boot.8 btrace.8 \
        cdprobe.8 chown.8 cleantmp.8 config.8 cron.8 \
-       dhcpd.8 diskctl.8 elvprsv.8 fbdctl.8 fdisk.8 fingerd.8 \
+       dhcpd.8 diskctl.8 fbdctl.8 fdisk.8 fingerd.8 \
        getty.8 halt.8 hgfs.8 httpd.8 ifconfig.8 inet.8 init.8 \
        intr.8 irdpd.8 loadramdisk.8 MAKEDEV.8 \
        netconf.8 newroot.8 nonamed.8 \
diff --git a/man/man8/elvprsv.8 b/man/man8/elvprsv.8
deleted file mode 100644 (file)
index 4b1f922..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-.TH ELVPRSV 8
-.SH NAME
-elvprsv - Preserve the the modified version of a file after a crash.
-.SH SYNOPSIS
-.nf
-\fB\fBelvprsv\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
-\fB\fBelvprsv\fP -R /tmp/\fIfilename\fP...
-.fi
-.SH DESCRIPTION
-.PP
-\fIelvprsv\fP preserves your edited text after \fIelvis\fP dies.
-The text can be recovered later, via the \fIelvprsv\fP program.
-.PP
-For UNIX-like systems,
-you should never need to run this program from the command line.
-It is run automatically when \fIelvis\fP is about to die,
-and it should be run (via /etc/rc) when the computer is booted.
-THAT'S ALL!
-.PP
-For non-UNIX systems such as MS-DOS, you can either use \fIelvprsv\fP
-the same way as under UNIX systems (by running it from your AUTOEXEC.BAT file),
-or you can run it separately with the "-R" flag to recover the files
-in one step.
-.PP
-If you're editing a file when \fIelvis\fP dies
-(due to a bug, system crash, power failure, etc.)
-then \fIelvprsv\fP will preserve the most recent version of your text.
-The preserved text is stored in a special directory; it does NOT overwrite
-your text file automatically.
-.PP
-\fIelvprsv\fP will send mail to any user whose work it preserves,
-if your operating system normally supports mail.
-.SH FILES
-.IP /tmp/elv*
-The temporary file that \fIelvis\fP was using when it died.
-.IP /usr/preserve/p*
-The text that is preserved by \fIelvprsv\fP.
-.IP /usr/preserve/Index
-A text file which lists the names of all preserved files, and the names
-of the /usr/preserve/p* files which contain their preserved text.
-.SH BUGS
-.PP
-Due to the permissions on the /usr/preserve directory, on UNIX systems
-\fIelvprsv\fP must be run as superuser.
-This is accomplished by making the \fIelvprsv\fP executable be owned by "root"
-and turning on its "set user id" bit.
-.PP
-If you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvprsv\fP will pretend
-that the file was named "foo".
-.SH AUTHOR
-.nf
-Steve Kirkendall
-kirkenda@cs.pdx.edu
-.fi
index cb1a410cd470635227c5868276ad7a64d16a4e45..efec301e30d2ff7bd827402ebb48cc88a0bec265 100644 (file)
@@ -22,6 +22,7 @@
 2012/10/17 12:00:00,common/lib/libprop
 2009/05/13 02:50:31,common/lib/libutil
 2012/10/17 12:00:00,common/lib/libutil
+2012/10/17 12:00:00,dist/nvi
 2012/08/10 05:22:22,distrib/common
 2012/10/17 12:00:00,distrib/Makefile
 2012/10/17 12:00:00,distrib/Makefile.inc
@@ -58,6 +59,7 @@
 2012/10/17 12:00:00,lib/libc
 2012/10/17 12:00:00,lib/libcrypt
 2012/10/17 12:00:00,lib/libcurses
+2012/10/17 12:00:00,lib/libedit
 2012/10/17 12:00:00,lib/libm
 2011/09/30 22:08:19,lib/libprop
 2012/10/17 12:00:00,lib/libpuffs
 2012/10/17 12:00:00,usr.bin/bzip2recover
 2009/04/11 12:10:02,usr.bin/chpass
 2012/10/17 12:00:00,usr.bin/cksum
+2012/10/17 12:00:00,usr.bin/ctags
 2011/09/01 13:37:33,usr.bin/du
 2012/10/17 12:00:00,usr.bin/genassym
 2012/10/17 12:00:00,usr.bin/gzip
 2010/10/15 05:46:48,usr.bin/mkdep
 2009/08/15 20:44:56,usr.bin/mktemp
 2012/10/17 12:00:00,usr.bin/nbperf
+2012/10/17 12:00:00,usr.bin/nvi
 2010/05/14 17:28:23,usr.bin/newgrp
 2012/10/17 12:00:00,usr.bin/passwd
 2010/02/19 16:35:27,usr.bin/sed
index 53984bb4ce3e7dbe61b41ea7bed35bd4613a2d72..b2b9d85d60e8efe433d4123e88676c64d6c7fa66 100644 (file)
@@ -4,24 +4,33 @@
 .include <bsd.own.mk>
 
 SUBDIR= \
-        \
+       \
        bzip2 bzip2recover \
-        chpass cksum \
-        \
-        du \
+       chpass cksum \
+       ctags \
+       du \
+       \
+       \
        genassym \
        indent join \
        ldd \
        login lorder m4 \
        make man \
        mkdep mktemp \
-       nbperf newgrp \
+       \
+       nbperf newgrp nvi \
        passwd \
+       \
+       \
+       \
        sed seq \
        sort stat su \
        tic \
        tsort \
        uniq \
+       \
+       \
+       \
        xinstall 
 
 .if !defined(__MINIX)
diff --git a/usr.bin/ctags/C.c b/usr.bin/ctags/C.c
new file mode 100644 (file)
index 0000000..9d32b22
--- /dev/null
@@ -0,0 +1,573 @@
+/*     $NetBSD: C.c,v 1.19 2009/07/13 19:05:40 roy Exp $       */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)C.c        8.4 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: C.c,v 1.19 2009/07/13 19:05:40 roy Exp $");
+#endif
+#endif /* not lint */
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static int     func_entry(void);
+static void    hash_entry(void);
+static void    skip_string(int);
+static int     str_entry(int);
+
+/*
+ * c_entries --
+ *     read .c and .h files and call appropriate routines
+ */
+void
+c_entries(void)
+{
+       int     c;                      /* current character */
+       int     level;                  /* brace level */
+       int     token;                  /* if reading a token */
+       int     t_def;                  /* if reading a typedef */
+       int     t_level;                /* typedef's brace level */
+       char    *sp;                    /* buffer pointer */
+       char    tok[MAXTOKEN];          /* token buffer */
+
+       lineftell = ftell(inf);
+       sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1;
+       while (GETC(!=, EOF)) {
+               switch (c) {
+               /*
+                * Here's where it DOESN'T handle: {
+                *      foo(a)
+                *      {
+                *      #ifdef notdef
+                *              }
+                *      #endif
+                *              if (a)
+                *                      puts("hello, world");
+                *      }
+                */
+               case '{':
+                       ++level;
+                       goto endtok;
+               case '}':
+                       /*
+                        * if level goes below zero, try and fix
+                        * it, even though we've already messed up
+                        */
+                       if (--level < 0)
+                               level = 0;
+                       goto endtok;
+
+               case '\n':
+                       SETLINE;
+                       /*
+                        * the above 3 cases are similar in that they
+                        * are special characters that also end tokens.
+                        */
+       endtok:                 if (sp > tok) {
+                               *sp = EOS;
+                               token = YES;
+                               sp = tok;
+                       }
+                       else
+                               token = NO;
+                       continue;
+
+               /*
+                * We ignore quoted strings and character constants
+                * completely.
+                */
+               case '"':
+               case '\'':
+                       (void)skip_string(c);
+                       break;
+
+               /*
+                * comments can be fun; note the state is unchanged after
+                * return, in case we found:
+                *      "foo() XX comment XX { int bar; }"
+                */
+               case '/':
+                       if (GETC(==, '*')) {
+                               skip_comment(c);
+                               continue;
+                       } else if (c == '/') {
+                               skip_comment(c);
+                               continue;
+                       }
+                       (void)ungetc(c, inf);
+                       c = '/';
+                       goto storec;
+
+               /* hash marks flag #define's. */
+               case '#':
+                       if (sp == tok) {
+                               hash_entry();
+                               break;
+                       }
+                       goto storec;
+
+               /*
+                * if we have a current token, parenthesis on
+                * level zero indicates a function.
+                */
+               case '(':
+                       do c = getc(inf);
+                       while (c != EOF && iswhite(c));
+                       if (c == '*')
+                               break;
+                       if (c != EOF)
+                               ungetc(c, inf);
+                       if (!level && token) {
+                               int     curline;
+
+                               if (sp != tok)
+                                       *sp = EOS;
+                               /*
+                                * grab the line immediately, we may
+                                * already be wrong, for example,
+                                *      foo\n
+                                *      (arg1,
+                                */
+                               get_line();
+                               curline = lineno;
+                               if (func_entry()) {
+                                       ++level;
+                                       pfnote(tok, curline);
+                               }
+                               break;
+                       }
+                       goto storec;
+
+               /*
+                * semi-colons indicate the end of a typedef; if we find a
+                * typedef we search for the next semi-colon of the same
+                * level as the typedef.  Ignoring "structs", they are
+                * tricky, since you can find:
+                *
+                *      "typedef long time_t;"
+                *      "typedef unsigned int u_int;"
+                *      "typedef unsigned int u_int [10];"
+                *
+                * If looking at a typedef, we save a copy of the last token
+                * found.  Then, when we find the ';' we take the current
+                * token if it starts with a valid token name, else we take
+                * the one we saved.  There's probably some reasonable
+                * alternative to this...
+                */
+               case ';':
+                       if (t_def && level == t_level) {
+                               t_def = NO;
+                               get_line();
+                               if (sp != tok)
+                                       *sp = EOS;
+                               pfnote(tok, lineno);
+                               break;
+                       }
+                       goto storec;
+
+               /*
+                * store characters until one that can't be part of a token
+                * comes along; check the current token against certain
+                * reserved words.
+                */
+               default:
+       storec:         if (c == EOF)
+                               break;
+                       if (!intoken(c)) {
+                               if (sp == tok)
+                                       break;
+                               *sp = EOS;
+                               if (tflag) {
+                                       /* no typedefs inside typedefs */
+                                       if (!t_def &&
+                                                  !memcmp(tok, "typedef",8)) {
+                                               t_def = YES;
+                                               t_level = level;
+                                               break;
+                                       }
+                                       /* catch "typedef struct" */
+                                       if ((!t_def || t_level <= level)
+                                           && (!memcmp(tok, "struct", 7)
+                                           || !memcmp(tok, "union", 6)
+                                           || !memcmp(tok, "enum", 5))) {
+                                               /*
+                                                * get line immediately;
+                                                * may change before '{'
+                                                */
+                                               get_line();
+                                               if (str_entry(c))
+                                                       ++level;
+                                               break;
+                                               /* } */
+                                       }
+                               }
+                               sp = tok;
+                       }
+                       else if (sp != tok || begtoken(c)) {
+                               if (sp < tok + sizeof tok)
+                                       *sp++ = c;
+                               token = YES;
+                       }
+                       continue;
+               }
+
+               sp = tok;
+               token = NO;
+       }
+}
+
+/*
+ * func_entry --
+ *     handle a function reference
+ */
+static int
+func_entry(void)
+{
+       int     c;                      /* current character */
+       int     level = 0;              /* for matching '()' */
+       static char attribute[] = "__attribute__";
+       char    maybe_attribute[sizeof attribute + 1],
+               *anext;
+
+       /*
+        * Find the end of the assumed function declaration.
+        * Note that ANSI C functions can have type definitions so keep
+        * track of the parentheses nesting level.
+        */
+       while (GETC(!=, EOF)) {
+               switch (c) {
+               case '\'':
+               case '"':
+                       /* skip strings and character constants */
+                       skip_string(c);
+                       break;
+               case '/':
+                       /* skip comments */
+                       if (GETC(==, '*'))
+                               skip_comment(c);
+                       else if (c == '/')
+                               skip_comment(c);
+                       break;
+               case '(':
+                       level++;
+                       break;
+               case ')':
+                       if (level == 0)
+                               goto fnd;
+                       level--;
+                       break;
+               case '\n':
+                       SETLINE;
+               }
+       }
+       return (NO);
+fnd:
+       /*
+        * we assume that the character after a function's right paren
+        * is a token character if it's a function and a non-token
+        * character if it's a declaration.  Comments don't count...
+        */
+       for (anext = maybe_attribute;;) {
+               while (GETC(!=, EOF) && iswhite(c))
+                       if (c == '\n')
+                               SETLINE;
+               if (c == EOF)
+                       return NO;
+               /*
+                * Recognize the gnu __attribute__ extension, which would
+                * otherwise make the heuristic test DTWT
+                */
+               if (anext == maybe_attribute) {
+                       if (intoken(c)) {
+                               *anext++ = c;
+                               continue;
+                       }
+               } else {
+                       if (intoken(c)) {
+                               if (anext - maybe_attribute 
+                                < (ptrdiff_t)(sizeof attribute - 1))
+                                       *anext++ = c;
+                               else    break;
+                               continue;
+                       } else {
+                               *anext++ = '\0';
+                               if (strcmp(maybe_attribute, attribute) == 0) {
+                                       (void)ungetc(c, inf);
+                                       return NO;
+                               }
+                               break;
+                       }
+               }
+               if (intoken(c) || c == '{')
+                       break;
+               if (c == '/' && GETC(==, '*'))
+                       skip_comment(c);
+               else if (c == '/')
+                       skip_comment(c);
+               else {                          /* don't ever "read" '/' */
+                       (void)ungetc(c, inf);
+                       return (NO);
+               }
+       }
+       if (c != '{')
+               (void)skip_key('{');
+       return (YES);
+}
+
+/*
+ * hash_entry --
+ *     handle a line starting with a '#'
+ */
+static void
+hash_entry(void)
+{
+       int     c;                      /* character read */
+       int     curline;                /* line started on */
+       char    *sp;                    /* buffer pointer */
+       char    tok[MAXTOKEN];          /* storage buffer */
+
+       curline = lineno;
+       do if (GETC(==, EOF))
+               return;
+       while(c != '\n' && iswhite(c));
+       ungetc(c, inf);
+       for (sp = tok;;) {              /* get next token */
+               if (GETC(==, EOF))
+                       return;
+               if (iswhite(c))
+                       break;
+               if (sp < tok + sizeof tok)
+                       *sp++ = c;
+       }
+       if(sp >= tok + sizeof tok)
+               --sp;
+       *sp = EOS;
+       if (memcmp(tok, "define", 6))   /* only interested in #define's */
+               goto skip;
+       for (;;) {                      /* this doesn't handle "#define \n" */
+               if (GETC(==, EOF))
+                       return;
+               if (!iswhite(c))
+                       break;
+       }
+       for (sp = tok;;) {              /* get next token */
+               if(sp < tok + sizeof tok)
+                       *sp++ = c;
+               if (GETC(==, EOF))
+                       return;
+               /*
+                * this is where it DOESN'T handle
+                * "#define \n"
+                */
+               if (!intoken(c))
+                       break;
+       }
+       if(sp >= tok + sizeof tok)
+               --sp;
+       *sp = EOS;
+       if (dflag || c == '(') {        /* only want macros */
+               get_line();
+               pfnote(tok, curline);
+       }
+skip:  if (c == '\n') {                /* get rid of rest of define */
+               SETLINE
+               if (*(sp - 1) != '\\')
+                       return;
+       }
+       (void)skip_key('\n');
+}
+
+/*
+ * str_entry --
+ *     handle a struct, union or enum entry
+ */
+static int
+str_entry(int c /* current character */)
+{
+       int     curline;                /* line started on */
+       char    *sp;                    /* buffer pointer */
+       char    tok[LINE_MAX];          /* storage buffer */
+
+       curline = lineno;
+       while (iswhite(c))
+               if (GETC(==, EOF))
+                       return (NO);
+       if (c == '{')           /* it was "struct {" */
+               return (YES);
+       for (sp = tok;;) {              /* get next token */
+               *sp++ = c;
+               if (GETC(==, EOF))
+                       return (NO);
+               if (!intoken(c))
+                       break;
+       }
+       switch (c) {
+               case '{':               /* it was "struct foo{" */
+                       --sp;
+                       break;
+               case '\n':              /* it was "struct foo\n" */
+                       SETLINE;
+                       /*FALLTHROUGH*/
+               default:                /* probably "struct foo " */
+                       while (GETC(!=, EOF))
+                               if (!iswhite(c))
+                                       break;
+                       if (c != '{') {
+                               (void)ungetc(c, inf);
+                               return (NO);
+                       }
+       }
+       *sp = EOS;
+       pfnote(tok, curline);
+       return (YES);
+}
+
+/*
+ * skip_comment --
+ *     skip over comment
+ */
+void
+skip_comment(int commenttype)
+{
+       int     c;                      /* character read */
+       int     star;                   /* '*' flag */
+
+       for (star = 0; GETC(!=, EOF);)
+               switch(c) {
+               /* comments don't nest, nor can they be escaped. */
+               case '*':
+                       star = YES;
+                       break;
+               case '/':
+                       if (commenttype == '*' && star)
+                               return;
+                       break;
+               case '\n':
+                       if (commenttype == '/') {
+                               /*
+                                * we don't really parse C, so sometimes it
+                                * is necessary to see the newline
+                                */
+                               ungetc(c, inf);
+                               return;
+                       }
+                       SETLINE;
+                       /*FALLTHROUGH*/
+               default:
+                       star = NO;
+                       break;
+               }
+}
+
+/*
+ * skip_string --
+ *     skip to the end of a string or character constant.
+ */
+void
+skip_string(int key)
+{
+       int     c,
+               skip;
+
+       for (skip = NO; GETC(!=, EOF); )
+               switch (c) {
+               case '\\':              /* a backslash escapes anything */
+                       skip = !skip;   /* we toggle in case it's "\\" */
+                       break;
+               case '\n':
+                       SETLINE;
+                       /*FALLTHROUGH*/
+               default:
+                       if (c == key && !skip)
+                               return;
+                       skip = NO;
+               }
+}
+
+/*
+ * skip_key --
+ *     skip to next char "key"
+ */
+int
+skip_key(int key)
+{
+       int     c,
+               skip,
+               retval;
+
+       for (skip = retval = NO; GETC(!=, EOF);)
+               switch(c) {
+               case '\\':              /* a backslash escapes anything */
+                       skip = !skip;   /* we toggle in case it's "\\" */
+                       break;
+               case ';':               /* special case for yacc; if one */
+               case '|':               /* of these chars occurs, we may */
+                       retval = YES;   /* have moved out of the rule */
+                       break;          /* not used by C */
+               case '\'':
+               case '"':
+                       /* skip strings and character constants */
+                       skip_string(c);
+                       break;
+               case '/':
+                       /* skip comments */
+                       if (GETC(==, '*')) {
+                               skip_comment(c);
+                               break;
+                       } else if (c == '/') {
+                               skip_comment(c);
+                               break;
+                       }
+                       (void)ungetc(c, inf);
+                       c = '/';
+                       goto norm;
+               case '\n':
+                       SETLINE;
+                       /*FALLTHROUGH*/
+               default:
+               norm:
+                       if (c == key && !skip)
+                               return (retval);
+                       skip = NO;
+               }
+       return (retval);
+}
diff --git a/usr.bin/ctags/Makefile b/usr.bin/ctags/Makefile
new file mode 100644 (file)
index 0000000..5bc61f9
--- /dev/null
@@ -0,0 +1,12 @@
+#      $NetBSD: Makefile,v 1.13 2012/08/10 12:10:27 joerg Exp $
+#      @(#)Makefile    8.1 (Berkeley) 6/6/93
+
+PROG=  ctags
+CPPFLAGS+=-I${.CURDIR}
+SRCS=  C.c ctags.c fortran.c lisp.c print.c tree.c yacc.c
+
+.if !defined(HOSTPROGNAME)
+COPTS.ctags.c+=        -Wno-pointer-sign
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ctags/ctags.1 b/usr.bin/ctags/ctags.1
new file mode 100644 (file)
index 0000000..649ba63
--- /dev/null
@@ -0,0 +1,226 @@
+.\"    $NetBSD: ctags.1,v 1.16 2010/05/14 16:48:36 joerg Exp $
+.\"
+.\" Copyright (c) 1987, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)ctags.1    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt CTAGS 1
+.Os
+.Sh NAME
+.Nm ctags
+.Nd create a tags file
+.Sh SYNOPSIS
+.Nm
+.Op Fl BFadtuwvx
+.Op Fl f Ar tagsfile
+.Ar name ...
+.Sh DESCRIPTION
+.Nm
+makes a tags file for
+.Xr ex 1
+from the specified C,
+Pascal, Fortran,
+.Tn YACC ,
+lex, and lisp sources.
+A tags file gives the locations of specified objects in a group of files.
+Each line of the tags file contains the object name, the file in which it
+is defined, and a search pattern for the object definition, separated by
+white-space.
+Using the
+.Ar tags
+file,
+.Xr ex 1
+can quickly locate these object definitions.
+Depending upon the options provided to
+.Nm ,
+objects will consist of subroutines, typedefs, defines, structs,
+enums and unions.
+.Bl -tag -width Ds
+.It Fl B
+use backward searching patterns
+.Pq Li ?...? .
+.It Fl F
+use forward searching patterns
+.Pq Li /.../
+(the default).
+.It Fl a
+append to
+.Ar tags
+file.
+.It Fl d
+create tags for
+.Li #defines
+that don't take arguments;
+.Li #defines
+that take arguments are tagged automatically.
+.It Fl f
+Places the tag descriptions in a file called
+.Ar tagsfile .
+The default behaviour is to place them in a file called
+.Ar tags .
+.It Fl t
+create tags for typedefs, structs, unions, and enums.
+.It Fl u
+update the specified files in the
+.Ar tags
+file, that is, all
+references to them are deleted, and the new values are appended to the
+file.
+(Beware: this option is implemented in a way which is rather
+slow; it is usually faster to simply rebuild the
+.Ar tags
+file.)
+.It Fl v
+An index of the form expected by
+.Xr vgrind 1
+is produced on the standard output.
+This listing
+contains the object name, file name, and page number (assuming 64
+line pages).
+Since the output will be sorted into lexicographic order,
+it may be desired to run the output through
+.Xr sort 1 .
+Sample use:
+.Bd -literal -offset indent
+ctags \-v files \&| sort \-f \*[Gt] index
+vgrind \-x index
+.Ed
+.It Fl w
+suppress warning diagnostics.
+.It Fl x
+.Nm
+produces a list of object
+names, the line number and file name on which each is defined, as well
+as the text of that line and prints this on the standard output.
+This
+is a simple index which can be printed out as an off-line readable
+function index.
+.El
+.Pp
+Files whose names end in
+.Sq \&.c
+or
+.Sq \&.h
+are assumed to be C
+source files and are searched for C style routine and macro definitions.
+Files whose names end in
+.Sq \&.y
+are assumed to be
+.Tn YACC
+source files.
+Files whose names end in
+.Sq \&.l
+are assumed to be lisp files if their
+first non-blank character is
+.Sq \&; ,
+.Sq \&( ,
+or
+.Sq \&[ ,
+otherwise, they are
+treated as lex files.
+Other files are first examined to see if they
+contain any Pascal or Fortran routine definitions, and, if not, are
+searched for C style definitions.
+.Pp
+The tag
+.Li main
+is treated specially in C programs.
+The tag formed
+is created by prepending
+.Ar M
+to the name of the file, with the
+trailing
+.Sq \&.c
+and any leading pathname components removed.
+This
+makes use of
+.Nm
+practical in directories with more than one
+program.
+.Pp
+Yacc and lex files each have a special tag.
+.Ar Yyparse
+is the start
+of the second section of the yacc file, and
+.Ar yylex
+is the start of
+the second section of the lex file.
+.Sh FILES
+.Bl -tag -width tags -compact
+.It Pa tags
+default output tags file
+.El
+.Sh EXIT STATUS
+.Nm
+exits with a value of 1 if an error occurred, 0 otherwise.
+Duplicate objects are not considered errors.
+.Sh SEE ALSO
+.Xr ex 1 ,
+.Xr vi 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh BUGS
+Recognition of
+.Em functions  ,
+.Em subroutines
+and
+.Em procedures
+for
+.Tn FORTRAN
+and Pascal is done in a very simpleminded way.
+No attempt
+is made to deal with block structure; if you have two Pascal procedures
+in different blocks with the same name you lose.
+.Nm
+doesn't
+understand about Pascal types.
+.Pp
+The method of deciding whether to look for C, Pascal or
+.Tn FORTRAN
+functions is a hack.
+.Pp
+.Nm
+relies on the input being well formed, and any syntactical
+errors will completely confuse it.
+It also finds some legal syntax
+confusing; for example, since it doesn't understand
+.Li #ifdef Ns 's
+(incidentally, that's a feature, not a bug), any code with unbalanced
+braces inside
+.Li #ifdef Ns 's
+will cause it to become somewhat disoriented.
+In a similar fashion, multiple line changes within a definition will
+cause it to enter the last line of the object, rather than the first, as
+the searching pattern.
+The last line of multiple line
+.Li typedef Ns 's
+will similarly be noted.
diff --git a/usr.bin/ctags/ctags.c b/usr.bin/ctags/ctags.c
new file mode 100644 (file)
index 0000000..5054b1b
--- /dev/null
@@ -0,0 +1,275 @@
+/*     $NetBSD: ctags.c,v 1.12 2008/07/21 14:19:22 lukem Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994, 1995\
+ The Regents of the University of California.  All rights reserved.");
+#endif /* not lint */
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)ctags.c    8.4 (Berkeley) 2/7/95";
+#endif
+__RCSID("$NetBSD: ctags.c,v 1.12 2008/07/21 14:19:22 lukem Exp $");
+#endif /* not lint */
+
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ctags.h"
+
+/*
+ * ctags: create a tags file
+ */
+
+NODE   *head;                  /* head of the sorted binary tree */
+
+                               /* boolean "func" (see init()) */
+bool   _wht[256], _etk[256], _itk[256], _btk[256], _gd[256];
+
+FILE   *inf;                   /* ioptr for current input file */
+FILE   *outf;                  /* ioptr for tags file */
+
+long   lineftell;              /* ftell after getc( inf ) == '\n' */
+
+int    lineno;                 /* line number of current line */
+int    dflag;                  /* -d: non-macro defines */
+int    tflag;                  /* -t: create tags for typedefs */
+int    vflag;                  /* -v: vgrind style index output */
+int    wflag;                  /* -w: suppress warnings */
+int    xflag;                  /* -x: cxref style output */
+
+char   *curfile;               /* current input file name */
+char   searchar = '/';         /* use /.../ searches by default */
+char   lbuf[LINE_MAX];
+
+void   init(void);
+void   find_entries(char *);
+
+int
+main(int argc, char **argv)
+{
+       static const char       *outfile = "tags";      /* output file */
+       int     aflag;                          /* -a: append to tags */
+       int     uflag;                          /* -u: update tags */
+       int     exit_val;                       /* exit value */
+       int     step;                           /* step through args */
+       int     ch;                             /* getopts char */
+       char    cmd[100];                       /* too ugly to explain */
+
+       aflag = uflag = NO;
+       while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != -1)
+               switch(ch) {
+               case 'B':
+                       searchar = '?';
+                       break;
+               case 'F':
+                       searchar = '/';
+                       break;
+               case 'a':
+                       aflag++;
+                       break;
+               case 'd':
+                       dflag++;
+                       break;
+               case 'f':
+                       outfile = optarg;
+                       break;
+               case 't':
+                       tflag++;
+                       break;
+               case 'u':
+                       uflag++;
+                       break;
+               case 'w':
+                       wflag++;
+                       break;
+               case 'v':
+                       vflag++;
+               case 'x':
+                       xflag++;
+                       break;
+               case '?':
+               default:
+                       goto usage;
+               }
+       argv += optind;
+       argc -= optind;
+       if (!argc) {
+usage:         (void)fprintf(stderr,
+                       "usage: ctags [-BFadtuwvx] [-f tagsfile] file ...\n");
+               exit(1);
+       }
+
+       init();
+
+       for (exit_val = step = 0; step < argc; ++step)
+               if (!(inf = fopen(argv[step], "r"))) {
+                       warn("%s", argv[step]);
+                       exit_val = 1;
+               }
+               else {
+                       curfile = argv[step];
+                       find_entries(argv[step]);
+                       (void)fclose(inf);
+               }
+
+       if (head) {
+               if (xflag)
+                       put_entries(head);
+               else {
+                       if (uflag) {
+                               for (step = 0; step < argc; step++) {
+                                       (void)snprintf(cmd, sizeof(cmd),
+                                               "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS",
+                                                       outfile, argv[step],
+                                                       outfile);
+                                       system(cmd);
+                               }
+                               ++aflag;
+                       }
+                       if (!(outf = fopen(outfile, aflag ? "a" : "w")))
+                               err(exit_val, "%s", outfile);
+                       put_entries(head);
+                       (void)fclose(outf);
+                       if (uflag) {
+                               (void)snprintf(cmd, sizeof(cmd),
+                                   "sort -o %s %s", outfile, outfile);
+                               system(cmd);
+                       }
+               }
+       }
+       exit(exit_val);
+}
+
+/*
+ * init --
+ *     this routine sets up the boolean psuedo-functions which work by
+ *     setting boolean flags dependent upon the corresponding character.
+ *     Every char which is NOT in that string is false with respect to
+ *     the pseudo-function.  Therefore, all of the array "_wht" is NO
+ *     by default and then the elements subscripted by the chars in
+ *     CWHITE are set to YES.  Thus, "_wht" of a char is YES if it is in
+ *     the string CWHITE, else NO.
+ */
+void
+init(void)
+{
+       int             i;
+       unsigned const char     *sp;
+
+       for (i = 0; i < 256; i++) {
+               _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO;
+               _gd[i] = YES;
+       }
+#define        CWHITE  " \f\t\n"
+       for (sp = CWHITE; *sp; sp++)    /* white space chars */
+               _wht[*sp] = YES;
+#define        CTOKEN  " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?"
+       for (sp = CTOKEN; *sp; sp++)    /* token ending chars */
+               _etk[*sp] = YES;
+#define        CINTOK  "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
+       for (sp = CINTOK; *sp; sp++)    /* valid in-token chars */
+               _itk[*sp] = YES;
+#define        CBEGIN  "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
+       for (sp = CBEGIN; *sp; sp++)    /* token starting chars */
+               _btk[*sp] = YES;
+#define        CNOTGD  ",;"
+       for (sp = CNOTGD; *sp; sp++)    /* invalid after-function chars */
+               _gd[*sp] = NO;
+}
+
+/*
+ * find_entries --
+ *     this routine opens the specified file and calls the function
+ *     which searches the file.
+ */
+void
+find_entries(char *file)
+{
+       char    *cp;
+
+       lineno = 0;                             /* should be 1 ?? KB */
+       if ((cp = strrchr(file, '.')) != NULL) {
+               if (cp[1] == 'l' && !cp[2]) {
+                       int     c;
+
+                       for (;;) {
+                               if (GETC(==, EOF))
+                                       return;
+                               if (!iswhite(c)) {
+                                       rewind(inf);
+                                       break;
+                               }
+                       }
+#define        LISPCHR ";(["
+/* lisp */             if (strchr(LISPCHR, c)) {
+                               l_entries();
+                               return;
+                       }
+/* lex */              else {
+                               /*
+                                * we search all 3 parts of a lex file
+                                * for C references.  This may be wrong.
+                                */
+                               toss_yysec();
+                               (void)strlcpy(lbuf, "%%$", sizeof(lbuf));
+                               pfnote("yylex", lineno);
+                               rewind(inf);
+                       }
+               }
+/* yacc */     else if (cp[1] == 'y' && !cp[2]) {
+                       /*
+                        * we search only the 3rd part of a yacc file
+                        * for C references.  This may be wrong.
+                        */
+                       toss_yysec();
+                       (void)strlcpy(lbuf, "%%$", sizeof(lbuf));
+                       pfnote("yyparse", lineno);
+                       y_entries();
+               }
+/* fortran */  else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
+                       if (PF_funcs())
+                               return;
+                       rewind(inf);
+               }
+       }
+/* C */        c_entries();
+}
diff --git a/usr.bin/ctags/ctags.h b/usr.bin/ctags/ctags.h
new file mode 100644 (file)
index 0000000..6aa2aa1
--- /dev/null
@@ -0,0 +1,92 @@
+/*     $NetBSD: ctags.h,v 1.9 2009/07/13 19:05:40 roy Exp $    */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ctags.h     8.3 (Berkeley) 4/2/94
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#define        bool    char
+
+#define        YES             1
+#define        NO              0
+#define        EOS             '\0'
+
+#define        ENDLINE         50              /* max length of pattern */
+#define        MAXTOKEN        250             /* max size of single token */
+
+#define        SETLINE         {++lineno;lineftell = ftell(inf);}
+#define        GETC(op,exp)    ((c = getc(inf)) op (int)exp)
+
+#define        iswhite(arg)    (_wht[(unsigned)arg])   /* T if char is white */
+#define        begtoken(arg)   (_btk[(unsigned)arg])   /* T if char can start token */
+#define        intoken(arg)    (_itk[(unsigned)arg])   /* T if char can be in token */
+#define        endtoken(arg)   (_etk[(unsigned)arg])   /* T if char ends tokens */
+#define        isgood(arg)     (_gd[(unsigned)arg])    /* T if char can be after ')' */
+
+typedef struct nd_st {                 /* sorting structure */
+       struct nd_st    *left,
+                       *right;         /* left and right sons */
+       char    *entry,                 /* function or type name */
+               *file,                  /* file name */
+               *pat;                   /* search pattern */
+       int     lno;                    /* for -x option */
+       bool    been_warned;            /* set if noticed dup */
+} NODE;
+
+extern char    *curfile;               /* current input file name */
+extern NODE    *head;                  /* head of the sorted binary tree */
+extern FILE    *inf;                   /* ioptr for current input file */
+extern FILE    *outf;                  /* ioptr for current output file */
+extern long    lineftell;              /* ftell after getc( inf ) == '\n' */
+extern int     lineno;                 /* line number of current line */
+extern int     dflag;                  /* -d: non-macro defines */
+extern int     tflag;                  /* -t: create tags for typedefs */
+extern int     vflag;                  /* -v: vgrind style index output */
+extern int     wflag;                  /* -w: suppress warnings */
+extern int     xflag;                  /* -x: cxref style output */
+extern bool    _wht[], _etk[], _itk[], _btk[], _gd[];
+extern char    lbuf[LINE_MAX];
+extern char    *lbp;
+extern char    searchar;               /* ex search character */
+
+extern int     cicmp(const char *);
+extern void    get_line(void);
+extern void    pfnote(const char *, int);
+extern int     skip_key(int);
+extern void    put_entries(NODE *);
+extern void    toss_yysec(void);
+extern void    l_entries(void);
+extern void    y_entries(void);
+extern int     PF_funcs(void);
+extern void    c_entries(void);
+extern void    skip_comment(int);
diff --git a/usr.bin/ctags/fortran.c b/usr.bin/ctags/fortran.c
new file mode 100644 (file)
index 0000000..2a9cefd
--- /dev/null
@@ -0,0 +1,174 @@
+/*     $NetBSD: fortran.c,v 1.11 2009/07/13 19:05:40 roy Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fortran.c  8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: fortran.c,v 1.11 2009/07/13 19:05:40 roy Exp $");
+#endif
+#endif /* not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static void takeprec(void);
+
+char *lbp;                             /* line buffer pointer */
+
+int
+PF_funcs(void)
+{
+       bool    pfcnt;                  /* pascal/fortran functions found */
+       char    *cp;
+       char    tok[MAXTOKEN];
+
+       for (pfcnt = NO;;) {
+               lineftell = ftell(inf);
+               if (!fgets(lbuf, sizeof(lbuf), inf))
+                       return (pfcnt);
+               ++lineno;
+               lbp = lbuf;
+               if (*lbp == '%')        /* Ratfor escape to fortran */
+                       ++lbp;
+               for (; isspace((unsigned char)*lbp); ++lbp)
+                       continue;
+               if (!*lbp)
+                       continue;
+               switch (*lbp | ' ') {   /* convert to lower-case */
+               case 'c':
+                       if (cicmp("complex") || cicmp("character"))
+                               takeprec();
+                       break;
+               case 'd':
+                       if (cicmp("double")) {
+                               for (; isspace((unsigned char)*lbp); ++lbp)
+                                       continue;
+                               if (!*lbp)
+                                       continue;
+                               if (cicmp("precision"))
+                                       break;
+                               continue;
+                       }
+                       break;
+               case 'i':
+                       if (cicmp("integer"))
+                               takeprec();
+                       break;
+               case 'l':
+                       if (cicmp("logical"))
+                               takeprec();
+                       break;
+               case 'r':
+                       if (cicmp("real"))
+                               takeprec();
+                       break;
+               }
+               for (; isspace((unsigned char)*lbp); ++lbp)
+                       continue;
+               if (!*lbp)
+                       continue;
+               switch (*lbp | ' ') {
+               case 'f':
+                       if (cicmp("function"))
+                               break;
+                       continue;
+               case 'p':
+                       if (cicmp("program") || cicmp("procedure"))
+                               break;
+                       continue;
+               case 's':
+                       if (cicmp("subroutine"))
+                               break;
+               default:
+                       continue;
+               }
+               for (; isspace((unsigned char)*lbp); ++lbp)
+                       continue;
+               if (!*lbp)
+                       continue;
+               for (cp = lbp + 1; *cp && intoken(*cp); ++cp)
+                       continue;
+               if ((cp = lbp + 1) != NULL)
+                       continue;
+               *cp = EOS;
+               (void)strlcpy(tok, lbp, sizeof(tok));
+               get_line();                     /* process line for ex(1) */
+               pfnote(tok, lineno);
+               pfcnt = YES;
+       }
+       /*NOTREACHED*/
+}
+
+/*
+ * cicmp --
+ *     do case-independent strcmp
+ */
+int
+cicmp(const char *cp)
+{
+       int     len;
+       char    *bp;
+
+       for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' ');
+           ++cp, ++len)
+               continue;
+       if (!*cp) {
+               lbp += len;
+               return (YES);
+       }
+       return (NO);
+}
+
+static void
+takeprec(void)
+{
+       for (; isspace((unsigned char)*lbp); ++lbp)
+               continue;
+       if (*lbp == '*') {
+               for (++lbp; isspace((unsigned char)*lbp); ++lbp)
+                       continue;
+               if (!isdigit((unsigned char)*lbp))
+                       --lbp;                  /* force failure */
+               else
+                       while (isdigit((unsigned char)*++lbp))
+                               continue;
+       }
+}
diff --git a/usr.bin/ctags/lisp.c b/usr.bin/ctags/lisp.c
new file mode 100644 (file)
index 0000000..d143c6c
--- /dev/null
@@ -0,0 +1,112 @@
+/*     $NetBSD: lisp.c,v 1.11 2009/07/13 19:05:40 roy Exp $    */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)lisp.c     8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: lisp.c,v 1.11 2009/07/13 19:05:40 roy Exp $");
+#endif
+#endif /* not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+/*
+ * lisp tag functions
+ * just look for (def or (DEF
+ */
+void
+l_entries(void)
+{
+       int     special;
+       char    *cp;
+       char    savedc;
+       char    tok[MAXTOKEN];
+
+       for (;;) {
+               lineftell = ftell(inf);
+               if (!fgets(lbuf, sizeof(lbuf), inf))
+                       return;
+               ++lineno;
+               lbp = lbuf;
+               if (!cicmp("(def"))
+                       continue;
+               special = NO;
+               switch(*lbp | ' ') {
+               case 'm':
+                       if (cicmp("method"))
+                               special = YES;
+                       break;
+               case 'w':
+                       if (cicmp("wrapper") || cicmp("whopper"))
+                               special = YES;
+               }
+               for (; !isspace((unsigned char)*lbp); ++lbp)
+                       continue;
+               for (; isspace((unsigned char)*lbp); ++lbp)
+                       continue;
+               for (cp = lbp; *cp && *cp != '\n'; ++cp)
+                       continue;
+               *cp = EOS;
+               if (special) {
+                       if (!(cp = strchr(lbp, ')')))
+                               continue;
+                       for (; cp >= lbp && *cp != ':'; --cp)
+                               continue;
+                       if (cp < lbp)
+                               continue;
+                       lbp = cp;
+                       for (; *cp && *cp != ')' && *cp != ' '; ++cp)
+                               continue;
+               }
+               else
+                       for (cp = lbp + 1;
+                           *cp && *cp != '(' && *cp != ' '; ++cp)
+                               continue;
+               savedc = *cp;
+               *cp = EOS;
+               (void)strlcpy(tok, lbp, sizeof(tok));
+               *cp = savedc;
+               get_line();
+               pfnote(tok, lineno);
+       }
+       /*NOTREACHED*/
+}
diff --git a/usr.bin/ctags/print.c b/usr.bin/ctags/print.c
new file mode 100644 (file)
index 0000000..86fcd3a
--- /dev/null
@@ -0,0 +1,121 @@
+/*     $NetBSD: print.c,v 1.10 2009/07/13 19:05:40 roy Exp $   */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)print.c    8.3 (Berkeley) 4/2/94";
+#else 
+__RCSID("$NetBSD: print.c,v 1.10 2009/07/13 19:05:40 roy Exp $");
+#endif
+#endif /* not lint */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ctags.h"
+
+/*
+ * get_line --
+ *     get the line the token of interest occurred on,
+ *     prepare it for printing.
+ */
+void
+get_line(void)
+{
+       long    saveftell;
+       int     c;
+       int     cnt;
+       char    *cp;
+
+       saveftell = ftell(inf);
+       (void)fseek(inf, lineftell, SEEK_SET);
+       if (xflag)
+               for (cp = lbuf; GETC(!=, '\n'); *cp++ = c)
+                       continue;
+       /*
+        * do all processing here, so we don't step through the
+        * line more than once; means you don't call this routine
+        * unless you're sure you've got a keeper.
+        */
+       else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) {
+               if (c == '\\') {                /* backslashes */
+                       if (cnt > ENDLINE - 2)
+                               break;
+                       *cp++ = '\\'; *cp++ = '\\';
+                       ++cnt;
+               }
+               else if (c == (int)searchar) {  /* search character */
+                       if (cnt > ENDLINE - 2)
+                               break;
+                       *cp++ = '\\'; *cp++ = c;
+                       ++cnt;
+               }
+               else if (c == '\n') {   /* end of keep */
+                       *cp++ = '$';            /* can find whole line */
+                       break;
+               }
+               else
+                       *cp++ = c;
+       }
+       *cp = EOS;
+       (void)fseek(inf, saveftell, SEEK_SET);
+}
+
+/*
+ * put_entries --
+ *     write out the tags
+ */
+void
+put_entries(NODE *node)
+{
+
+       if (node->left)
+               put_entries(node->left);
+       if (vflag)
+               printf("%s %s %d\n",
+                   node->entry, node->file, (node->lno + 63) / 64);
+       else if (xflag)
+               printf("%-16s%4d %-16s %s\n",
+                   node->entry, node->lno, node->file, node->pat);
+       else
+               fprintf(outf, "%s\t%s\t%c^%s%c\n",
+                   node->entry, node->file, searchar, node->pat, searchar);
+       if (node->right)
+               put_entries(node->right);
+}
diff --git a/usr.bin/ctags/test/ctags.test b/usr.bin/ctags/test/ctags.test
new file mode 100644 (file)
index 0000000..658a073
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: ctags.test,v 1.2 1995/03/26 20:14:14 glass Exp $       */
+
+int    bar = (1 + 5);
+
+FOO("here is a #define test: ) {");
+char sysent[20];
+int    nsysent = sizeof (sysent) / sizeof (sysent[0]);
+/*
+ * now is the time for a comment.
+ * four lines in length...
+ */struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe;
+#define FOO    BAR
+struct struct_three {
+       int     list;
+};
+#define SINGLE
+int    BAD();
+enum color {red, green, gold, brown};
+char qq[] = "  quote(one,two) {int bar;}  ";
+typedef struct {
+       int     bar;
+       struct struct_two {
+               int foo;
+               union union_3 {
+                       struct struct_three entry;
+                       char size[25];
+               };
+               struct last {
+                       struct struct_three xentry;
+                       char list[34];
+               };
+       };
+} struct_one;
+#define TWOLINE        ((MAXLIST + FUTURE + 15) \
+       / (time_to_live ? 3 : 4))
+#if (defined(BAR))
+int    bar;
+#endif
+#define MULTIPLE {\
+       multiple(one,two); \
+       lineno++; \
+       callroute(one,two); \
+}
+#if defined(BAR)
+int    bar;
+#endif
+union union_one {
+       struct struct_three     s3;
+       char    foo[25];
+};
+#define XYZ(A,B)       (A + B / 2) * (3 - 26 + l_lineno)
+routine1(one,two)      /* comments here are fun... */
+       struct {
+               int entry;
+               char bar[34];
+       } *one;
+       char two[10];
+{
+typedef unsigned char  u_char;
+       register struct buf *bp;
+       five(one,two);
+}
+ routine2 (one,two) { puts("hello\n"); }
+ routine3
+(one,
+two) { puts("world\n"); }
+routine4(int one, char (*two)(void)) /* test ANSI arguments */
+{
+}
diff --git a/usr.bin/ctags/tree.c b/usr.bin/ctags/tree.c
new file mode 100644 (file)
index 0000000..93f4a41
--- /dev/null
@@ -0,0 +1,145 @@
+/*     $NetBSD: tree.c,v 1.12 2006/04/05 19:38:47 dsl Exp $    */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)tree.c     8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: tree.c,v 1.12 2006/04/05 19:38:47 dsl Exp $");
+#endif
+#endif /* not lint */
+
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static void    add_node(NODE *, NODE *);
+static void    free_tree(NODE *);
+
+/*
+ * pfnote --
+ *     enter a new node in the tree
+ */
+void
+pfnote(const char *name, int ln)
+{
+       NODE    *np;
+       char    *fp;
+       char    nbuf[MAXTOKEN];
+
+       /*NOSTRICT*/
+       if (!(np = (NODE *)malloc(sizeof(NODE)))) {
+               warnx("too many entries to sort");
+               put_entries(head);
+               free_tree(head);
+               /*NOSTRICT*/
+               if (!(head = np = (NODE *)malloc(sizeof(NODE))))
+                       err(1, "out of space");
+       }
+       if (!xflag && !strcmp(name, "main")) {
+               if (!(fp = strrchr(curfile, '/')))
+                       fp = curfile;
+               else
+                       ++fp;
+               (void)snprintf(nbuf, sizeof(nbuf), "M%s", fp);
+               fp = strrchr(nbuf, '.');
+               if (fp && !fp[2])
+                       *fp = EOS;
+               name = nbuf;
+       }
+       if (!(np->entry = strdup(name)))
+               err(1, "strdup");
+       np->file = curfile;
+       np->lno = ln;
+       np->left = np->right = 0;
+       if (!(np->pat = strdup(lbuf)))
+               err(1, "strdup");
+       if (!head)
+               head = np;
+       else
+               add_node(np, head);
+}
+
+static void
+add_node(NODE *node, NODE *cur_node)
+{
+       int     dif;
+
+       dif = strcmp(node->entry, cur_node->entry);
+       if (!dif) {
+               if (node->file == cur_node->file) {
+                       if (!wflag)
+                               fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry);
+                       return;
+               }
+               if (!cur_node->been_warned)
+                       if (!wflag)
+                               fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry);
+               cur_node->been_warned = YES;
+       }
+       else if (dif < 0) {
+               if (cur_node->left)
+                       add_node(node, cur_node->left);
+               else
+                       cur_node->left = node;
+       } else {
+               if (cur_node->right)
+                       add_node(node, cur_node->right);
+               else
+                       cur_node->right = node;
+       }
+}
+
+static void
+free_tree(NODE *node)
+{
+       NODE *nnode;
+
+       for (; node != NULL; node = nnode) {
+               nnode = node->left;
+               if (node->right) {
+                       if (nnode == NULL)
+                               nnode = node->right;
+                       else
+                               free_tree(node->right);
+               }
+               free(node);
+       }
+}
diff --git a/usr.bin/ctags/yacc.c b/usr.bin/ctags/yacc.c
new file mode 100644 (file)
index 0000000..d17fa99
--- /dev/null
@@ -0,0 +1,160 @@
+/*     $NetBSD: yacc.c,v 1.12 2009/07/13 19:05:40 roy Exp $    */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)yacc.c     8.3 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: yacc.c,v 1.12 2009/07/13 19:05:40 roy Exp $");
+#endif
+#endif /* not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+/*
+ * y_entries:
+ *     find the yacc tags and put them in.
+ */
+void
+y_entries(void)
+{
+       int     c;
+       char    *sp;
+       bool    in_rule;
+       char    tok[MAXTOKEN];
+
+       in_rule = NO;
+
+       while (GETC(!=, EOF))
+               switch (c) {
+               case '\n':
+                       SETLINE;
+                       /* FALLTHROUGH */
+               case ' ':
+               case '\f':
+               case '\r':
+               case '\t':
+                       break;
+               case '{':
+                       if (skip_key('}'))
+                               in_rule = NO;
+                       break;
+               case '\'':
+               case '"':
+                       if (skip_key(c))
+                               in_rule = NO;
+                       break;
+               case '%':
+                       if (GETC(==, '%'))
+                               return;
+                       (void)ungetc(c, inf);
+                       break;
+               case '/':
+                       if (GETC(==, '*'))
+                               skip_comment('*');
+                       else
+                               (void)ungetc(c, inf);
+                       break;
+               case '|':
+               case ';':
+                       in_rule = NO;
+                       break;
+               default:
+                       if (in_rule || (!isalpha(c) && c != '.' && c != '_'))
+                               break;
+                       sp = tok;
+                       *sp++ = c;
+                       while (GETC(!=, EOF) && (intoken(c) || c == '.'))
+                               *sp++ = c;
+                       *sp = EOS;
+                       get_line();             /* may change before ':' */
+                       if (c == EOF)
+                               return;
+                       while (iswhite(c)) {
+                               if (c == '\n')
+                                       SETLINE;
+                               if (GETC(==, EOF))
+                                       return;
+                       }
+                       if (c == ':') {
+                               pfnote(tok, lineno);
+                               in_rule = YES;
+                       }
+                       else
+                               (void)ungetc(c, inf);
+               }
+}
+
+/*
+ * toss_yysec --
+ *     throw away lines up to the next "\n%%\n"
+ */
+void
+toss_yysec(void)
+{
+       int     c;                      /* read character */
+       int     state;
+
+       /*
+        * state == 0 : waiting
+        * state == 1 : received a newline
+        * state == 2 : received first %
+        * state == 3 : received second %
+        */
+       lineftell = ftell(inf);
+       for (state = 0; GETC(!=, EOF);)
+               switch (c) {
+               case '\n':
+                       ++lineno;
+                       lineftell = ftell(inf);
+                       if (state == 3)         /* done! */
+                               return;
+                       state = 1;              /* start over */
+                       break;
+               case '%':
+                       if (state)              /* if 1 or 2 */
+                               ++state;        /* goto 3 */
+                       break;
+               default:
+                       state = 0;              /* reset */
+                       break;
+               }
+}
diff --git a/usr.bin/nvi/Makefile b/usr.bin/nvi/Makefile
new file mode 100644 (file)
index 0000000..f954033
--- /dev/null
@@ -0,0 +1,21 @@
+#      $NetBSD: Makefile,v 1.3 2008/10/13 18:11:54 dyoung Exp $
+
+.include "Makefile.inc"
+
+.include <bsd.own.mk>
+
+.if defined(__MINIX)
+SUBDIR+= build
+.else
+.if ${MKSHARE} != "no"
+SUBDIR+= catalog
+.endif
+
+SUBDIR+= build recover
+
+.if ${MKDOC} != "no"
+SUBDIR+= docs
+.endif
+.endif # defined(__MINIX)
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/nvi/Makefile.inc b/usr.bin/nvi/Makefile.inc
new file mode 100644 (file)
index 0000000..3173631
--- /dev/null
@@ -0,0 +1,6 @@
+#      $NetBSD: Makefile.inc,v 1.2 2008/07/13 03:44:41 christos Exp $
+
+.include <bsd.own.mk>
+
+DIST= ${NETBSDSRCDIR}/dist/nvi
+.PATH: ${DIST}
diff --git a/usr.bin/nvi/build/Makefile b/usr.bin/nvi/build/Makefile
new file mode 100644 (file)
index 0000000..5b0eb5f
--- /dev/null
@@ -0,0 +1,69 @@
+#      $NetBSD: Makefile,v 1.17 2012/03/21 05:44:39 matt Exp $
+
+.include <bsd.own.mk>
+
+USE_WIDECHAR?=yes
+
+CWARNFLAGS.clang+=     -Wno-uninitialized -Wno-format-security
+
+CPPFLAGS+=-I${DIST}/include -I${.CURDIR} -I. -DGTAGS
+#DBG=-g
+
+#CWARNFLAGS+=-Wno-parentheses -Wno-unused -Wno-missing-prototypes
+#.if defined(HAVE_GCC)
+#CWARNFLAGS+=-Wno-pointer-sign
+#COPTS+=-fno-strict-aliasing
+#.endif
+
+LDADD+=        -lcurses -lterminfo
+DPADD+=        ${LIBCURSES} ${LIBTERMINFO}
+PROG=  vi
+SRCS=  api.c cl_bsd.c cl_funcs.c cl_main.c cl_read.c cl_screen.c cl_term.c \
+       conv.c cut.c db.c db1.c delete.c ex.c ex_abbrev.c ex_append.c \
+       ex_args.c ex_argv.c ex_at.c ex_bang.c ex_cd.c ex_cmd.c ex_cscope.c \
+       ex_delete.c ex_display.c ex_edit.c ex_equal.c ex_file.c ex_filter.c \
+       ex_global.c ex_init.c ex_join.c ex_map.c ex_mark.c ex_mkexrc.c \
+       ex_move.c ex_open.c ex_perl.c ex_preserve.c ex_print.c ex_put.c \
+       ex_quit.c ex_read.c ex_screen.c ex_script.c ex_set.c ex_shell.c \
+       ex_shift.c ex_source.c ex_stop.c ex_subst.c ex_tag.c ex_tcl.c \
+       ex_txt.c ex_undo.c ex_usage.c ex_util.c ex_version.c ex_visual.c \
+       ex_write.c ex_yank.c ex_z.c exf.c getc.c gs.c key.c log.c \
+       main.c mark.c msg.c nothread.c options.c options_f.c put.c recover.c \
+       screen.c search.c seq.c util.c v_at.c v_ch.c v_cmd.c v_delete.c \
+       v_event.c v_ex.c v_increment.c v_init.c v_itxt.c v_left.c v_mark.c \
+       v_match.c v_paragraph.c v_put.c v_redraw.c v_replace.c v_right.c \
+       v_screen.c v_scroll.c v_search.c v_section.c v_sentence.c v_status.c \
+       v_txt.c v_ulcase.c v_undo.c v_util.c v_word.c v_xchar.c v_yank.c \
+       v_z.c v_zexit.c vi.c vs_line.c vs_msg.c vs_refresh.c vs_relative.c \
+       vs_smap.c vs_split.c
+
+# For wide char support
+.if ${USE_WIDECHAR} == "yes"
+SRCS+= regcomp.c regerror.c regexec.c regfree.c
+CPPFLAGS+=-I${DIST}/regex -D__REGEX_PRIVATE -DUSE_WIDECHAR
+.endif
+
+LINKS= ${BINDIR}/vi ${BINDIR}/ex ${BINDIR}/vi ${BINDIR}/view
+MLINKS=        vi.1 ex.1 vi.1 view.1
+
+DPSRCS+=options_def.h
+CLEANFILES+=options_def.h
+
+options_def.h: options.awk options.c
+       ${_MKTARGET_CREATE}
+       ${TOOL_AWK} -f ${.ALLSRC} >${.TARGET}
+
+.include "../Makefile.inc"
+.include "../../Makefile.inc"
+
+WARNS= 4
+
+.PATH: ${DIST}/vi ${DIST}/ex ${DIST}/cl
+.PATH: ${DIST}/common
+.PATH: ${DIST}/regex
+.PATH: ${DIST}/docs/vi.man
+
+COPTS.exf.c += -Wno-format-nonliteral
+COPTS.msg.c += -Wno-format-nonliteral
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nvi/build/config.h b/usr.bin/nvi/build/config.h
new file mode 100644 (file)
index 0000000..4300f83
--- /dev/null
@@ -0,0 +1,291 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+/* Id: acconfig.h,v 8.34 2002/01/19 23:01:35 skimo Exp  (Berkeley) Date: 2002/01/19 23:01:35  */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+/* #undef ssize_t */
+
+/* Define if you want a debugging version. */
+/* #undef DEBUG */
+
+/* Define if you have a System V-style (broken) gettimeofday. */
+/* #undef HAVE_BROKEN_GETTIMEOFDAY */
+
+/* Define if you have a Ultrix-style (broken) vdisable. */
+/* #undef HAVE_BROKEN_VDISABLE */
+
+/* Define if you have a BSD version of curses. */
+/* #undef HAVE_BSD_CURSES */
+
+/* Define if you have wide ncurses(3). */
+/* #undef HAVE_NCURSESW */
+
+/* Define if you have the curses(3) waddnwstr function. */
+/* #undef HAVE_CURSES_ADDNWSTR */
+
+/* Define if you have the curses(3) waddnstr function. */
+#define HAVE_CURSES_WADDNSTR 1
+
+/* Define if you have the curses(3) beep function. */
+#define HAVE_CURSES_BEEP 1
+
+/* Define if you have the curses(3) flash function. */
+#define HAVE_CURSES_FLASH 1
+
+/* Define if you have the curses(3) idlok function. */
+#define HAVE_CURSES_IDLOK 1
+
+/* Define if you have the curses(3) keypad function. */
+#define HAVE_CURSES_KEYPAD 1
+
+/* Define if you have the curses(3) newterm function. */
+#define HAVE_CURSES_NEWTERM 1
+
+/* Define if you have the curses(3) setupterm function. */
+#define HAVE_CURSES_SETUPTERM 1
+
+/* Define if you have the curses(3) tigetstr/tigetnum functions. */
+#define HAVE_CURSES_TIGETSTR 1
+
+/* Define if you have the DB __hash_open call in the C library. */
+/* #undef HAVE_DB_HASH_OPEN */
+
+/* Define if you have the chsize(2) system call. */
+/* #undef HAVE_FTRUNCATE_CHSIZE */
+
+/* Define if you have the ftruncate(2) system call. */
+#define HAVE_FTRUNCATE_FTRUNCATE 1
+
+/* Define if you have gcc. */
+#define HAVE_GCC 1
+
+/* Define if you have fcntl(2) style locking. */
+/* #undef HAVE_LOCK_FCNTL */
+
+/* Define if you have flock(2) style locking. */
+#define HAVE_LOCK_FLOCK 1
+
+/* Define is appropriate pango is available */
+/* #undef HAVE_PANGO */
+
+/* Define if you want to compile in the Perl interpreter. */
+/* #undef HAVE_PERL_INTERP */
+
+/* Define if using pthread. */
+/* #undef HAVE_PTHREAD */
+
+#ifndef __minix
+/* Define if you have the Berkeley style revoke(2) system call. */
+#define HAVE_REVOKE 1
+#endif
+
+/* Define if you have the Berkeley style strsep(3) function. */
+#define HAVE_STRSEP 1
+
+/* Define if you have <sys/mman.h> */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define if you have <sys/select.h> */
+#define HAVE_SYS_SELECT_H 1
+
+#ifndef __minix
+/* Define if you have the System V style pty calls. */
+#define HAVE_SYS5_PTY 1
+#endif
+
+/* Define if you want to compile in the Tcl interpreter. */
+/* #undef HAVE_TCL_INTERP */
+
+/* Define is appropriate zvt is available */
+/* #undef HAVE_ZVT */
+
+/* Define if your sprintf returns a pointer, not a length. */
+/* #undef SPRINTF_RET_CHARPNT */
+
+/* Define when using db1 */
+#define USE_DB1 1
+
+/* Define when using db4 logging */
+/* #undef USE_DB4_LOGGING */
+
+/* Define when dynamically loading DB 3 */
+/* #undef USE_DYNAMIC_LOADING */
+
+/* Define when iconv can be used */
+#define USE_ICONV 1
+
+/* Define when perl's setenv should be used */
+/* #undef USE_PERL_SETENV */
+
+/* Define when using S-Lang */
+/* #undef USE_SLANG_CURSES */
+
+/* Define when using wide characters */
+/* #undef USE_WIDECHAR */
+
+/* Define if you have <ncurses.h> */
+/* #undef HAVE_NCURSES_H */
+
+/* Define when fprintf prototype not in an obvious place */
+/* #undef NEED_FPRINTF_PROTO */
+
+/* Define to 1 if you have the `bsearch' function. */
+#define HAVE_BSEARCH 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `iswblank' function. */
+#define HAVE_ISWBLANK 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the <ncursesw/ncurses.h> header file. */
+/* #undef HAVE_NCURSESW_NCURSES_H */
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+/* #undef HAVE_NCURSES_H */
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strpbrk' function. */
+#define HAVE_STRPBRK 1
+
+/* Define to 1 if you have the `strsep' function. */
+#define HAVE_STRSEP 1
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+
+/* Define to 1 if your `struct stat' has `st_blksize'. Deprecated, use
+   `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+#define HAVE_UNSETENV 1
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Name of package */
+#define PACKAGE "vi"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Version number of package */
+#define VERSION "1.81.6"
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
diff --git a/usr.bin/nvi/build/pathnames.h b/usr.bin/nvi/build/pathnames.h
new file mode 100644 (file)
index 0000000..6dd0bf1
--- /dev/null
@@ -0,0 +1,49 @@
+/* Id: pathnames.h.in,v 8.5 2000/04/21 21:26:21 skimo Exp  (Berkeley) Date: 2000/04/21 21:26:21  */
+
+#ifndef        _PATH_BSHELL
+#define        _PATH_BSHELL    "/bin/sh"
+#endif
+
+#ifndef        _PATH_DB3
+#define        _PATH_DB3       ""
+#endif
+
+#ifndef        _PATH_EXRC
+#define        _PATH_EXRC      ".exrc"
+#endif
+
+#ifndef        _PATH_MSGCAT
+#define        _PATH_MSGCAT    "./"
+#endif
+
+#ifndef        _PATH_NEXRC
+#define        _PATH_NEXRC     ".nexrc"
+#endif
+
+#ifndef        _PATH_PRESERVE
+#define        _PATH_PRESERVE  "/var/tmp/vi.recover"
+#endif
+
+#ifndef _PATH_SYSV_PTY
+#define        _PATH_SYSV_PTY  "/dev/ptmx"
+#endif
+
+#ifndef        _PATH_SENDMAIL
+#define        _PATH_SENDMAIL  "/usr/sbin/sendmail"
+#endif
+
+#ifndef        _PATH_SYSEXRC
+#define        _PATH_SYSEXRC   "/etc/vi.exrc"
+#endif
+
+#ifndef        _PATH_TAGS
+#define        _PATH_TAGS      "tags"
+#endif
+
+#ifndef        _PATH_TMP
+#define        _PATH_TMP       "/tmp"
+#endif
+
+#ifndef        _PATH_TTY
+#define        _PATH_TTY       "/dev/tty"
+#endif
diff --git a/usr.bin/nvi/build/port.h b/usr.bin/nvi/build/port.h
new file mode 100644 (file)
index 0000000..b7cf93a
--- /dev/null
@@ -0,0 +1,201 @@
+/* Id: port.h.in,v 8.15 2001/01/01 20:26:48 skimo Exp  (Berkeley) Date: 2001/01/01 20:26:48  */
+
+/*
+ * Declare the basic types, if they aren't already declared.  Named and
+ * some system's db.h files protect them with __BIT_TYPES_DEFINED__.
+ */
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+
+
+
+
+#endif
+
+
+
+
+
+
+/*
+ * XXX
+ * Handle function prototypes.  This steps on name space that vi doesn't
+ * control, but all of the other solutions are worse.
+ */
+#undef __P
+#if defined(__STDC__) || defined(__cplusplus)
+#define        __P(protos)     protos          /* ANSI C prototypes */
+#else
+#define        __P(protos)     ()              /* K&R C preprocessor */
+#endif
+
+/*
+ * XXX
+ * Some versions of System V changed the number of arguments to gettimeofday
+ * without changing the name.
+ */
+#ifdef HAVE_BROKEN_GETTIMEOFDAY
+#define        gettimeofday(tv, tz)    gettimeofday(tv)
+#endif
+
+/* 
+ * XXX
+ * If we don't have mmap, we fake it with read and write, but we'll
+ * still need the header information.
+ */
+#ifndef HAVE_SYS_MMAN_H
+#define        MAP_SHARED      1               /* share changes */
+#define        MAP_PRIVATE     2               /* changes are private */
+#define        PROT_READ       0x1             /* pages can be read */
+#define        PROT_WRITE      0x2             /* pages can be written */
+#define        PROT_EXEC       0x4             /* pages can be executed */
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 names for file descriptors.
+ */
+#ifndef STDERR_FILENO
+#define STDIN_FILENO   0               /* ANSI C #defines */
+#define STDOUT_FILENO  1
+#define STDERR_FILENO  2
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 names for seek settings.
+ */
+#ifndef SEEK_END
+#define        SEEK_SET        0               /* POSIX 1003.1 seek values */
+#define        SEEK_CUR        1
+#define        SEEK_END        2
+#endif
+
+/*
+ * Hack _POSIX_VDISABLE to \377 since Ultrix doesn't honor _POSIX_VDISABLE
+ * (treats it as ^@).  The symptom is that the ^@ keystroke immediately
+ * drops core.
+ */
+#ifdef HAVE_BROKEN_VDISABLE
+#undef _POSIX_VDISABLE
+#define        _POSIX_VDISABLE ((unsigned char)'\377')
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 tty disabling character.
+ */
+#ifndef _POSIX_VDISABLE
+#define        _POSIX_VDISABLE 0               /* Some systems used 0. */
+#endif
+
+/*
+ * XXX
+ * 4.4BSD extension to only set the software termios bits.
+ */
+#ifndef        TCSASOFT                        /* 4.4BSD extension. */
+#define        TCSASOFT        0
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 maximum path length.
+ */
+#ifndef MAXPATHLEN
+#ifdef PATH_MAX
+#define        MAXPATHLEN      PATH_MAX
+#else
+#define        MAXPATHLEN      1024
+#endif
+#endif
+
+/*
+ * XXX
+ * MIN, MAX, historically in <sys/param.h>
+ */
+#ifndef        MAX
+#define        MAX(_a,_b)      ((_a)<(_b)?(_b):(_a))
+#endif
+#ifndef        MIN
+#define        MIN(_a,_b)      ((_a)<(_b)?(_a):(_b))
+#endif
+
+#ifndef USE_DB1
+/*
+ * XXX
+ * "DB" isn't always portable, and we want the private information.
+ */
+#define DB      L__DB
+#undef pgno_t                  /* IRIX has its own version. */
+#define        pgno_t  L__db_pgno_t
+#endif /* USE_DB1 */
+
+/*
+ * XXX
+ * 4.4BSD extension to provide lock values in the open(2) call.
+ */
+#ifndef O_EXLOCK
+#define        O_EXLOCK        0
+#endif
+
+#ifndef O_SHLOCK
+#define        O_SHLOCK        0
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 bad file format errno.
+ */
+#ifndef EFTYPE
+#define        EFTYPE          EINVAL
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.2 RE length limit.
+ */
+#ifndef        _POSIX2_RE_DUP_MAX
+#define        _POSIX2_RE_DUP_MAX      255
+#endif
+
+/*
+ * XXX
+ * 4.4BSD extension to determine if a program dropped core from the exit
+ * status.
+ */
+#ifndef        WCOREDUMP
+#define        WCOREDUMP(a)    0
+#endif
+
+/*
+ * XXX
+ * Endian-ness of the machine.
+ */
+#if !defined(LITTLE_ENDIAN)
+#define        LITTLE_ENDIAN   1234
+#endif
+#if !defined(BIG_ENDIAN)
+#define        BIG_ENDIAN      4321
+#endif
+#if !defined(BYTE_ORDER)
+#if WORDS_BIGENDIAN == 1
+#define        BYTE_ORDER      BIG_ENDIAN
+#else
+#define        BYTE_ORDER      LITTLE_ENDIAN
+#endif
+#endif
+
+#ifndef HAVE_MEMCPY
+#define memcpy memmove
+#endif
+
+#ifdef NEED_FPRINTF_PROTO
+extern  int     fprintf( FILE *, const char *, ... );
+#endif
+
+#ifdef HAVE_PTHREAD
+#define VI_DB_THREAD DB_THREAD
+#else
+#define VI_DB_THREAD 0
+#endif
diff --git a/usr.bin/nvi/catalog/Makefile b/usr.bin/nvi/catalog/Makefile
new file mode 100644 (file)
index 0000000..6a3cbec
--- /dev/null
@@ -0,0 +1,101 @@
+#      $NetBSD: Makefile,v 1.6 2008/10/25 22:27:39 apb Exp $
+#
+#      @(#)Makefile    8.29 (Berkeley) 10/19/96
+
+NOMAN=         # defined
+
+.include "../Makefile.inc"
+
+.PATH: ${DIST}/catalog
+
+CATALOG=       dutch english french german ru_RU.KOI8-R spanish swedish
+VI_FILES=      ${DIST}/cl/*.c ${DIST}/common/*.c \
+               ${DIST}/ex/*.c ${DIST}/vi/*.c
+FILES=         ${CATALOG}
+FILESDIR=      /usr/share/nvi/catalog
+
+HOSTPROG=      dump
+SRCS=          dump.c
+
+CLEANFILES+=   ${CATALOG} english.base *.check __ck1 __ck2
+
+realall: ${CATALOG}
+
+${CATALOG}: ${CATALOG:S/$/.base/}
+       @echo "... $@";                                                 \
+       rm -f $@;                                                       \
+       if test -f $@.base; then                                        \
+               f=$@.base;                                              \
+       else                                                            \
+               f=${DIST}/catalog/$@.base;                              \
+       fi;                                                             \
+       sort -u $$f |                                                   \
+       ${TOOL_AWK} '{                                                  \
+               if ($$1 == 1) {                                         \
+                       print "\nMESSAGE NUMBER 1 IS NOT LEGAL";        \
+                       exit 1;                                         \
+               }                                                       \
+               if (++nline > $$1) {                                    \
+                       print "DUPLICATE MESSAGE NUMBER " $$1;          \
+                       exit 1;                                         \
+               }                                                       \
+               for (; nline < $$1; ++nline)                            \
+                       print "";                                       \
+               print $0;                                               \
+       }' |                                                            \
+       ${TOOL_SED} -e '1s/^/VI_MESSAGE_CATALOG/'                       \
+           -e '/"/s/^[^"]*"//'                                         \
+           -e '1!s/"$$/X/' > $@;                                       \
+       if grep DUPLICATE $@ > /dev/null; then                          \
+               grep DUPLICATE $@;                                      \
+       fi;                                                             \
+       if grep 'NOT LEGAL' $@ > /dev/null; then                        \
+               grep 'NOT LEGAL' $@;                                    \
+       fi
+
+CHK=   dutch.check english.check french.check german.check \
+       ru_RU.KOI8-R.check spanish.check swedish.check
+check: ${CHK}
+${CHK}: ${CATALOG}
+       @echo "... $@";                                                 \
+       f=${DIST}/catalog/`basename $@ .check`;                         \
+       (echo "Unused message id's (this is okay):";                    \
+       ${TOOL_AWK} '{                                                  \
+               while (++nline < $$1)                                   \
+                       printf "%03d\n", nline;                         \
+       }' < ${DIST}/catalog/$$f.base;                                  \
+       echo =========================;                                 \
+       echo "MISSING ERROR MESSAGES (Please add!):";                   \
+       ${TOOL_AWK} '{print $$1}' < $$f.base | sort -u > __ck1;         \
+       ${TOOL_AWK} '{print $$1}' < english.base | sort -u > __ck2;     \
+       comm -13 __ck1 __ck2;                                           \
+       echo =========================;                                 \
+       echo "Extra error messages (just delete them):";                \
+       comm -23 __ck1 __ck2;                                           \
+       echo =========================;                                 \
+       echo "MESSAGES WITH THE SAME MESSAGE ID's (FIX!):";             \
+       for j in                                                        \
+           `${TOOL_SED} '/^$$/d' < $$f.base | sort -u |                \
+           ${TOOL_AWK} '{print $$1}' | uniq -d`; do                    \
+               egrep $$j $$f.base;                                     \
+       done;                                                           \
+       echo =========================;                                 \
+       echo "Duplicate messages, both id and message (this is okay):"; \
+       ${TOOL_SED} '/^$$/d' < $$f.base | sort | uniq -c |              \
+       ${TOOL_AWK} '$$1 != 1 { print $$0 }' | sort -n;                 \
+       echo =========================;                                 \
+       echo "Duplicate messages, just message (this is okay):";        \
+       ${TOOL_SED} '/^$$/d' < $$f | sort | uniq -c |                   \
+       ${TOOL_AWK} '$$1 != 1 { print $$0 }' | sort -n;                 \
+       echo =========================) > $@
+
+english.base: dump ${VI_FILES} #Makefile
+       ${_MKTARGET_CREATE}
+       ./dump ${VI_FILES} |\
+       ${TOOL_SED} -e '/|/!d' \
+           -e 's/|/ "/' \
+           -e 's/^"//' \
+           -e 's/\\"/"/g' |\
+       sort -n > $@
+
+.include <bsd.hostprog.mk>
diff --git a/usr.bin/nvi/docs/Makefile b/usr.bin/nvi/docs/Makefile
new file mode 100644 (file)
index 0000000..13e122d
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+
+SUBDIR= USD.doc info
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/nvi/docs/USD.doc/Makefile b/usr.bin/nvi/docs/USD.doc/Makefile
new file mode 100644 (file)
index 0000000..0cf5b9a
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+
+SUBDIR= edit exref vi.ref vitut
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/nvi/docs/USD.doc/edit/Makefile b/usr.bin/nvi/docs/USD.doc/edit/Makefile
new file mode 100644 (file)
index 0000000..f17888e
--- /dev/null
@@ -0,0 +1,24 @@
+#      $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+#
+#      @(#)Makefile    8.1 (Berkeley) 6/8/93
+
+.include "../../../Makefile.inc"
+.PATH: ${DIST}/docs/edit
+DIR=   usd/11.edit
+SRCS=  edittut.ms
+MACROS=        -ms
+
+all: paper.ps
+
+paper.ps: ${SRCS}
+       ${TOOL_TBL} ${.ALLSRC} | ${TOOL_ROFF_PS} ${MACROS} > ${.TARGET}
+
+# index for versatec is different from the one in edit.tut
+# because the fonts are different and entries reference page
+# rather than section numbers.  if you have a typesetter
+# you should just use the index in edit.tut, and ignore editvindex.
+
+editvindex:
+       ${TOOL_ROFF_RAW} ${MACROS} -n22 edit.vindex
+
+.include <bsd.doc.mk>
diff --git a/usr.bin/nvi/docs/USD.doc/edit/edit.vindex b/usr.bin/nvi/docs/USD.doc/edit/edit.vindex
new file mode 100644 (file)
index 0000000..613d5b4
--- /dev/null
@@ -0,0 +1,113 @@
+.\"    $NetBSD: edit.vindex,v 1.1 2008/09/02 09:25:39 christos Exp $
+.\"
+.\" Copyright (c) 1980, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)edit.vindex 8.1 (Berkeley) 6/8/93
+.\"
+.bd I
+.ND
+.TL
+Index
+.sp 3
+.2C
+.nf
+addressing, \fIsee\fR line numbers
+append mode, 4
+backslash (\\), 18
+buffer, 2
+command mode, 4
+context search, 8, 10, 13, 18
+control characters (``^'' notation), 8
+control-d, 6
+current filename, 19, 20
+current line (.), 9, 15
+diagnostic messages, 4
+disk, 2
+documentation, 21
+edit (to begin editing session), 3, 7
+editing commands:
+.in +2
+append (a), 4, 7
+change (c), 16
+copy (co), 13
+delete (d), 13-14
+edit (e), 12
+file (f), 19
+global (g), 18-19
+move (m), 12-13
+number (nu), 9
+preserve (pre), 20-21
+print (p), 8
+quit (q), 5, 11
+quit! (q!), 11
+read (r), 20
+recover (rec), 20
+substitute (s), 9-10, 17, 18
+undo (u), 14, 17
+write (w), 5-6, 11, 19-20
+z, 11
+.sp 10i
+! (shell escape), 19
+$= , 15
++, 15
+\-, 15
+//, 8, 18
+??, 18
+\&\fB.\fR, 9, 15
+\&\fB.\fR=, 9, 15
+.in -2
+erasing
+.ti +2
+characters (#), 8
+.ti +2
+lines (@), 8
+ex (text editor), 21
+\fIEx Reference Manual\fR, 21
+file, 1
+file recovery, 20
+filename, 2
+Interrupt (message), 7
+line numbers, \fIsee also\fR current line
+.ti +2
+dollar sign ($), 8, 12-13, 15
+.ti +2
+dot (.), 9, 15
+.ti +2
+relative (+ and \-), 15, 16
+logging out, 6
+login procedure, 2
+``magic'' characters, 21
+non-printing characters, 8
+``not found'' (message), 3
+program, 1
+recovery \fIsee\fR file recovery
+shell, 18
+shell escape (!), 19
+special characters (^, $, \e), 18
+text input mode, 4
+UNIX, 1
diff --git a/usr.bin/nvi/docs/USD.doc/exref/Makefile b/usr.bin/nvi/docs/USD.doc/exref/Makefile
new file mode 100644 (file)
index 0000000..8501b85
--- /dev/null
@@ -0,0 +1,21 @@
+#      $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+#
+# @(#)Makefile 8.8 (Berkeley) 10/10/96
+
+.include "../../../Makefile.inc"
+.PATH: ${DIST}/docs/exref
+
+DIR=           usd/12.ex
+SRCS=          ex.rm ex.summary
+MACROS=                -ms
+CLEANFILES=    summary.ps
+
+all: paper.ps summary.ps
+
+paper.ps: ex.rm
+       ${TOOL_TBL} ${.ALLSRC} | ${TOOL_ROFF_PS} ${MACROS} > ${.TARGET}
+
+summary.ps: ex.summary
+       ${TOOL_TBL} ${.ALLSRC} | ${TOOL_ROFF_PS} ${MACROS} > ${.TARGET}
+
+.include <bsd.doc.mk>
diff --git a/usr.bin/nvi/docs/USD.doc/vi.ref/Makefile b/usr.bin/nvi/docs/USD.doc/vi.ref/Makefile
new file mode 100644 (file)
index 0000000..5b1628c
--- /dev/null
@@ -0,0 +1,35 @@
+#      $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+#
+#      @(#)Makefile    8.20 (Berkeley) 8/18/96
+
+DIR=           usd/13.viref
+SRCS=          vi.ref ex.cmd.roff set.opt.roff vi.cmd.roff ref.so
+MACROS=                -me
+CLEANFILES+=   vi.ref.txt vi.ref.ps index index.so
+
+all: vi.ref.txt vi.ref.ps
+
+vi.ref.txt: vi.ref index.so
+       ${TOOL_SOELIM} vi.ref | ${TOOL_TBL} | ${TOOL_ROFF_ASCII} ${MACROS} > $@
+       rm -f index
+       chmod 444 $@
+
+vi.ref.ps: vi.ref index.so
+       ${TOOL_SOELIM} vi.ref | ${TOOL_TBL} | ${TOOL_ROFF_PS} ${MACROS} > $@
+       rm -f index
+       chmod 444 $@
+
+index.so: vi.ref
+       # Build index.so, side-effect of building the paper.
+       ${TOOL_SOELIM} vi.ref | ${TOOL_TBL} | \
+           ${TOOL_ROFF_PS} ${MACROS} > /dev/null
+       sed -e 's/MINUSSIGN/\\-/' \
+           -e 's/DOUBLEQUOTE/""/' \
+           -e "s/SQUOTE/'/" \
+           -e 's/ /__SPACE/g' < index | \
+       sort -u '-t     ' +0 -1 +1n | awk -f merge.awk | \
+       sed -e 's/__SPACE/ /g' > $@
+       rm -f index
+       chmod 444 $@
+
+.include <bsd.doc.mk>
diff --git a/usr.bin/nvi/docs/USD.doc/vi.ref/ex.cmd.roff b/usr.bin/nvi/docs/USD.doc/vi.ref/ex.cmd.roff
new file mode 100644 (file)
index 0000000..4bea084
--- /dev/null
@@ -0,0 +1,1926 @@
+.\"    $NetBSD: ex.cmd.roff,v 1.1 2008/09/02 09:25:39 christos Exp $
+.\"
+.\" Copyright (c) 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\"    Keith Bostic.  All rights reserved.
+.\"
+.\" See the LICENSE file for redistribution information.
+.\"
+.\"    @(#)ex.cmd.roff 8.41 (Berkeley) 8/17/96
+.\"
+.SH 1 "Ex Description"
+.pp
+The following words have special meanings for
+.CO ex
+commands.
+.KY "<end-of-file>"
+.IP "<end-of-file>"
+The end-of-file character is used to scroll the screen in the
+.CO ex
+editor.
+This character is normally
+.LI <control-D> .
+However, whatever character is set for the current terminal is supported
+as well as
+.LI <control-D> .
+.KY "line"
+.IP "line"
+A single-line address, given in any of the forms described in the
+section entitled
+.QB "Ex Addressing" .
+The default for
+.LI line
+is the current line.
+.KY "range"
+.IP "range"
+A line, or a pair of line addresses, separated by a comma or semicolon.
+(See the section entitled
+.QB "Ex Addressing"
+for more information.)
+The default for range is the current line
+.i only ,
+i.e.
+.QT \&.,. .
+A percent sign
+.PQ %
+stands for the range
+.QT 1,$ .
+The starting address must be less than, or equal to, the ending address.
+.KY "count"
+.IP "count"
+A positive integer, specifying the number of lines to be affected by
+the command; the default is 1.
+Generally, a count past the end-of-file may be specified, e.g. the
+command
+.QT "p 3000"
+in a 10 line file is acceptable, and will print from the current line
+through the last line in the file.
+.KY "flags"
+.IP "flags"
+One or more of the characters
+.QQ # ,
+.QQ p ,
+and
+.QQ l .
+When a command that accepts these flags completes, the addressed line(s)
+are written out as if by the corresponding
+.CO # ,
+.CO l
+or
+.CO p
+commands.
+In addition, any number of
+.QT +
+or
+.QT \-
+characters can be specified before, after, or during the flags, in which
+case the line written is not necessarily the one affected by the command,
+but rather the line addressed by the offset address specified.
+The default for
+.LI flags
+is none.
+.KY "file"
+.IP "file"
+A pattern used to derive a pathname; the default is the current file.
+File names are subjected to normal
+.XR sh 1
+word expansions.
+.pp
+Anywhere a file name is specified, it is also possible to use
+the special string
+.QT /tmp .
+This will be replaced with a temporary file name which can be used
+for temporary work, e.g.
+.QT ":e /tmp"
+creates and edits a new file.
+.pp
+If both a count and a range are specified for commands that use either,
+the starting line for the command is the
+.i last
+line addressed by the range, and
+.LI count - 1
+subsequent lines are affected by the command, e.g. the command
+.QT 2,3p4
+prints out lines 3, 4, 5 and 6.
+.pp
+When only a line or range is specified, with no command, the implied
+command is either a
+.CO list ,
+.CO number
+or
+.CO print
+command.
+The command used is the most recent of the three commands to have been
+used (including any use as a flag).
+If none of these commands have been used before, the
+.CO print
+command is the implied command.
+When no range or count is specified and the command line is a blank line,
+the current line is incremented by 1 and then the current line is displayed.
+.pp
+Zero or more whitespace characters may precede or follow the addresses,
+count, flags, or command name.
+Any object following a command name (such as buffer, file, etc.),
+that begins with an alphabetic character,
+should be separated from the command name by at least one whitespace
+character.
+.pp
+Any character, including
+.LI <carriage-return> ,
+.QT %
+and
+.QT #
+retain their literal value when preceded by a backslash.
+.SH 1 "Ex Commands"
+.pp
+The following section describes the commands available in the
+.CO ex
+editor.
+In each entry below, the tag line is a usage synopsis for the command.
+.pp
+Each command can be entered as the abbreviation
+(those characters in the synopsis command word preceding the
+.QQ [
+character),
+the full command (all characters shown for the command word,
+omitting the
+.QQ [
+and
+.QQ ]
+characters),
+or any leading subset of the full command down to the abbreviation.
+For example, the args command (shown as
+.QT ar[gs]
+in the synopsis)
+can be entered as
+.QT ar ,
+.QT arg
+or
+.QT args .
+.pp
+Each
+.CO ex
+command described below notes the new current line after it
+is executed, as well as any options that affect the command.
+.\" I cannot get a double quote to print to save my life.  The ONLY way
+.\" I've been able to get this to work is with the .tr command.
+.tr Q"
+.ds ms Q
+.KY DOUBLEQUOTE
+.IP "\*(ms"
+.tr QQ
+A comment.
+Command lines beginning with the double-quote character
+.PQ """"
+are ignored.
+This permits comments in editor scripts and startup files.
+.KY "<control-D>"
+.KY "<end-of-file>"
+.IP "<control-D>"
+.IP "<end-of-file>"
+Scroll the screen.
+Write the next N lines, where N is the value of the
+.OP scroll
+option.
+The command is the end-of-file terminal character, which may be
+different on different terminals.
+Traditionally, it is the
+.LI <control-D>
+key.
+.sp
+Historically, the
+.CO eof
+command ignored any preceding count, and the
+.LI <end-of-file>
+character was ignored unless it was entered as the first character
+of the command.
+This implementation treats it as a command
+.i only
+if entered as the first character of the command line, and otherwise
+treats it as any other character.
+.SS
+.SP Line:
+Set to the last line written.
+.SP Options:
+Affected by the
+.OP scroll
+option.
+.SE
+.KY "!"
+.IP "! argument(s)"
+.Ip "[range]! argument(s)"
+Execute a shell command, or filter lines through a shell command.
+In the first synopsis, the remainder of the line after the
+.QT !
+character is passed to the program named by the
+.OP shell
+option, as a single argument.
+.sp
+Within the rest of the line,
+.QT %
+and
+.QT #
+are expanded into the current and alternate pathnames, respectively.
+The character
+.QT !
+is expanded with the command text of the previous
+.CO !
+command.
+(Therefore, the command
+.CO !!
+repeats the previous
+.CO !
+command.)
+The special meanings of
+.QT % ,
+.QT # ,
+and
+.QT !
+can be overridden by escaping them with a backslash.
+If no
+.CO !
+or
+.CO :!
+command has yet been executed, it is an error to use an unescaped
+.QT !
+character.
+The
+.CO !
+command does
+.i not
+do shell expansion on the strings provided as arguments.
+If any of the above expansions change the command the user entered,
+the command is redisplayed at the bottom of the screen.
+.sp
+.CO Ex
+then executes the program named by the
+.OP shell
+option, with a
+.b \-c
+flag followed by the arguments (which are bundled into a single argument).
+.sp
+The
+.CO !
+command is permitted in an empty file.
+.sp
+If the file has been modified since it was last completely written,
+the
+.Co !
+command will warn you.
+.sp
+A single
+.QT !
+character is displayed when the command completes.
+.sp
+In the second form of the
+.CO !
+command, the remainder of the line after the
+.QT !
+is passed to the program named by the
+.OP shell
+option, as described above.
+The specified lines are passed to the program as standard input,
+and the standard and standard error output of the program replace
+the original lines.
+.SS
+.SP Line:
+Unchanged if no range was specified, otherwise set to the first
+line of the range.
+.SP Options:
+Affected by the
+.OP shell
+and
+.OP warn
+options.
+.SE
+.KY "#"
+.IP "[range] # [count] [flags]"
+.KY "number"
+.Ip "[range] nu[mber] [count] [flags]"
+Display the selected lines, each preceded with its line number.
+.sp
+The line number format is
+.QQ %6d ,
+followed by two spaces.
+.SS
+.SP Line:
+Set to the last line displayed.
+.SP Options:
+Affected by the
+.OP list
+option.
+.SE
+.KY "@"
+.IP "@ buffer"
+.KY "*"
+.Ip "* buffer"
+Execute a buffer.
+Each line in the named buffer is executed as an
+.CO ex
+command.
+If no buffer is specified, or if the specified buffer is
+.QT @
+or
+.QT * ,
+the last buffer executed is used.
+.KY <
+.IP "[range] <[< ...] [count] [flags]"
+Shift lines left or right.
+The specified lines are shifted to the left (for the
+.CO <
+command) or right (for the
+.CO >
+command), by the number of columns specified by the
+.OP shiftwidth
+option.
+Only leading whitespace characters are deleted when shifting left;
+once the first column of the line contains a nonblank character,
+the
+.CO shift
+command will succeed, but the line will not be modified.
+.sp
+If the command character
+.CO <
+or
+.CO >
+is repeated more than once, the command is repeated once for each
+additional command character.
+.SS
+.SP Line:
+If the current line is set to one of the lines that are affected
+by the command, it is unchanged.
+Otherwise, it is set to the first nonblank character of the lowest
+numbered line shifted.
+.SP Options:
+Affected by the
+.OP shiftwidth
+option.
+.SE
+.KY =
+.IP "[line] = [flags]"
+Display the line number of
+.LI line
+(which defaults to the last line in the file).
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY >
+.IP "[range] >[> ...] [count] [flags]"
+Shift right.
+The specified lines are shifted to the right by the number of columns
+specified by the
+.OP shiftwidth
+option, by inserting tab and space characters.
+Empty lines are not changed.
+.sp
+If the command character
+.QT >
+is repeated more than once, the command is repeated once for each
+additional command character.
+.SS
+.SP Line:
+Set to the last line modified by the command.
+.SP Options:
+Affected by the
+.OP shiftwidth
+option.
+.SE
+.KY abbrev
+.IP "ab[brev] lhs rhs"
+Add an abbreviation to the current abbreviation list.
+When inserting text in
+.CO vi ,
+each time a non-word character is entered after a word character,
+a set of characters ending at the word character are checked for
+a match with
+.LI lhs .
+If a match is found, they are replaced with
+.LI rhs .
+The set of characters that are checked for a match are defined as follows,
+for inexplicable historical reasons.
+If only one or two characters were entered before the non-word character
+that triggered the check,
+and after the beginning of the insertion,
+or the beginning of the line or the file,
+or the last
+.LI <blank>
+character that was entered,
+then the one or the both characters are checked for a match.
+Otherwise, the set includes both characters,
+as well as the characters that precede them that are the same word
+class (i.e. word or non-word) as the
+.b second
+to last character entered before the non-word character that triggered
+the check,
+back to the first
+.LI <blank> character,
+the beginning of the insertion,
+or the beginning of the line or the file.
+.sp
+For example, the abbreviations:
+.sp
+.ne 3v
+.ft C
+.TS
+r l l.
+:abbreviate    abc     ABC
+:abbreviate    #i      #include
+:abbreviate    /*#i    /*#include
+.TE
+.ft R
+will all work, while the abbreviations:
+.sp
+.ne 2v
+.ft C
+.TS
+r l l.
+:abbreviate    a#i     A#include
+:abbreviate    /*      /********************
+.TE
+.ft R
+will not work, and are not permitted by
+.CO nvi .
+.sp
+To keep the abbreviation expansion from happening,
+the character immediately following the
+.LI lhs
+characters should be quoted with a
+.LI <literal-next>
+character.
+.sp
+The replacement
+.LI rhs
+is itself subject to both further abbreviation expansion and further
+map expansion.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY append
+.IP "[line] a[ppend][!]"
+The input text is appended to the specified line.
+If line 0 is specified, the text is inserted at the beginning of the file.
+Set to the last line input.
+If no lines are input, then set to
+.LI line ,
+or to the first line of the file if a
+.LI line
+of 0 was specified.
+Following the command name with a
+.QT !
+character causes the
+.OP autoindent
+option to be toggled for the duration of the command.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP autoindent
+and
+.OP number
+options.
+.SE
+.KY args
+.IP "ar[gs]"
+Display the argument list.
+The current argument is displayed inside of
+.QT [
+and
+.QT ]
+characters.
+The argument list is the list of operands specified on startup,
+which can be replaced using the
+.CO next
+command.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY bg
+.IP bg
+.CO Vi
+mode only.
+Background the current screen.
+The screen is unchanged,
+but is no longer accessible and disappears from the display.
+Use the
+.CO fg
+command to bring the screen back to the display foreground.
+.SS
+.SP Line:
+Set to the current line when the screen was last edited.
+.SP Options:
+None.
+.SE
+.KY change
+.IP "[range] c[hange][!] [count]"
+Replace the lines with input text.
+Following the command name with a
+.QT !
+character causes the
+.OP autoindent
+option to be toggled for the duration of the command.
+.SS
+.SP Line:
+Set to the last line input, or, if no lines were input,
+set to the line before the target line, or to the first
+line of the file if there are no lines preceding the target line.
+.SP Options:
+Affected by the
+.OP autoindent
+and
+.OP number
+options.
+.SE
+.KY cd
+.KY chdir
+.IP "chd[ir][!] [directory]"
+.Ip "cd[!] [directory]"
+Change the current working directory.
+The
+.LI directory
+argument is subjected to
+.XR sh 1
+word expansions.
+When invoked with no directory argument and the
+.LI HOME
+environment variable is set, the directory named by the
+.LI HOME
+environment variable becomes the new current directory.
+Otherwise, the new current directory becomes the directory returned
+by the
+.XR getpwent 3
+routine.
+.sp
+The
+.CO chdir
+command will fail if the file has been modified since the last complete
+write of the file.
+You can override this check by appending a
+.QT !
+character to the command.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP cdpath
+option.
+.SE
+.KY copy
+.KY t
+.IP "[range] co[py] line [flags]"
+.Ip "[range] t line [flags]"
+Copy the specified lines (range) after the destination line.
+Line 0 may be specified to insert the lines at the beginning of
+the file.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY cscope
+.IP "cs[cope] command [args]"
+Execute a
+.CO cscope
+command.
+For more information, see the section of the reference manual entitled
+.QB "Tags, Tag Stacks, and Cscope" .
+.KY delete
+.IP "[range] d[elete] [buffer] [count] [flags]"
+Delete the lines from the file.
+The deleted text is saved in the specified buffer, or, if no buffer
+is specified, in the unnamed buffer.
+If the command name is followed by a letter that could be interpreted
+as either a buffer name or a flag value (because neither a
+.LI count
+or
+.LI flags
+values were given),
+.CO ex
+treats the letter as a
+.LI flags
+value if the letter immediately follows the command name,
+without any whitespace separation.
+If the letter is preceded by whitespace characters,
+it treats it as a buffer name.
+.SS
+.SP Line:
+Set to the line following the deleted lines,
+or to the last line if the deleted lines were at the end.
+.SP Options:
+None.
+.SE
+.KY display
+.IP "di[splay] b[uffers] | c[onnections] | s[creens] | t[ags]"
+Display buffers,
+.CO cscope
+connections, screens or tags.
+The
+.CO display
+command takes one of three additional arguments, which are as follows:
+.SS
+.SP b[uffers]
+Display all buffers (including named, unnamed, and numeric)
+that contain text.
+.SP c[onnections]
+Display the source directories for all attached
+.CO cscope
+databases.
+.SP s[creens]
+Display the file names of all background screens.
+.SP t[ags]
+Display the tags stack.
+.SE
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY edit
+.IP "e[dit][!] [+cmd] [file]"
+.Ip "ex[!] [+cmd] [file]"
+Edit a different file.
+If the current buffer has been modified since the last complete write,
+the command will fail.
+You can override this by appending a
+.QT !
+character to the command name.
+.sp
+If the
+.QT +cmd
+option is specified, that
+.CO ex
+command will be executed in the new file.
+Any
+.CO ex
+command may be used, although the most common use of this feature is
+to specify a line number or search pattern to set the initial location
+in the new file.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Edit
+or
+.CO Ex ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS
+.SP Line:
+If you have previously edited the file, the current line will be set
+to your last position in the file.
+If that position does not exist, or you have not previously edited the
+file, the current line will be set to the first line of the file if
+you are in
+.CO vi
+mode, and the last line of the file if you are in
+.CO ex .
+.SP Options:
+None.
+.SE
+.KY exusage
+.IP "exu[sage] [command]"
+Display usage for an
+.CO ex
+command.
+If
+.LI command
+is specified, a usage statement for that command is displayed.
+Otherwise, usage statements for all
+.CO ex
+commands are displayed.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY file
+.IP "f[ile] [file]"
+Display and optionally change the file name.
+If a file name is specified, the current pathname is changed to the
+specified name.
+The current pathname, the number of lines, and the current position
+in the file are displayed.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY fg
+.IP "fg [name]"
+.CO Vi
+mode only.
+Foreground the specified screen.
+If the argument name doesn't exactly match the name of a file displayed
+by a background screen,
+it is compared against the last component of each of the file names.
+If no background screen is specified,
+the first background screen is foregrounded.
+.sp
+By default,
+foregrounding causes the current screen to be swapped with the backgrounded
+screen.
+Capitalizing the first letter of the command, i.e.
+.CO Fg ,
+will foreground the backgrounded screen in a new screen instead of
+swapping it with the current screen.
+.SS
+.SP Line:
+Set to the current line when the screen was last edited.
+.SP Options:
+None.
+.SE
+.KY global
+.IP "[range] g[lobal] /pattern/ [commands]"
+.KY v
+.Ip "[range] v /pattern/ [commands]"
+Apply commands to lines matching (or not matching) a pattern.
+The lines within the given range that match
+.PQ g[lobal] ,
+or do not match
+.PQ v
+the given pattern are selected.
+Then, the specified
+.CO ex
+command(s) are executed with the current line
+.PQ \&.
+set to each selected line.
+If no range is specified, the entire file is searched for matching,
+or not matching, lines.
+.sp
+Multiple commands can be specified, one per line, by escaping each
+.LI <newline>
+character with a backslash, or by separating commands with a
+.QT |
+character.
+If no commands are specified, the command defaults to the
+.CO print
+command.
+.sp
+For the
+.CO append ,
+.CO change
+and
+.CO insert
+commands, the input text must be part of the global command line.
+In this case, the terminating period can be omitted if it ends the commands.
+.sp
+The
+.CO visual
+command may also be specified as one of the
+.CO ex
+commands.
+In this mode, input is taken from the terminal.
+Entering a
+.CO Q
+command in
+.CO vi
+mode causes the next line matching the pattern to be selected and
+.CO vi
+to be reentered, until the list is exhausted.
+.sp
+The
+.CO global ,
+.CO v
+and
+.CO undo
+commands cannot be used as part of these commands.
+.sp
+The editor options
+.OP autoindent ,
+.OP autoprint
+and
+.OP report
+are turned off for the duration of the
+.CO global
+and
+.CO v
+commands.
+.SS
+.SP Line:
+The last line modified.
+.SP Options:
+Affected by the
+.OP ignorecase
+and
+.OP magic
+options.
+Turns off the
+.OP autoindent ,
+.OP autoprint
+and
+.OP report
+options.
+.SE
+.KY help
+.IP "he[lp]"
+Display a help message.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY insert
+.IP "[line] i[nsert][!]"
+The input text is inserted before the specified line.
+Following the command name with a
+.QT !
+character causes the
+.OP autoindent
+option setting to be toggled for the duration of this command.
+.SS
+.SP Line:
+Set to the last line input; if no lines were input,
+set to the line before the target line, or to the first line
+of the file if there are no lines preceding the target line.
+Affected by the
+.OP autoindent
+and
+.OP number
+options.
+.SE
+.KY join
+.IP "[range] j[oin][!] [count] [flags]"
+Join lines of text together.
+.sp
+A
+.LI count
+specified to the
+.Sy join
+command specifies that the last line of the
+.LI range
+plus
+.LI count
+subsequent lines will be joined.
+(Note, this differs by one from the general rule where only
+.LI count - 1
+subsequent lines are affected.)
+.sp
+If the current line ends with a whitespace character, all whitespace
+is stripped from the next line.
+Otherwise, if the next line starts with a open parenthesis
+.PQ ( ,
+do nothing.
+Otherwise, if the current line ends with a question mark
+.PQ ? ,
+period
+.PQ \&.
+or exclamation point
+.PQ ! ,
+insert two spaces.
+Otherwise, insert a single space.
+.sp
+Appending a
+.QT !
+character to the command name causes a simpler join with no
+white-space processing.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY list
+.IP "[range] l[ist] [count] [flags]"
+Display the lines unambiguously.
+Tabs are displayed as
+.QT ^I ,
+and the end of the line is marked with a
+.QT $
+character.
+.SS
+.SP Line:
+Set to the last line displayed.
+.SP Options:
+Affected by the
+.OP number
+option.
+.SE
+.KY map
+.IP "map[!] [lhs rhs]"
+Define or display maps (for
+.CO vi
+only).
+.sp
+If
+.QT lhs
+and
+.QT rhs
+are not specified, the current set of command mode maps are displayed.
+If a
+.QT !
+character is appended to to the command,
+the text input mode maps are displayed.
+.sp
+Otherwise, when the
+.QT lhs
+character sequence is entered in
+.CO vi ,
+the action is as if the corresponding
+.QT rhs
+had been entered.
+If a
+.QT !
+character is appended to the command name,
+the mapping is effective during text input mode,
+otherwise, it is effective during command mode.
+This allows
+.QT lhs
+to have two different macro definitions at the same time: one for command
+mode and one for input mode.
+.sp
+Whitespace characters require escaping with a
+.LI <literal-next>
+character to be entered in the
+.LI lhs
+string in visual mode.
+.sp
+Normally, keys in the
+.LI rhs
+string are remapped (see the
+.OP remap
+option),
+and it is possible to create infinite loops.
+However, keys which map to themselves are not further remapped,
+regardless of the setting of the
+.OP remap
+option.
+For example, the command
+.QT ":map n nz."
+maps the
+.QT n
+key to the
+.CO n
+and
+.CO z
+commands.
+.sp
+To exit an infinitely looping map, use the terminal
+.LI <interrupt>
+character.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP remap
+option.
+.SE
+.KY mark
+.KY k
+.IP "[line] ma[rk] <character>"
+.Ip "[line] k <character>"
+Mark the line with the mark
+.LI <character> .
+The expressions
+.QT '<character>
+and
+.QT `<character>
+can then be used as an address in any command that uses one.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY move
+.IP "[range] m[ove] line"
+Move the specified lines after the target line.
+A target line of 0 places the lines at the beginning of the file.
+.SS
+.SP Line:
+Set to the first of the moved lines.
+.SP Options:
+None.
+.SE
+.KY mkexrc
+.IP "mk[exrc][!] file"
+Write the abbreviations, editor options and maps to the specified
+file.
+Information is written in a form which can later be read back in
+using the
+.CO ex
+.CO source
+command.
+If
+.LI file
+already exists, the
+.CO mkexrc
+command will fail.
+This check can be overridden by appending a
+.QT !
+character to the command.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY next
+.IP "n[ext][!] [file ...]"
+Edit the next file from the argument list.
+The
+.CO next
+command will fail if the file has been modified since the last complete
+write.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+The argument list can optionally be replaced by specifying a new one
+as arguments to this command.
+In this case, editing starts with the first file on the new list.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Next ,
+while in
+.CO vi
+mode, will set the argument list and edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS
+.SP Line:
+Set as described for the
+.CO edit
+command.
+.SP Options:
+Affected by the options
+.OP autowrite
+and
+.OP writeany .
+.SE
+.KY open
+.IP "[line] o[pen] /pattern/ [flags]"
+Enter open mode.
+Open mode is the same as being in
+.CO vi ,
+but with a one-line window.
+All the standard
+.CO vi
+commands are available.
+If a match is found for the optional RE argument,
+the cursor is set to the start of the matching pattern.
+.sp
+.i "This command is not yet implemented."
+.SS
+.SP Line:
+Unchanged, unless the optional RE is specified, in which case it is
+set to the line where the matching pattern is found.
+.SP Options:
+Affected by the
+.OP open
+option.
+.SE
+.KY preserve
+.IP "pre[serve]"
+Save the file in a form that can later be recovered using the
+.CO ex
+.b \-r
+option.
+When the file is preserved, an email message is sent to the user.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY previous
+.IP "prev[ious][!]"
+Edit the previous file from the argument list.
+The
+.CO previous
+command will fail if the file has been modified since the last complete
+write.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Previous ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS
+.SP Line:
+Set as described for the
+.CO edit
+command.
+.SP Options:
+Affected by the options
+.OP autowrite
+and
+.OP writeany .
+None.
+.SE
+.KY print
+.IP "[range] p[rint] [count] [flags]"
+Display the specified lines.
+.SS
+.SP Line:
+Set to the last line displayed.
+.SP Options:
+Affected by the
+.OP list
+and
+.OP number
+option.
+.SE
+.KY put
+.IP "[line] pu[t] [buffer]"
+Append buffer contents to the current line.
+If a buffer is specified, its contents are appended to the line,
+otherwise, the contents of the unnamed buffer are used.
+.SS
+.SP Line:
+Set to the line after the current line.
+.SP Options:
+None.
+.SE
+.KY quit
+.IP "q[uit][!]"
+End the editing session.
+If the file has been modified since the last complete write, the
+.CO quit
+command will fail.
+This check may be overridden by appending a
+.QT !
+character to the command.
+.sp
+If there are more files to edit, the
+.CO quit
+command will fail.
+Appending a
+.QT !
+character to the command name or entering two
+.CO quit
+commands (i.e.
+.CO wq ,
+.CO quit ,
+.CO xit
+or
+.CO ZZ )
+in a row) will override this check and the editor will exit.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY read
+.IP "[line] r[ead][!] [file]"
+Read a file.
+A copy of the specified file is appended to the line.
+If
+.LI line
+is 0, the copy is inserted at the beginning of the file.
+If no file is specified, the current file is read; if there is no
+current file, then
+.LI file
+becomes the current file.
+If there is no current file and no
+.LI file
+is specified, then the
+.CO read
+command will fail.
+.sp
+If
+.LI file
+is preceded by a
+.QT !
+character,
+.LI file
+is treated as if it were a shell command, and passed to the program
+named by the
+.OP shell
+edit option.
+The standard and standard error outputs of that command are read into
+the file after the specified line.
+The special meaning of the
+.QT !
+character can be overridden by escaping it with a backslash
+.PQ \e
+character.
+.SS
+.SP Line:
+When executed from
+.CO ex ,
+the current line is set to the last line read.
+When executed from
+.CO vi ,
+the current line is set to the first line read.
+.SP Options:
+None.
+.SE
+.KY recover
+.IP "rec[over] file"
+Recover
+.LI file
+if it was previously saved.
+If no saved file by that name exists, the
+.CO recover
+command behaves equivalently to the
+.CO edit
+command.
+.SS
+.SP Line:
+Set as described for the
+.CO edit
+command.
+.SP Options:
+None.
+.SE
+.KY resize
+.IP "res[ize] [+|-]size"
+.CO Vi
+mode only.
+Grow or shrink the current screen.
+If
+.LI size
+is a positive, signed number, the current screen is grown by that many lines.
+If
+.LI size
+is a negative, signed number, the current screen is shrunk by that many lines.
+If
+.LI size
+is not signed, the current screen is set to the specified
+.LI size .
+Applicable only to split screens.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY rewind
+.IP "rew[ind][!]"
+Rewind the argument list.
+If the current file has been modified since the last complete write,
+the
+.CO rewind
+command will fail.
+This check may be overridden by appending the
+.QT !
+character to the command.
+.sp
+Otherwise, the current file is set to the first file in the argument
+list.
+.SS
+.SP Line:
+Set as described for the
+.CO edit
+command.
+.SP Options:
+Affected by the
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY set
+.IP "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
+Display or set editor options.
+When no arguments are specified, the editor option
+.OP term ,
+and any editor options whose values have been changed from the
+default settings are displayed.
+If the argument
+.LI all
+is specified, the values of all of editor options are displayed.
+.sp
+Specifying an option name followed by the character
+.QT ?
+causes the current value of that option to be displayed.
+The
+.QT ?
+can be separated from the option name by whitespace characters.
+The
+.QT ?
+is necessary only for Boolean valued options.
+Boolean options can be given values by the form
+.QT "set option"
+to turn them on, or
+.QT "set nooption"
+to turn them off.
+String and numeric options can be assigned by the form
+.QT "set option=value" .
+Any whitespace characters in strings can be included literally by preceding
+each with a backslash.
+More than one option can be set or listed by a single set command,
+by specifying multiple arguments, each separated from the next by
+whitespace characters.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY shell
+.IP "sh[ell]"
+Run the shell program.
+The program named by the
+.OP shell
+option is run with a
+.b \-i
+(for interactive) flag.
+Editing is resumed when that program exits.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP shell
+option.
+.SE
+.KY source
+.IP "so[urce] file"
+Read and execute
+.CO ex
+commands from a file.
+.CO Source
+commands may be nested.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY substitute
+.IP "[range] s[ubstitute] [/pattern/replace/] [options] [count] [flags]"
+.KY &
+.Ip "[range] & [options] [count] [flags]"
+.KY ~
+.Ip "[range] ~ [options] [count] [flags]"
+Make substitutions.
+Replace the first instance of
+.LI pattern
+with the string
+.LI replace
+on the specified line(s).
+If the
+.QT /pattern/repl/
+argument is not specified, the
+.QT /pattern/repl/
+from the previous
+.CO substitute
+command is used.
+Any character other than an alphabetic, numeric, <blank> or backslash
+character may be used as the delimiter.
+.sp
+If
+.LI options
+includes the letter
+.QT c
+(confirm), you will be prompted for confirmation before each replacement
+is done.
+An affirmative response (in English, a
+.QT y
+character) causes the replacement to be made.
+A quit response (in English, a
+.QT q
+character) causes the
+.CO substitute
+command to be terminated.
+Any other response causes the replacement not to be made, and the
+.CO substitute
+command continues.
+If
+.LI options
+includes the letter
+.QT g
+(global), all nonoverlapping instances of
+.LI pattern
+in the line are replaced.
+.sp
+The
+.CO &
+version of the command is the same as not specifying a pattern
+or replacement string to the
+.CO substitute
+command, and the
+.QT &
+is replaced by the pattern and replacement information from the
+previous substitute command.
+.sp
+The
+.CO ~
+version of the command is the same as
+.CO &
+and
+.CO s ,
+except that the search pattern used is the last RE used in
+.i any
+command, not necessarily the one used in the last
+.CO substitute
+command.
+.sp
+For example, in the sequence
+.ft C
+.(b
+s/red/blue/
+/green
+~
+.)b
+.ft R
+the
+.QT ~
+is equivalent to
+.QT s/green/blue/ .
+.sp
+The
+.CO substitute
+command may be interrupted, using the terminal interrupt character.
+All substitutions completed before the interrupt are retained.
+.SS
+.SP Line:
+Set to the last line upon which a substitution was made.
+.SP Options:
+Affected by the
+.OP ignorecase
+and
+.OP magic
+option.
+.SE
+.KY suspend
+.IP "su[spend][!]"
+.KY stop
+.Ip "st[op][!]"
+.KY <control-Z>
+.Ip <control-Z>
+Suspend the edit session.
+Appending a
+.QT !
+character to these commands turns off the
+.OP autowrite
+option for the command.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY tag
+.IP "ta[g][!] tagstring"
+Edit the file containing the specified tag.
+If the tag is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+.CO tag
+command will fail.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+.sp
+The
+.CO tag
+command searches for
+.LI tagstring
+in the tags file(s) specified by the
+.Op tags
+option.
+(See
+.XR ctags 1
+for more information on tags files.)
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Tag ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the
+.OP autowrite ,
+.OP taglength ,
+.OP tags
+and
+.OP writeany
+options.
+.SE
+.KY tagnext
+.IP "tagn[ext][!]"
+Edit the file containing the next context for the current tag.
+If the context is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+.CO tagnext
+command will fail.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Tagnext ,
+while in 
+.CO vi 
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS 
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the 
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY tagpop
+.IP "tagp[op][!] [file | number]"
+Pop to the specified tag in the tags stack.
+If neither
+.LI file
+or
+.LI number
+is specified, the
+.CO tagpop
+command pops to the most recent entry on the tags stack.
+If
+.LI file
+or
+.LI number
+is specified, the
+.CO tagpop
+command pops to the most recent entry in the tags stack for that file,
+or numbered entry in the tags stack, respectively.
+(See the
+.CO display
+command for information on displaying the tags stack.)
+.sp
+If the file has been modified since the last complete write, the
+.CO tagpop
+command will fail.
+This check may be overridden by appending a
+.QT !
+character to the command name.
+.SS
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY tagprev
+.IP "tagpr[ev][!]"
+Edit the file containing the previous context for the current tag.
+If the context is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+.CO tagprev
+command will fail.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Tagprev ,
+while in 
+.CO vi 
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS 
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the 
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY tagtop
+.IP "tagt[op][!]"
+Pop to the least recent tag on the tags stack, clearing the tags stack.
+.sp
+If the file has been modified since the last complete write, the
+.CO tagtop
+command will fail.
+This check may be overridden by appending a
+.QT !
+character to the command name.
+.SS
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY unabbrev
+.IP "una[bbrev] lhs"
+Delete an abbreviation.
+Delete
+.LI lhs
+from the current list of abbreviations.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY undo
+.IP "u[ndo]"
+Undo the last change made to the file.
+Changes made by
+.CO global ,
+.CO v ,
+.CO visual
+and map sequences are considered a single command.
+If repeated, the
+.CO u
+command alternates between these two states, and is its own inverse.
+.SS
+.SP Line:
+Set to the last line modified by the command.
+.SP Options:
+None.
+.SE
+.KY unmap
+.IP "unm[ap][!] lhs"
+Unmap a mapped string.
+Delete the command mode map definition for
+.LI lhs .
+If a
+.QT !
+character is appended to the command name, delete the text input mode
+map definition instead.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY version
+.IP "ve[rsion]"
+Display the version of the
+.CO ex/vi
+editor.
+.KY visual
+.IP "[line] vi[sual] [type] [count] [flags]"
+.CO Ex
+mode only.
+Enter
+.CO vi .
+The
+.LI type
+is optional, and can be
+.QT \- ,
+.QT +
+or
+.QT ^ ,
+as in the
+.CO ex
+.CO z
+command, to specify the position of the specified line in the screen
+window.
+(The default is to place the line at the top of the screen window.)
+A
+.LI count
+specifies the number of lines that will initially be displayed.
+(The default is the value of the
+.OP window
+editor option.)
+.SS
+.SP Line:
+Unchanged unless
+.LI line
+is specified, in which case it is set to that line.
+.SP Options:
+None.
+.SE
+.KY visual
+.IP "vi[sual][!] [+cmd] [file]"
+.CO Vi
+mode only.
+Edit a new file.
+Identical to the
+.QT "edit[!] [+cmd] [file]"
+command.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Visual ,
+will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.KY viusage
+.IP "viu[sage] [command]"
+Display usage for a
+.CO vi
+command.
+If
+.LI command
+is specified, a usage statement for that command is displayed.
+Otherwise, usage statements for all
+.CO vi
+commands are displayed.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY write
+.IP "[range] w[rite][!] [>>] [file]"
+.Ip "[range] w[rite] [!] [file]"
+.KY wn
+.Ip "[range] wn[!] [>>] [file]"
+.KY wq
+.Ip "[range] wq[!] [>>] [file]"
+Write the file.
+The specified lines (the entire file, if no range is given) is written
+to
+.LI file .
+If
+.LI file
+is not specified, the current pathname is used.
+If
+.LI file
+is specified, and it exists, or if the current pathname was set using the
+.CO file
+command, and the file already exists, these commands will fail.
+Appending a
+.QT !
+character to the command name will override this check and the write
+will be attempted, regardless.
+.sp
+Specifying the optional
+.QT >>
+string will cause the write to be appended to the file, in which case
+no tests are made for the file already existing.
+.sp
+If the file is preceded by a
+.QT !
+character, the program named by the shell edit option is
+invoked with file as its second argument, and the specified
+lines are passed as standard input to that command.
+The
+.QT !
+in this usage must be separated from command name by at least one
+whitespace character.
+The special meaning of the
+.QT !
+may be overridden by escaping it with a backslash
+.PQ \e
+character.
+.sp
+The
+.CO wq
+version of the write command will exit the editor after writing the file,
+if there are no further files to edit.
+Appending a
+.QT !
+character to the command name or entering two
+.QQ quit
+commands (i.e.
+.CO wq ,
+.CO quit ,
+.CO xit
+or
+.CO ZZ )
+in a row) will override this check and the editor will exit,
+ignoring any files that have not yet been edited.
+.sp
+The
+.CO wn
+version of the write command will move to the next file after writing
+the file, unless the write fails.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP readonly
+and
+.OP writeany
+options.
+.SE
+.KY xit
+.IP "[range] x[it][!] [file]"
+Write the file if it has been modified.
+The specified lines are written to
+.LI file ,
+if the file has been modified since the last complete write to any
+file.
+If no
+.LI range
+is specified, the entire file is written.
+.sp
+The
+.CO xit
+command will exit the editor after writing the file,
+if there are no further files to edit.
+Appending a
+.QT !
+character to the command name or entering two
+.QQ quit
+commands (i.e.
+.CO wq ,
+.CO quit ,
+.CO xit
+or
+.CO ZZ )
+in a row) will override this check and the editor will exit,
+ignoring any files that have not yet been edited.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+Affected by the
+.OP readonly
+and
+.OP writeany
+options.
+.SE
+.KY yank
+.IP "[range] ya[nk] [buffer] [count]"
+Copy the specified lines to a buffer.
+If no buffer is specified, the unnamed buffer is used.
+.SS
+.SP Line:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY z
+.IP "[line] z [type] [count] [flags]"
+Adjust the window.
+If no
+.LI type
+is specified, then
+.LI count
+lines following the specified line are displayed.
+The default
+.LI count
+is the value of the
+.OP window
+option.
+The
+.LI type
+argument changes the position at which
+.LI line
+is displayed on the screen by changing the number of lines
+displayed before and after
+.LI line .
+The following
+.LI type
+characters may be used:
+.SS
+.SP \-
+Place the line at the bottom of the screen.
+.SP +
+Place the line at the top of the screen.
+.SP \&.
+Place the line in the middle of the screen.
+.SP ^
+Write out count lines starting
+.LI "count * 2"
+lines before
+.LI line ;
+the net effect of this is that a
+.QT z^
+command following a
+.CO z
+command writes the previous page.
+.SP =
+Center
+.LI line
+on the screen with a line of hyphens displayed immediately before and
+after it.
+The number of preceding and following lines of text displayed are
+reduced to account for those lines.
+.SE
+.SS
+.SP Line:
+Set to the last line displayed, with the exception of the
+.Dq Li \&=
+.LI type ,
+where the current line is set to the line specified by the command.
+.SP Options:
+Affected by the
+.OP scroll
+option.
+.SE
diff --git a/usr.bin/nvi/docs/USD.doc/vi.ref/merge.awk b/usr.bin/nvi/docs/USD.doc/vi.ref/merge.awk
new file mode 100644 (file)
index 0000000..8453b1d
--- /dev/null
@@ -0,0 +1,18 @@
+#      $NetBSD: merge.awk,v 1.1 2008/09/02 09:25:39 christos Exp $
+#
+#      @(#)merge.awk   8.3 (Berkeley) 5/25/94
+#
+# merge index entries into one line per label
+$1 == prev {
+       printf ", %s", $2;
+       next;
+}
+{
+       if (NR != 1)
+               printf "\n";
+       printf "%s \t%s", $1, $2;
+       prev = $1;
+}
+END {
+       printf "\n"
+}
diff --git a/usr.bin/nvi/docs/USD.doc/vi.ref/set.opt.roff b/usr.bin/nvi/docs/USD.doc/vi.ref/set.opt.roff
new file mode 100644 (file)
index 0000000..e37343c
--- /dev/null
@@ -0,0 +1,1312 @@
+.\"    $NetBSD: set.opt.roff,v 1.1 2008/09/02 09:25:39 christos Exp $
+.\"
+.\" Copyright (c) 1994
+.\"     The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\"    Keith Bostic.  All rights reserved.
+.\"
+.\" See the LICENSE file for redistribution information.
+.\"
+.\"     @(#)set.opt.roff       8.66 (Berkeley) 10/10/96
+.\"
+.SH 1 "Set Options"
+.pp
+There are a large number of options that may be set (or unset) to
+change the editor's behavior.
+This section describes the options, their abbreviations and their
+default values.
+.pp
+In each entry below, the first part of the tag line is the full name
+of the option, followed by any equivalent abbreviations.
+(Regardless of the abbreviations, it is only necessary to use the
+minimum number of characters necessary to distinguish an abbreviation
+from all other commands for it to be accepted, in
+.EV nex nvi .
+Historically, only the full name and the official abbreviations
+were accepted by
+.EV ex vi .
+Using full names in your startup files and environmental variables will
+probably make them more portable.)
+The part in square brackets is the default value of the option.
+Most of the options are boolean, i.e. they are either on or off,
+and do not have an associated value.
+.pp
+Options apply to both
+.CO ex
+and
+.CO vi
+modes, unless otherwise specified.
+.pp
+With a few exceptions,
+all options are settable per screen, i.e. the
+.OP tags
+option can be set differently in each screen.
+The exceptions are the
+.OP columns ,
+.OP lines ,
+.OP secure
+and
+.OP term
+options.
+Changing these options modifies the respective information for all screens.
+.pp
+For information on modifying the options or to display the options and
+their current values, see the
+.QQ set
+command in the section entitled
+.QB "Ex Commands" .
+.KY altwerase
+.IP "altwerase [off]"
+.CO Vi
+only.
+Change how
+.CO vi
+does word erase during text input.
+When this option is set, text is broken up into three classes:
+alphabetic, numeric and underscore characters, other nonblank
+characters, and blank characters.
+Changing from one class to another marks the end of a word.
+In addition, the class of the first character erased is ignored
+(which is exactly what you want when erasing pathname components).
+.KY autoindent
+.IP "autoindent, ai [off]"
+If this option is set, whenever you create a new line (using the
+.CO vi
+.CO A ,
+.CO a ,
+.CO C ,
+.CO c ,
+.CO I ,
+.CO i ,
+.CO O ,
+.CO o ,
+.CO R ,
+.CO r ,
+.CO S ,
+and
+.CO s
+commands, or the
+.CO ex
+.CO append ,
+.CO change ,
+and
+.CO insert
+commands) the new line is automatically indented to align the cursor with
+the first nonblank character of the line from which you created it.
+Lines are indented using tab characters to the extent possible (based on
+the value of the
+.OP tabstop
+option) and then using space characters as necessary.
+For commands inserting text into the middle of a line, any blank characters
+to the right of the cursor are discarded, and the first nonblank character
+to the right of the cursor is aligned as described above.
+.sp
+The indent characters are themselves somewhat special.
+If you do not enter more characters on the new line before moving to
+another line, or entering
+.LI <escape> ,
+the indent character will be deleted and the line will be empty.
+For example, if you enter
+.LI <carriage-return>
+twice in succession,
+the line created by the first
+.LI <carriage-return>
+will not have any characters in it,
+regardless of the indentation of the previous or subsequent line.
+.sp
+Indent characters also require that you enter additional erase characters
+to delete them.
+For example,
+if you have an indented line, containing only blanks, the first
+.LI <word-erase>
+character you enter will erase up to end of the indent characters,
+and the second will erase back to the beginning of the line.
+(Historically, only the
+.LI <control-D>
+key would erase the indent characters.
+Both the
+.LI <control-D>
+key and the usual erase keys work in
+.CO nvi .)
+In addition, if the cursor is positioned at the end of the indent
+characters, the keys
+.QT 0<control-D>
+will erase all of the indent characters for the current line,
+resetting the indentation level to 0.
+Similarly, the keys
+.QT ^<control-D>
+will erase all of the indent characters for the current line,
+leaving the indentation level for future created lines unaffected.
+.sp
+Finally, if the
+.OP autoindent
+option is set, the
+.CO S
+and
+.CO cc
+commands change from the first nonblank of the line to the end of the
+line, instead of from the beginning of the line to the end of the line.
+.KY autoprint
+.IP "autoprint, ap [off]"
+.CO Ex
+only.
+Cause the current line to be automatically displayed after the
+.CO ex
+commands
+.CO < ,
+.CO > ,
+.CO copy ,
+.CO delete ,
+.CO join ,
+.CO move ,
+.CO put ,
+.CO t ,
+.CO Undo ,
+and
+.CO undo .
+This automatic display is suppressed during
+.CO global
+and
+.CO v
+commands, and for any command where optional flags are used to explicitly
+display the line.
+.KY autowrite
+.IP "autowrite, aw [off]"
+If this option is set, the
+.CO vi
+.CO ! ,
+.CO ^^ ,
+.CO ^]
+and
+.CO <control-Z>
+commands, and the
+.CO ex
+.CO edit ,
+.CO next ,
+.CO rewind ,
+.CO stop ,
+.CO suspend ,
+.CO tag ,
+.CO tagpop ,
+and
+.CO tagtop
+commands automatically write the current file back to the current file name
+if it has been modified since it was last written.
+If the write fails, the command fails and goes no further.
+.sp
+Appending the optional force flag character
+.QT !
+to the
+.CO ex
+commands
+.CO next ,
+.CO rewind ,
+.CO stop ,
+.CO suspend ,
+.CO tag ,
+.CO tagpop ,
+and
+.CO tagtop
+stops the automatic write from being attempted.
+.sp
+(Historically, the
+.CO next
+command ignored the optional force flag.)
+Note, the
+.CO ex
+commands
+.CO edit ,
+.CO quit ,
+.CO shell ,
+and
+.CO xit
+are
+.i not
+affected by the
+.OP autowrite
+option.
+.sp
+The
+.OP autowrite
+option is ignored if the file is considered read-only for any reason.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms backup [QQ]
+.KY backup
+.IP "\*(ms"
+.tr QQ
+If this option is set, it specifies a pathname used as a backup file,
+and, whenever a file is written, the file's current contents are copied
+to it.
+The pathname is
+.QT \&# ,
+.QT \&%
+and
+.QT \&!
+expanded.
+.sp
+If the first character of the pathname is
+.QT \&N ,
+a version number is appended to the pathname (and the
+.QT \&N
+character is then discarded).
+Version numbers are always incremented, and each backup file will have
+a version number one greater than the highest version number currently
+found in the directory.
+.sp
+Backup files must be regular files, owned by the real user ID of the
+user running the editor, and not accessible by any other user.
+.KY beautify
+.IP "beautify, bf [off]"
+If this option is set, all control characters that are not currently being
+specially interpreted, other than
+.LI <tab> ,
+.LI <newline> ,
+and
+.LI <form-feed> ,
+are
+discarded from commands read in by
+.CO ex
+from command files, and from input text entered to
+.CO vi
+(either into the file or to the colon command line).
+Text files read by
+.EV ex vi
+are
+.i not
+affected by the
+.OP beautify
+option.
+.KY cdpath
+.IP "cdpath [environment variable CDPATH, or current directory]"
+This option is used to specify a colon separated list of directories
+which are used as path prefixes for any relative path names used as
+arguments for the
+.CO cd
+command.
+The value of this option defaults to the value of the environmental
+variable
+.LI CDPATH
+if it is set, otherwise to the current directory.
+For compatibility with the POSIX 1003.2 shell, the
+.CO cd
+command does
+.i not
+check the current directory as a path prefix for relative path names
+unless it is explicitly specified.
+It may be so specified by entering an empty string or a
+.QT \&.
+character into the
+.LI CDPATH
+variable or the option value.
+.KY cedit
+.IP "cedit [no default]"
+This option adds the ability to edit the colon command-line history.
+This option is set to a string.
+Whenever the first character of that string is entered on the colon
+command line,
+you will enter a normal editing window on the collected commands that
+you've entered on the
+.CO vi
+colon command-line.
+You may then modify and/or execute the commands.
+All normal text editing is available,
+except that you cannot use
+.CO <control-W>
+to switch to an alternate screen.
+Entering a
+.CO <carriage-return>
+will execute the current line of the screen window as an ex command in
+the context of the screen from which you created the colon command-line
+screen,
+and you will then return to that screen.
+.sp
+Because of
+.CO vi \&'s
+parsing rules, it can be difficult to set the colon command-line edit
+character to the
+.LI <escape>
+character.
+To set it to
+.LI <escape> ,
+use
+.QT "set cedit=<literal-next><escape>" .
+.sp
+If the
+.OP cedit
+edit option is set to the same character as the
+.OP filec
+edit option,
+.CO vi
+will perform colon command-line editing if the character is entered as
+the first character of the line,
+otherwise,
+.CO vi
+will perform file name expansion.
+.KY columns
+.IP "columns, co [80]"
+The number of columns in the screen.
+Setting this option causes
+.EV ex vi
+to set (or reset) the environmental variable
+.LI COLUMNS .
+See the section entitled
+.QB "Sizing the Screen"
+more information.
+.KY comment
+.IP "comment [off]"
+.CO Vi
+only.
+If the first non-empty line of the file begins with the string
+.QT # ,
+.QT /\&*
+or
+.QT // ,
+this option causes
+.CO vi
+to skip to the end of that shell, C or C++ comment (probably a
+terribly boring legal notice) before displaying the file.
+.KY directory
+.IP "directory, dir [environment variable TMPDIR, or /tmp]"
+The directory where temporary files are created.
+The environmental variable
+.LI TMPDIR
+is used as the default value if it exists, otherwise
+.LI /tmp
+is used.
+.KY edcompatible
+.IP "edcompatible, ed [off]"
+Remember the values of the
+.QQ c
+and
+.QQ g
+suffixes to the
+.CO substitute
+commands, instead of initializing them as unset for each new
+command.
+Specifying pattern and replacement strings to the
+.CO substitute
+command unsets the
+.QQ c
+and
+.QQ g
+suffixes as well.
+.KY escapetime
+.IP "escapetime [1]"
+The 10th's of a second
+.EV ex vi
+waits for a subsequent key to complete an
+.LI <escape>
+key mapping.
+.KY errorbells
+.IP "errorbells, eb [off]"
+.CO Ex
+only.
+.CO Ex
+error messages are normally presented in inverse video.
+If that is not possible for the terminal, setting this option causes
+error messages to be announced by ringing the terminal bell.
+.KY exrc
+.IP "exrc, ex [off]"
+If this option is turned on in the EXINIT environment variables,
+or the system or $HOME startup files,
+the local startup files are read,
+unless they are the same as the system or $HOME startup files or
+fail to pass the standard permission checks.
+See the section entitled
+.QB "Startup Information"
+for more information.
+.KY extended
+.IP "extended [off]"
+This option causes all regular expressions to be treated as POSIX
+1003.2 Extended Regular Expressions (which are similar to historic
+.XR egrep 1
+style expressions).
+.KY filec
+.IP "filec [no default]"
+This option adds the ability to do shell expansion when entering input
+on the colon command line.
+This option is set to a string.
+Whenever the first character of that string is entered on the colon
+command line,
+the <blank> delimited string immediately before the cursor is expanded
+as if it were followed by a
+.LI \&*
+character, and file name expansion for the
+.CO ex
+edit command was done.
+If no match is found, the screen is flashed and text input resumed.
+If a single match results, that match replaces the expanded text.
+In addition, if the single match is for a directory, a
+.LI \&/
+character is appended and file completion is repeated.
+If more than a single match results,
+any unique prefix shared by the matches replaces the expanded text,
+the matches are displayed,
+and text input resumed.
+.sp
+Because of
+.CO vi \&'s
+parsing rules, it can be difficult to set the path completion character
+to two command values,
+.LI <escape>
+and
+.LI <tab> .
+To set it to
+.LI <escape> ,
+use
+.QT "set filec=<literal-next><escape>" .
+To set it to
+.LI <tab> ,
+use
+.QT "set filec=\e<tab>" .
+.sp
+If the
+.OP cedit
+edit option is set to the same character as the
+.OP filec
+edit option,
+.CO vi
+will perform colon command-line editing if the character is entered as
+the first character of the line,
+otherwise,
+.CO vi
+will perform file name expansion.
+.KY flash
+.IP "flash [on]"
+This option causes the screen to flash instead of beeping the keyboard,
+on error, if the terminal has the capability.
+.KY hardtabs
+.IP "hardtabs, ht [8]"
+This option defines the spacing between hardware tab settings, i.e.
+the tab expansion done by the operating system and/or the terminal
+itself.
+As
+.EV nex nvi
+never writes
+.LI <tab>
+characters to the terminal, unlike historic versions of
+.EV ex vi ,
+this option does not currently have any affect.
+.KY iclower
+.IP "iclower [off]"
+The
+.OP iclower
+edit option makes all Regular Expressions case-insensitive,
+as long as an upper-case letter does not appear in the search string.
+.KY ignorecase
+.IP "ignorecase, ic [off]"
+This option causes regular expressions, both in
+.CO ex
+commands and in searches,
+to be evaluated in a case-insensitive manner.
+.KY keytime
+.IP "keytime [6]"
+The 10th's of a second
+.EV ex vi
+waits for a subsequent key to complete a key mapping.
+.KY leftright
+.IP "leftright [off]"
+.CO Vi
+only.
+This option causes the screen to be scrolled left-right to view
+lines longer than the screen, instead of the traditional
+.CO vi
+screen interface which folds long lines at the right-hand margin
+of the terminal.
+.KY lines
+.IP "lines, li [24]"
+.CO Vi
+only.
+The number of lines in the screen.
+Setting this option causes
+.EV ex vi
+to set (or reset) the environmental variable
+.LI LINES .
+See the section entitled
+.QB "Sizing the Screen"
+for more information.
+.KY lisp
+.IP "lisp [off]"
+.CO Vi
+only.
+This option changes the behavior of the
+.CO vi
+.CO ( ,
+.CO ) ,
+.CO { ,
+.CO } ,
+.CO [[
+and
+.CO ]]
+commands to match the Lisp language.
+Also, the
+.OP autoindent
+option's behavior is changed to be appropriate for Lisp.
+.sp
+.i "This option is not yet implemented."
+.KY list
+.IP "list [off]"
+This option causes lines to be displayed in an unambiguous fashion.
+Specifically, tabs are displayed as control characters, i.e.
+.QT ^I ,
+and the ends of lines are marked with a
+.QT $
+character.
+.KY lock
+.IP "lock [on]"
+This option causes the editor to attempt to get an exclusive lock on
+any file being edited, read or written.
+Reading or writing a file that cannot be locked produces a warning
+message, but no other effect.
+Editing a file that cannot be locked results in a read only edit session,
+as if the
+.OP readonly
+edit option were set.
+.KY magic
+.IP "magic [on]"
+This option is on by default.
+Turning the
+.OP magic
+option off causes all regular expression characters except for
+.QT ^
+and
+.QT $ ,
+to be treated as ordinary characters.
+To re-enable characters individually, when the
+.OP magic
+option is off,
+precede them with a backslash
+.QT \e
+character.
+See the section entitled
+.QB "Regular Expressions and Replacement Strings"
+for more information.
+.KY matchchars
+.IP "matchchars [[]{}()<>]"
+.CO Vi
+only.
+This option defines the character pairs used by the
+.CO %
+command.
+.KY matchtime
+.IP "matchtime [7]"
+.CO Vi
+only.
+The 10th's of a second
+.CO vi
+pauses on the matching character when the
+.OP showmatch
+option is set.
+.KY mesg
+.IP "mesg [on]"
+This option allows other users to contact you using the
+.XR talk 1
+and
+.XR write 1
+utilities, while you are editing.
+.EV Ex vi
+does not turn message on, i.e. if messages were turned off when the
+editor was invoked, they will stay turned off.
+This option only permits you to disallow messages for the edit session.
+See the
+.XR mesg 1
+utility for more information.
+.KY msgcat
+.IP "msgcat [./]"
+This option selects a message catalog to be used to display error and
+informational messages in a specified language.
+If the value of this option ends with a '/', it is treated as the name
+of a directory that contains a message catalog
+.QT "vi_XXXX" ,
+where
+.QT XXXX
+is the value of the
+.LI LANG
+environmental variable, if it's set, or the value of the
+.LI LC_MESSAGES
+environmental variable if it's not.
+If neither of those environmental variables are set,
+or if the option doesn't end in a '/',
+the option is treated as the full path name of the message catalog to use.
+.sp
+If any messages are missing from the catalog,
+the backup text (English) is used instead.
+.sp
+See the distribution file
+.LI catalog/README
+for additional information on building and installing message catalogs.
+.KY modelines
+.IP "modelines, modeline [off]"
+If the
+.OP modelines
+option is set,
+.EV ex vi
+has historically scanned the first and last five lines of each file as
+it is read for editing, looking for any
+.CO ex
+commands that have been placed in those lines.
+After the startup information has been processed, and before the user
+starts editing the file, any commands embedded in the file are executed.
+.sp
+Commands were recognized by the letters
+.QQ e
+or
+.QQ v
+followed by
+.QQ x
+or
+.QQ i ,
+at the beginning of a line or following a tab or space character,
+and followed by a
+.QQ : ,
+an
+.CO ex
+command, and another
+.QQ : .
+.sp
+This option is a security problem of immense proportions,
+and should not be used under any circumstances.
+.sp
+.i "This option will never be implemented."
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms noprint [QQ]
+.KY noprint
+.IP "\*(ms"
+.tr QQ
+Characters that are never handled as printable characters.
+By default, the C library function
+.XR isprint 3
+is used to determine if a character is printable or not.
+This edit option overrides that decision.
+.KY number
+.IP "number, nu [off]"
+Precede each line displayed with its current line number.
+.KY octal
+.IP "octal [off]"
+Display unknown characters as octal numbers
+.PQ "\e###" ,
+instead of the default
+hexadecimal
+.PQ "\ex##" .
+.KY open
+.IP "open [on]"
+.CO Ex
+only.
+If this option is not set, the
+.CO open
+and
+.CO visual
+commands are disallowed.
+.KY optimize
+.IP "optimize, opt [on]"
+.CO Vi
+only.
+Throughput of text is expedited by setting the terminal not to do automatic
+carriage returns when printing more than one (logical) line of output,
+greatly speeding output on terminals without addressable cursors when text
+with leading white space is printed.
+.sp
+.i "This option is not yet implemented."
+.KY paragraphs
+.IP "paragraphs, para [IPLPPPQPP LIpplpipbp]"
+.CO Vi
+only.
+Define additional paragraph boundaries for the
+.CO {
+and
+.CO }
+commands.
+The value of this option must be a character string consisting
+of zero or more character pairs.
+.sp
+In the text to be edited, the character string
+.LI "<newline>.<char-pair>" ,
+(where
+.LI <char-pair>
+is one of the character pairs in the option's value)
+defines a paragraph boundary.
+For example, if the option were set to
+.LI "LaA<space>##" ,
+then all of the following additional paragraph boundaries would be
+recognized:
+.sp
+.(l
+<newline>.La
+<newline>.A<space>
+<newline>.##
+.)l
+.KY path
+.IP "path []"
+The path option can be used to specify a <colon>-separated list of
+paths, similar to the
+.LI PATH
+environment variable in the shells.
+If this option is set,
+the name of the file to be edited is not an absolute pathname,
+the first component of the filename is not
+.QT \&.
+or
+.QT \&.. ,
+and the file to be edited doesn't exist in the current directory,
+the elements of the
+.OP path
+option are sequentially searched for a file of the specified name.
+If such a file is found, it is edited.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms print [QQ]
+.KY print
+.IP "\*(ms"
+.tr QQ
+Characters that are always handled as printable characters.
+By default, the C library function
+.XR isprint 3
+is used to determine if a character is printable or not.
+This edit option overrides that decision.
+.KY prompt
+.IP "prompt [on]"
+.CO Ex
+only.
+This option causes
+.CO ex
+to prompt for command input with a
+.QT :
+character; when it is not set, no prompt is displayed.
+.KY readonly
+.IP "readonly, ro [off]"
+This option causes a force flag to be required to attempt to write the file.
+Setting this option is equivalent to using the
+.b \-R
+command line option,
+or executing the
+.CO vi
+program using the name
+.CO view .
+.sp
+The
+.OP readonly
+edit option is not usually persistent, like other edit options.
+If the
+.b \-R
+command line option is set,
+.CO vi
+is executed as
+.CO view ,
+or the
+.OP readonly
+edit option is explicitly set,
+all files edited in the screen will be marked readonly,
+and the force flag will be required to write them.
+However, if none of these conditions are true,
+or the
+.OP readonly
+edit option is explicitly unset,
+then the
+.OP readonly
+edit option will toggle based on the write permissions of the file currently
+being edited as of when it is loaded into the edit buffer.
+In other words, the
+.OP readonly
+edit option will be set if the current file lacks write permissions,
+and will not be set if the user has write permissions for the file.
+.KY recdir
+.IP "recdir [/var/tmp/vi.recover]"
+The directory where recovery files are stored.
+.sp
+If you change the value of
+.OP recdir ,
+be careful to choose a directory whose contents are not regularly
+deleted.
+Bad choices include directories in memory based filesystems,
+or
+.LI /tmp ,
+on most systems,
+as their contents are removed when the machine is rebooted.
+.sp
+Public directories like
+.LI /usr/tmp
+and
+.LI /var/tmp
+are usually safe, although some sites periodically prune old files
+from them.
+There is no requirement that you use a public directory,
+e.g. a sub-directory of your home directory will work fine.
+.sp
+Finally, if you change the value of
+.OP recdir ,
+you must modify the recovery script to operate in your chosen recovery
+area.
+.sp
+See the section entitled
+.QB "Recovery"
+for further information.
+.KY redraw
+.IP "redraw, re [off]"
+.CO Vi
+only.
+The editor simulates (using great amounts of output), an intelligent
+terminal on a dumb terminal (e.g. during insertions in
+.CO vi
+the characters to the right of the cursor are refreshed as each input
+character is typed).
+.sp
+.i "This option is not yet implemented."
+.KY remap
+.IP "remap [on]"
+If this option is set,
+it is possible to define macros in terms of other macros.
+Otherwise, each key is only remapped up to one time.
+For example, if
+.QT A
+is mapped to
+.QT B ,
+and
+.QT B
+is mapped to
+.QT C ,
+The keystroke
+.QT A
+will be mapped to
+.QT C
+if the
+.OP remap
+option is set, and to
+.QT B
+if it is not set.
+.KY report
+.IP "report [5]"
+Set the threshold of the number of lines that need to be changed or
+yanked before a message will be displayed to the user.
+For everything but the yank command, the value is the largest value
+about which the editor is silent, i.e. by default, 6 lines must be
+deleted before the user is notified.
+However, if the number of lines yanked is greater than
+.i "or equal to"
+the set value, it is reported to the user.
+.KY ruler
+.IP "ruler [off]"
+.CO Vi
+only.
+Display a row/column ruler on the colon command line.
+.KY scroll
+.IP "scroll, scr [(environment variable LINES - 1) / 2]"
+Set the number of lines scrolled by the
+.CO ex
+.CO <control-D>
+and
+.CO <end-of-file>
+commands.
+.sp
+Historically, the
+.CO ex
+.CO z
+command, when specified without a count, used two times the size of the
+scroll value; the POSIX 1003.2 standard specified the window size, which
+is a better choice.
+.KY searchincr
+.IP "searchincr [off]"
+The
+.OP searchincr
+edit option makes the search commands
+.CO \&/
+and
+.CO \&?
+incremental, i.e. the screen is updated and the cursor moves to the matching
+text as the search pattern is entered.
+If the search pattern is not found,
+the screen is beeped and the cursor remains on the colon-command line.
+Erasing characters from the search pattern backs the cursor up to the
+previous matching text.
+.KY sections
+.IP "sections, sect [NHSHH HUnhsh]"
+.CO Vi
+only.
+Define additional section boundaries for the
+.CO [[
+and
+.CO ]]
+commands.
+The
+.OP sections
+option should be set to a character string consisting of zero or
+more character pairs.
+In the text to be edited, the character string
+.LI "<newline>.<char-pair>" ,
+(where
+.LI <char-pair>
+is one of the character pairs in the option's value),
+defines a section boundary in the same manner that
+.OP paragraphs
+option boundaries are defined.
+.KY secure
+.IP "secure [off]"
+The
+.OP secure
+edit option turns off all access to external programs.
+This means that the versions of the
+.CO read
+and
+.CO write
+commands that filter text through other programs,
+the
+.CO vi
+.CO \&!
+and
+.CO <control-Z>
+commands,
+the
+.CO ex
+.CO \&! ,
+.CO script ,
+.CO shell ,
+.CO stop
+and
+.CO suspend
+commands and file name expansion will not be permitted.
+Once set,
+the
+.OP secure
+edit option may not be unset.
+.KY shell
+.IP "shell, sh [environment variable SHELL, or /bin/sh]"
+Select the shell used by the editor.
+The specified path is the pathname of the shell invoked by the
+.CO vi
+.CO !
+shell escape command and by the
+.CO ex
+.CO shell
+command.
+This program is also used to resolve any shell meta-characters in
+.CO ex
+commands.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life.  The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms shellmeta [~{[*?$`'Q\e]
+.KY shellmeta
+.IP "\*(ms"
+.tr QQ
+The set of characters that
+.CO ex
+checks for when doing file name expansion.
+If any of the specified characters are found in the file name arguments
+to the
+.CO ex
+commands,
+the arguments are expanded using the program defined by the
+.OP shell
+option.
+The default set of characters is a union of meta characters
+from the Version 7 and the Berkeley C shell.
+.KY shiftwidth
+.IP "shiftwidth, sw [8]"
+Set the autoindent and shift command indentation width.
+This width is used by the
+.OP autoindent
+option and by the
+.CO < ,
+.CO > ,
+and
+.CO shift
+commands.
+.KY showmatch
+.IP "showmatch, sm [off]"
+.CO Vi
+only.
+This option causes
+.CO vi ,
+when a
+.QT }
+or
+.QT )
+is entered, to briefly move the cursor the matching
+.QT {
+or
+.QT ( .
+See the
+.OP matchtime
+option for more information.
+.KY showmode
+.IP "showmode, smd [off]"
+.CO Vi
+only.
+This option causes
+.CO vi
+to display a string identifying the current editor mode on the colon
+command line.
+The string is preceded by an asterisk (``*'') if the file has been
+modified since it was last completely written,
+.KY sidescroll
+.IP "sidescroll [16]"
+.CO Vi
+only.
+Sets the number of columns that are shifted to the left or right,
+when
+.CO vi
+is doing left-right scrolling and the left or right margin is
+crossed.
+See the
+.OP leftright
+option for more information.
+.KY slowopen
+.IP "slowopen, slow [off]"
+This option affects the display algorithm used by
+.CO vi ,
+holding off display updating during input of new text to improve
+throughput when the terminal in use is slow and unintelligent.
+.sp
+.i "This option is not yet implemented."
+.KY sourceany
+.IP "sourceany [off]"
+If this option is turned on,
+.CO vi
+historically read startup files that were owned by someone other than
+the editor user.
+See the section entitled
+.QB "Startup Information"
+for more information.
+This option is a security problem of immense proportions,
+and should not be used under any circumstances.
+.sp
+.i "This option will never be implemented."
+.KY tabstop
+.IP "tabstop, ts [8]"
+This option sets tab widths for the editor display.
+.KY taglength
+.IP "taglength, tl [0]"
+This option sets the maximum number of characters that are considered
+significant in a tag name.
+Setting the value to 0 makes all of the characters in the tag name
+significant.
+.KY tags
+.IP "tags, tag [tags /var/db/libc.tags /sys/kern/tags]"
+Sets the list of tags files, in search order,
+which are used when the editor searches for a tag.
+.KY term
+.IP "term, ttytype, tty [environment variable TERM]"
+Set the terminal type.
+Setting this option causes
+.EV ex vi
+to set (or reset) the environmental variable
+.LI TERM .
+.KY terse
+.IP "terse [off]"
+This option has historically made editor messages less verbose.
+It has no effect in this implementation.
+See the
+.OP verbose
+option for more information.
+.KY tildeop
+.IP "tildeop [off]"
+Modify the
+.CO ~
+command to take an associated motion.
+.KY timeout
+.IP "timeout, to [on]"
+If this option is set,
+.EV ex vi
+waits for a specific period for a subsequent key to complete a key
+mapping (see the
+.OP keytime
+option).
+If the option is not set, the editor waits until enough keys are
+entered to resolve the ambiguity, regardless of how long it takes.
+.KY ttywerase
+.IP "ttywerase [off]"
+.CO Vi
+only.
+This option changes how
+.CO vi
+does word erase during text input.
+If this option is set, text is broken up into two classes,
+blank characters and nonblank characters.
+Changing from one class to another marks the end of a word.
+.KY verbose
+.IP "verbose [off]"
+.CO Vi
+only.
+.CO Vi
+historically bells the terminal for many obvious mistakes, e.g. trying
+to move past the left-hand margin, or past the end of the file.
+If this option is set, an error message is displayed for all errors.
+.KY w300
+.IP "w300 [no default]"
+.CO Vi
+only.
+Set the window size if the baud rate is less than 1200 baud.
+See the
+.OP window
+option for more information.
+.KY w1200
+.IP "w1200 [no default]"
+.CO Vi
+only.
+Set the window size if the baud rate is equal to 1200 baud.
+See the
+.OP window
+option for more information.
+.KY w9600
+.IP "w9600 [no default]"
+.CO Vi
+only.
+Set the window size if the baud rate is greater than 1200 baud.
+See the
+.OP window
+option for more information.
+.KY warn
+.IP "warn [on]"
+.CO Ex
+only.
+This option causes a warning message to the terminal if the file has
+been modified, since it was last written, before a
+.CO !
+command.
+.KY window
+.IP "window, w, wi [environment variable LINES - 1]"
+This option determines the default number of lines in a screenful,
+as displayed by the
+.CO z
+command.
+It also determines the number of lines scrolled by the
+.CO vi
+commands
+.CO <control-B>
+and
+.CO <control-F> ,
+and the default number of lines scrolled by the
+.CO vi
+commands
+.CO <control-D>
+and
+.CO <control-U> .
+The value of window can be unrelated to the real screen size,
+although it starts out as the number of lines on the screen.
+See the section entitled
+.QB "Sizing the Screen"
+for more information.
+Setting the value of the
+.OP window
+option is the same as using the
+.b \-w
+command line option.
+.sp
+If the value of the
+.OP window
+option (as set by the
+.OP window ,
+.OP w300 ,
+.OP w1200
+or
+.OP w9600
+options) is smaller than the actual size of the screen,
+large screen movements will result in displaying only that smaller
+number of lines on the screen.
+(Further movements in that same area will result in the screen being
+filled.)
+This can provide a performance improvement when viewing different
+places in one or more files over a slow link.
+.sp
+Resetting the window size does not reset the default number of lines
+scrolled by the
+.CO <control-D>
+and
+.CO <control-U>
+commands.
+.KY windowname
+.IP "windowname [off]"
+.CO Vi
+changes the name of the editor's icon/window to the current file name
+when it's possible and not destructive, i.e.,
+when the editor can restore it to its original value on exit or when
+the icon/window will be discarded as the editor exits.
+If the
+.OP windowname
+edit option is set,
+.CO vi
+will change the icon/window name even when it's destructive and the
+icon/window name will remain after the editor exits.
+(This is the case for
+.XR xterm 1 ).
+.KY wraplen
+.IP "wraplen, wl [0]"
+This option is identical to the
+.OP wrapmargin
+option, with the exception that it specifies the number of columns
+from the
+.i left
+margin before the line splits, not the right margin.
+.sp
+If both
+.OP wraplen
+and
+.OP wrapmargin
+are set, the
+.OP wrapmargin
+value is used.
+.KY wrapmargin
+.IP "wrapmargin, wm [0]"
+.CO Vi
+only.
+If the value of the
+.OP wrapmargin
+option is non-zero,
+.CO vi
+will split lines so that they end at least that number of columns
+before the right-hand margin of the screen.
+(Note, the value of
+.OP wrapmargin
+is
+.i not
+a text length.
+In a screen that is 80 columns wide, the command
+.QT ":set wrapmargin=8"
+attempts to keep the lines less than or equal to 72 columns wide.)
+.sp
+Lines are split at the previous whitespace character closest to the
+number.
+Any trailing whitespace characters before that character are deleted.
+If the line is split because of an inserted
+.LI <space>
+or
+.LI <tab>
+character, and you then enter another
+.LI <space>
+character, it is discarded.
+.sp
+If wrapmargin is set to 0,
+or if there is no blank character upon which to split the line,
+the line is not broken.
+.sp
+If both
+.OP wraplen
+and
+.OP wrapmargin
+are set, the
+.OP wrapmargin
+value is used.
+.KY wrapscan
+.IP "wrapscan, ws [on]"
+This option causes searches to wrap around the end or the beginning
+of the file, and back to the starting point.
+Otherwise, the end or beginning of the file terminates the search.
+.KY writeany
+.IP "writeany, wa [off]"
+If this option is set, file-overwriting checks that would usually be
+made before the
+.CO write
+and
+.CO xit
+commands, or before an automatic write (see the
+.OP autowrite
+option), are not made.
+This allows a write to any file, provided the file permissions allow it.
diff --git a/usr.bin/nvi/docs/USD.doc/vi.ref/vi.cmd.roff b/usr.bin/nvi/docs/USD.doc/vi.ref/vi.cmd.roff
new file mode 100644 (file)
index 0000000..d515f97
--- /dev/null
@@ -0,0 +1,3097 @@
+.\"    $NetBSD: vi.cmd.roff,v 1.1 2008/09/02 09:25:39 christos Exp $
+.\"
+.\" Copyright (c) 1994
+.\"    The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\"    Keith Bostic.  All rights reserved.
+.\"
+.\" See the LICENSE file for redistribution information.
+.\"
+.\"    @(#)vi.cmd.roff 8.49 (Berkeley) 8/17/96
+.\"
+.SH 1 "Vi Description"
+.pp
+.CO Vi
+takes up the entire screen to display the edited file,
+except for the bottom line of the screen.
+The bottom line of the screen is used to enter
+.CO ex
+commands, and for
+.CO vi
+error and informational messages.
+If no other information is being displayed,
+the default display can show the current cursor row and cursor column,
+an indication of whether the file has been modified,
+and the current mode of the editor.
+See the
+.OP ruler
+and
+.OP showmode
+options for more information.
+.pp
+Empty lines do not have any special representation on the screen,
+but lines on the screen that would logically come after the end of
+the file are displayed as a single tilde
+.PQ ~
+character.
+To differentiate between empty lines and lines consisting of only
+whitespace characters, use the
+.OP list
+option.
+Historically, implementations of
+.CO vi
+have also displayed some lines as single asterisk
+.PQ @
+characters.
+These were lines that were not correctly displayed, i.e. lines on the
+screen that did not correspond to lines in the file, or lines that did
+not fit on the current screen.
+.CO Nvi
+never displays lines in this fashion.
+.pp
+.CO Vi
+is a modeful editor, i.e. it has two modes,
+.QQ command
+mode and
+.QQ "text input"
+mode.
+When
+.CO vi
+first starts, it is in command mode.
+There are several commands that change
+.CO vi
+into text input mode.
+The
+.LI <escape>
+character is used to resolve the text input into the file,
+and exit back into command mode.
+In
+.CO vi
+command mode, the cursor is always positioned on the last column of
+characters which take up more than one column on the screen.
+In
+.CO vi
+text insert mode, the cursor is positioned on the first column of
+characters which take up more than one column on the screen.
+.pp
+When positioning the cursor to a new line and column,
+the type of movement is defined by the distance to the new cursor position.
+If the new position is close,
+the screen is scrolled to the new location.
+If the new position is far away,
+the screen is repainted so that the new position is on the screen.
+If the screen is scrolled,
+it is moved a minimal amount,
+and the cursor line will usually appear at the top or bottom of the screen.
+If the screen is repainted,
+the cursor line will appear in the center of the screen,
+unless the cursor is sufficiently close to the beginning or end of the file
+that this isn't possible.
+If the
+.OP leftright
+option is set, the screen may be scrolled or repainted in a horizontal
+direction as well as in a vertical one.
+.pp
+A major difference between the historical
+.CO vi
+presentation and
+.CO nvi
+is in the scrolling and screen oriented position commands,
+.CO <control-B> ,
+.CO <control-D> ,
+.CO <control-E> ,
+.CO <control-F> ,
+.CO <control-U> ,
+.CO <control-Y> ,
+.CO H ,
+.CO L
+and
+.CO M .
+In historical implementations of
+.CO vi ,
+these commands acted on physical (as opposed to logical, or screen)
+lines.
+For lines that were sufficiently long in relation to the size of the
+screen, this meant that single line scroll commands might repaint the
+entire screen, scrolling or screen positioning commands might not change
+the screen or move the cursor at all, and some lines simply could not
+be displayed, even though
+.CO vi
+would edit the file that contained them.
+In
+.CO nvi ,
+these commands act on logical, i.e. screen lines.
+You are unlikely to notice any difference unless you are editing files
+with lines significantly longer than a screen width.
+.pp
+.CO Vi
+keeps track of the currently
+.QQ "most attractive"
+cursor position.
+Each command description (for commands that alter the current cursor
+position),
+specifies if the cursor is set to a specific location in the line,
+or if it is moved to the
+.QQ "most attractive cursor position" .
+The latter means that the cursor is moved to the cursor position that
+is horizontally as close as possible to the current cursor position.
+If the current line is shorter than the cursor position
+.CO vi
+would select, the cursor is positioned on the last character in the line.
+(If the line is empty, the cursor is positioned on the first column
+of the line.)
+If a command moves the cursor to the most attractive position,
+it does not alter the current cursor position, and a subsequent
+movement will again attempt to move the cursor to that position.
+Therefore, although a movement to a line shorter than the currently
+most attractive position will cause the cursor to move to the end of
+that line, a subsequent movement to a longer line will cause the
+cursor to move back to the most attractive position.
+.pp
+In addition, the
+.CO $
+command makes the end of each line the most attractive cursor position
+rather than a specific column.
+.pp
+Each
+.CO vi
+command described below notes where the cursor ends up after it is
+executed.
+This position is described in terms of characters on the line, i.e.
+.QQ "the previous character" ,
+or,
+.QQ "the last character in the line" .
+This is to avoid needing to continually refer to on what part of the
+character the cursor rests.
+.pp
+The following words have special meaning for
+.CO vi
+commands.
+.KY "previous context"
+.IP "previous context"
+The position of the cursor before the command which caused the
+last absolute movement was executed.
+Each 
+.CO vi
+command described in the next section that is considered an
+absolute movement is so noted.
+In addition, specifying
+.i any
+address to an
+.CO ex
+command is considered an absolute movement.
+.KY "motion"
+.IP "motion"
+A second
+.CO vi
+command can be used as an optional trailing argument to the
+.CO vi
+.CO \&< ,
+.CO \&> ,
+.CO \&! ,
+.CO \&c ,
+.CO \&d ,
+.CO \&y ,
+and (depending on the
+.OP tildeop
+option)
+.CO \&~
+commands.
+This command indicates the end of the region of text that's affected by
+the command.
+The motion command may be either the command character repeated (in
+which case it means the current line) or a cursor movement command.
+In the latter case, the region affected by the command is from the
+starting or stopping cursor position which comes first in the file,
+to immediately before the starting or stopping cursor position which
+comes later in the file.
+Commands that operate on lines instead of using beginning and ending
+cursor positions operate on all of the lines that are wholly or
+partially in the region.
+In addition, some other commands become line oriented depending on
+where in the text they are used.
+The command descriptions below note these special cases.
+.sp
+The following commands may all be used as motion components for
+.CO vi
+commands:
+.sp
+.ne 12v
+.ft C
+.TS
+r r r r.
+<control-A>    <control-H>     <control-J>     <control-M>
+<control-N>    <control-P>     <space> $
+%      '<character>    (       )
++      ,       -       /
+0      ;       ?       B
+E      F       G       H
+L      M       N       T
+W      [[      ]]      ^
+\&_    `<character>    b       e
+f      h       j       k
+l      n       t       w
+{      |       }
+.TE
+.ft R
+.sp
+The optional count prefix available for some of the
+.CO vi
+commands that take motion commands,
+or the count prefix available for the
+.CO vi
+commands that are used as motion components,
+may be included and is
+.i always
+considered part of the motion argument.
+For example, the commands
+.QT c2w
+and
+.QT 2cw
+are equivalent, and the region affected by the
+.CO c
+command is two words of text.
+In addition,
+if the optional count prefix is specified for both the
+.CO vi
+command and its motion component,
+the effect is multiplicative and is considered part of the motion argument.
+For example, the commands
+.QT 4cw
+and
+.QT 2c2w
+are equivalent, and the region affected by the
+.CO c
+command is four words of text.
+.KY "count"
+.IP "count"
+A positive number used as an optional argument to most commands,
+either to give a size or a position (for display or movement commands),
+or as a repeat count (for commands that modify text).
+The count argument is always optional and defaults to 1 unless otherwise
+noted in the command description.
+.sp
+When a
+.CO vi
+command synopsis shows both a
+.LI [buffer]
+and
+.LI [count] ,
+they may be presented in any order.
+.KY word
+.IP word
+Generally, in languages where it is applicable,
+.CO vi
+recognizes two kinds of words.
+First, a sequence of letters, digits and underscores,
+delimited at both ends by:
+characters other than letters, digits, or underscores,
+the beginning or end of a line, and the beginning or end of the file.
+Second, a sequence of characters other than letters, digits, underscores,
+or whitespace characters, delimited at both ends by: a letter, digit,
+underscore, or whitespace character,
+the beginning or end of a line, and the beginning or end of the file.
+For example, the characters
+.QT " !@#abc$%^ "
+contain three words:
+.QT "!@#" ,
+.QT "abc"
+and
+.QT "$%^" .
+.sp
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single word.
+.KY "bigword"
+.IP "bigword"
+A set of non-whitespace characters preceded and followed by whitespace
+characters or the beginning or end of the file or line.
+For example, the characters
+.QT " !@#abc$%^ "
+contain one bigword:
+.QT "!@#abc$%^" .
+.sp
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single bigword.
+.KY "paragraph"
+.IP "paragraph"
+An area of text that begins with either the beginning of a file,
+an empty line, or a section boundary, and continues until either
+an empty line, section boundary, or the end of the file.
+.sp
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single paragraph.
+.sp
+Additional paragraph boundaries can be defined using the
+.OP paragraphs
+option.
+.KY "section"
+.IP "section"
+An area of text that starts with the beginning of the file or a line
+whose first character is an open brace
+.PQ {
+and continues until the next section or the end of the file.
+.sp
+Additional section boundaries can be defined using the
+.OP sections
+option.
+.KY "sentence"
+.IP "sentence"
+An area of text that begins with either the beginning of the file or the
+first nonblank character following the previous sentence, paragraph, or
+section boundary and continues until the end of the file or a period
+.PQ \&.
+exclamation point
+.PQ !
+or question mark
+.PQ ?
+character,
+followed by either an end-of-line or two whitespace characters.
+Any number of closing parentheses
+.PQ ) ,
+brackets
+.PQ ] ,
+double-quote
+.PQ """"
+or single quote
+.PQ '
+characters can appear between the period, exclamation point,
+or question mark and the whitespace characters or end-of-line.
+.sp
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single sentence.
+.SH 1 "Vi Commands"
+.pp
+The following section describes the commands available in the command
+mode of the
+.CO vi
+editor.
+In each entry below, the tag line is a usage synopsis for the command
+character.
+In addition, the final line and column the cursor rests upon,
+and any options which affect the command are noted.
+.KY <control-A>
+.IP "[count] <control-A>"
+Search forward
+.LI count
+times for the current word.
+The current word begins at the first non-whitespace character on or
+after the current cursor position,
+and extends up to the next non-word character or the end of the line.
+The search is literal, i.e. no characters in the word have any special
+meaning in terms of Regular Expressions.
+It is an error if no matching pattern is found between the starting position
+and the end of the file.
+.sp
+The
+.CO <control-A>
+command is an absolute movement.
+The
+.CO <control-A>
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Set to the line where the word is found.
+.SP Column:
+Set to the first character of the word.
+.SP Options:
+Affected by the
+.OP ignorecase
+and
+.OP wrapscan
+options.
+.SE
+.KY <control-B>
+.IP "[count] <control-B>"
+Page backward
+.LI count
+screens.
+Two lines of overlap are maintained, if possible,
+by displaying the window starting at line
+.LI "(top_line - count * window_size) + 2" ,
+where
+.LI window_size
+is the value of the
+.OP window
+option.
+(In the case of split screens, this size is corrected to the
+current screen size.)
+It is an error if the movement is past the beginning of the file.
+.SS
+.SP Line:
+Set to the last line of text displayed on the screen.
+.SP Column:
+Set to the first nonblank character of the line.
+.SP Options:
+Affected by the
+.OP window
+option.
+.SE
+.KY <control-D>
+.IP "[count] <control-D>"
+Scroll forward
+.LI count
+lines.
+If
+.LI count
+is not specified, scroll forward the number of lines specified by the last
+.CO <control-D>
+or
+.CO <control-U>
+command.
+If this is the first
+.CO <control-D>
+or
+.CO <control-U>
+command,
+scroll forward half the number of lines in the screen.
+(In the case of split screens, the default scrolling distance is
+corrected to half the current screen size.)
+It is an error if the movement is past the end of the file.
+.SS
+.SP Line:
+Set to the current line plus the number of lines scrolled.
+.SP Column:
+Set to the first nonblank character of the line.
+.SP Options:
+None.
+.SE
+.KY <control-E>
+.IP "[count] <control-E>"
+Scroll forward
+.LI count
+lines, leaving the cursor on the current line and column, if possible.
+It is an error if the movement is past the end of the file.
+.SS
+.SP Line:
+Unchanged unless the current line scrolls off the screen,
+in which case it is set to the first line on the screen.
+.SP Column:
+Unchanged unless the current line scrolls off the screen,
+in which case it is set to the most attractive cursor position.
+.SP Options:
+None.
+.SE
+.KY <control-F>
+.IP "[count] <control-F>"
+Page forward
+.LI count
+screens.
+Two lines of overlap are maintained, if possible,
+by displaying the window starting at line
+.LI "top_line + count * window_size - 2" ,
+where
+.LI window_size
+is the value of the
+.OP window
+option.
+(In the case of split screens, this size is corrected to the
+current screen size.)
+It is an error if the movement is past the end of the file.
+.SS
+.SP Line:
+Set to the first line on the screen.
+.SP Column:
+Set to the first nonblank character of the current line.
+.SP Options:
+Affected by the
+.OP window
+option.
+.SE
+.KY <control-G>
+.IP "<control-G>"
+Display the file information.
+The information includes the current pathname, the current line,
+the number of total lines in the file, the current line as a percentage
+of the total lines in the file, if the file has been modified,
+was able to be locked, if the file's name has been changed,
+and if the edit session is read-only.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY <control-H>
+.IP "[count] <control-H>"
+.Ip "[count] h"
+Move the cursor back
+.LI count
+characters in the current line.
+It is an error if the cursor is on the first character in the line.
+.sp
+The
+.CO <control-H>
+and
+.CO h
+commands may be used as the motion component of other
+.CO vi
+commands,
+in which case any text copied into a buffer is character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the
+.LI "current - count"
+character, or, the first character in the line if
+.LI count
+is greater than or equal to the number of characters in the line
+before the cursor.
+.SP Options:
+None.
+.SE
+.KY <control-J>
+.IP "[count] <control-J>"
+.KY <control-N>
+.Ip "[count] <control-N>"
+.KY j
+.Ip "[count] j"
+Move the cursor down
+.LI count
+lines without changing the current column.
+It is an error if the movement is past the end of the file.
+.sp
+The
+.CO <control-J> ,
+.CO <control-N>
+and
+.CO j
+commands may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to the current line plus
+.LI count .
+.SP Column:
+The most attractive cursor position.
+.SP Options:
+None.
+.SE
+.KY <control-L>
+.IP "<control-L>"
+.KY <control-R>
+.Ip "<control-R>"
+Repaint the screen.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY <control-M>
+.IP "[count] <control-M>"
+.KY +
+.Ip "[count] +"
+Move the cursor down
+.LI count
+lines to the first nonblank character of that line.
+It is an error if the movement is past the end of the file.
+.sp
+The
+.CO <control-M>
+and
+.CO +
+commands may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to the current line plus
+.LI count .
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+None.
+.SE
+.KY <control-P>
+.IP "[count] <control-P>"
+.KY k
+.Ip "[count] k"
+Move the cursor up
+.LI count
+lines, without changing the current column.
+It is an error if the movement is past the beginning of the file.
+.sp
+The
+.CO <control-P>
+and
+.CO k
+commands may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to the current line minus
+.LI count .
+.SP Column:
+The most attractive cursor position.
+.SP Options:
+None.
+.SE
+.KY <control-T>
+.IP "<control-T>"
+Return to the most recent tag context.
+The
+.CO <control-T>
+command is an absolute movement.
+.SS
+.SP Line:
+Set to the context of the previous tag command.
+.SP Column:
+Set to the context of the previous tag command.
+.SP Options:
+None.
+.SE
+.KY <control-U>
+.IP "[count] <control-U>"
+Scroll backward
+.LI count
+lines.
+If
+.LI count
+is not specified, scroll backward the number of lines specified by the
+last
+.CO <control-D>
+or
+.CO <control-U>
+command.
+If this is the first
+.CO <control-D>
+or
+.CO <control-U>
+command,
+scroll backward half the number of lines in the screen.
+(In the case of split screens, the default scrolling distance is
+corrected to half the current screen size.)
+It is an error if the movement is past the beginning of the file.
+.SS
+.SP Line:
+Set to the current line minus the amount scrolled.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+None.
+.SE
+.KY <control-W>
+.IP "<control-W>"
+Switch to the next lower screen in the window, or, to the first
+screen if there are no lower screens in the window.
+.SS
+.SP Line:
+Set to the previous cursor position in the window.
+.SP Column:
+Set to the previous cursor position in the window.
+.SP Options:
+None.
+.SE
+.KY <control-Y>
+.IP "[count] <control-Y>"
+Scroll backward
+.LI count
+lines, leaving the current line and column as is, if possible.
+It is an error if the movement is past the beginning of the file.
+.SS
+.SP Line:
+Unchanged unless the current line scrolls off the screen,
+in which case it is set to the last line of text displayed
+on the screen.
+.SP Column:
+Unchanged unless the current line scrolls off the screen,
+in which case it is the most attractive cursor position.
+.SP Options:
+None.
+.SE
+.KY <control-Z>
+.IP "<control-Z>"
+Suspend the current editor session.
+If the file has been modified since it was last completely written,
+and the
+.OP autowrite
+option is set, the file is written before the editor session is
+suspended.
+If this write fails, the editor session is not suspended.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged.
+.SP Options:
+Affected by the
+.OP autowrite
+option.
+.SE
+.KY <escape>
+.IP "<escape>"
+Execute
+.CO ex
+commands or cancel partial commands.
+If an
+.CO ex
+command is being entered (e.g.
+.CO / ,
+.CO ? ,
+.CO :
+or
+.CO ! ),
+the command is executed.
+If a partial command has been entered, e.g.
+.QT "[0-9]*" ,
+or
+.QT "[0-9]*[!<>cdy]" ,
+the command is cancelled.
+Otherwise, it is an error.
+.SS
+.SP Line:
+When an
+.CO ex
+command is being executed, the current line is set as described for
+that command.
+Otherwise, unchanged.
+.SP Column:
+When an
+.CO ex
+command is being executed, the current column is set as described for
+that command.
+Otherwise, unchanged.
+.SP Options:
+None.
+.SE
+.KY <control-]>
+.IP "<control-]>"
+Push a tag reference onto the tag stack.
+The tags files (see the
+.OP tags
+option for more information) are searched for a tag matching the
+current word.
+The current word begins at the first non-whitespace character on or
+after the current cursor position,
+and extends up to the next non-word character or the end of the line.
+If a matching tag is found, the current file is discarded and the
+file containing the tag reference is edited.
+.sp
+If the current file has been modified since it was last completely
+written, the command will fail.
+The
+.CO <control-]>
+command is an absolute movement.
+.SS
+.SP Line:
+Set to the line containing the matching tag string.
+.SP Column:
+Set to the start of the matching tag string.
+.SP Options:
+Affected by the
+.OP tags
+and
+.OP taglength
+options.
+.SE
+.KY <control-^>
+.IP "<control-^>"
+Switch to the most recently edited file.
+.sp
+If the file has been modified since it was last completely written,
+and the
+.OP autowrite
+option is set, the file is written out.
+If this write fails, the command will fail.
+Otherwise, if the current file has been modified since it was last
+completely written, the command will fail.
+.SS
+.SP Line:
+Set to the line the cursor was on when the file was last edited.
+.SP Column:
+Set to the column the cursor was on when the file was last edited.
+.SP Options:
+Affected by the
+.OP autowrite
+option.
+.SE
+.KY <space>
+.IP "[count] <space>"
+.KY l
+.Ip "[count] l"
+Move the cursor forward
+.LI count
+characters without changing the current line.
+It is an error if the cursor is on the last character in the line.
+.sp
+The
+.CO <space>
+and
+.CO \&l
+commands may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+In addition, these commands may be used as the motion components
+of other commands when the cursor is on the last character in the
+line, without error.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the current character plus the next
+.LI count
+characters, or to the last character on the line if
+.LI count
+is greater than the number of characters in the line after the
+current character.
+.SP Options:
+None.
+.SE
+.KY !
+.IP "[count] ! motion shell-argument(s)<carriage-return>"
+Replace text with results from a shell command.
+Pass the lines specified by the
+.LI count
+and
+.LI motion
+arguments as standard input to the program named by the
+.OP shell
+option, and replace those lines with the output (both
+standard error and standard output) of that command.
+.sp
+After the motion is entered,
+.CO vi
+prompts for arguments to the shell command.
+.sp
+Within those arguments,
+.QT %
+and
+.QT #
+characters are expanded to the current and alternate pathnames,
+respectively.
+The
+.QT !
+character is expanded with the command text of the previous
+.CO !
+or
+.CO :!
+commands.
+(Therefore, the command
+.CO !<motion>!
+repeats the previous
+.CO !
+command.)
+The special meanings of
+.QT % ,
+.QT #
+and
+.QT !
+can be overridden by escaping them with a backslash.
+If no
+.CO !
+or
+.CO :!
+command has yet been executed,
+it is an error to use an unescaped
+.QT !
+character as a shell argument.
+The
+.CO !
+command does
+.i not
+do shell expansion on the strings provided as arguments.
+If any of the above expansions change the arguments the user entered,
+the command is redisplayed at the bottom of the screen.
+.sp
+.CO Vi
+then executes the program named by the
+.OP shell
+option, with a
+.b \-c
+flag followed by the arguments (which are bundled into a single argument).
+.sp
+The
+.CO !
+command is permitted in an empty file.
+.sp
+If the file has been modified since it was last completely written,
+the
+.CO !
+command will warn you.
+.SS
+.SP Line:
+The first line of the replaced text.
+.SP Column:
+The first column of the replaced text.
+.SP Options:
+Affected by the
+.OP shell
+option.
+.SE
+.KY #
+.IP "[count] # #|+|-"
+Increment or decrement the number referenced by the cursor.
+If the trailing character is a
+.LI \&+
+or
+.LI \&# ,
+the number is incremented by
+.LI count .
+If the trailing character is a
+.LI \&- ,
+the number is decremented by
+.LI count .
+.sp
+A leading
+.QT \&0X
+or
+.QT \&0x
+causes the number to be interpreted as a hexadecimal number.
+Otherwise, a leading
+.QT \&0
+causes the number to be interpreted as an octal number, unless a non-octal
+digit is found as part of the number.
+Otherwise, the number is interpreted as a decimal number, and may
+have a leading
+.LI \&+
+or
+.LI \&-
+sign.
+The current number begins at the first non-blank character at or after
+the current cursor position, and extends up to the end of the line or
+the first character that isn't a possible character for the numeric type.
+The format of the number (e.g. leading 0's, signs) is retained unless
+the new value cannot be represented in the previous format.
+.sp
+Octal and hexadecimal numbers, and the result of the operation, must fit
+into an
+.QT "unsigned long" .
+Similarly, decimal numbers and their result must fit into a
+.QT "signed long" .
+It is an error to use this command when the cursor is not positioned at
+a number.
+.sp
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the first character in the cursor number.
+.SP Options:
+None.
+.SE
+.KY $
+.IP "[count] $"
+Move the cursor to the end of a line.
+If
+.LI count
+is specified, the cursor moves down
+.LI "count - 1"
+lines.
+.sp
+It is not an error to use the
+.CO $
+command when the cursor is on the last character in the line or
+when the line is empty.
+.sp
+The
+.CO $
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the cursor is at, or before the first
+nonblank character in the line, in which case it is line oriented.
+It is not an error to use the
+.CO $
+command as a motion component when the cursor is on the last character
+in the line, although it is an error when the line is empty.
+.SS
+.SP Line:
+Set to the current line plus
+.LI count
+minus 1.
+.SP Column:
+Set to the last character in the line.
+.SP Options:
+None.
+.SE
+.KY %
+.IP %
+Move to the matching character.
+The cursor moves to the bracket character that
+.i matches
+the bracket found at the current cursor position
+or which is the closest one to the right of the cursor on the line.
+The bracket characters are defined by the
+.OP matchchars
+option.
+An error will be reported if none of the
+.OP matchchars
+characters is found, or if no matching character is found.
+If the open and close brackes are identical (e.g.: if they are
+.QT '
+or
+.QT " ),
+then repeating a
+.CO %
+command will perform a backwards search from the original opening bracket.
+Historically, any
+.LI count
+specified to the
+.CO %
+command was ignored.
+.sp
+The
+.CO %
+command is an absolute movement.
+The
+.CO %
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting point of the region is at
+or before the first nonblank character on its line, and the ending
+point is at or after the last nonblank character on its line, in
+which case it is line oriented.
+.SS
+.SP Line:
+Set to the line containing the matching character.
+.SP Column:
+Set to the matching character.
+.SP Options:
+None.
+.SE
+.KY &
+.IP "&"
+Repeat the previous substitution command on the current line.
+.sp
+Historically, any
+.LI count
+specified to the
+.CO &
+command was ignored.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged if the cursor was on the last character in the line,
+otherwise, set to the first nonblank character in the line.
+.SP Options:
+Affected by the
+.OP edcompatible ,
+.OP extended ,
+.OP ignorecase
+and
+.OP magic
+options.
+.SE
+.KY SQUOTE<character>
+.IP \'<character>
+.KY `<character>
+.Ip `<character>
+Return to a context marked by the character
+.LI <character> .
+If
+.LI <character>
+is the
+.QT '
+or
+.QT `
+character, return to the previous context.
+If
+.LI <character>
+is any other character,
+return to the context marked by that character (see the
+.CO m
+command for more information).
+If the command is the
+.CO \'
+command, only the line value is restored,
+and the cursor is placed on the first nonblank character of that line.
+If the command is the
+.CO `
+command, both the line and column values are restored.
+.sp
+It is an error if the context no longer exists because of
+line deletion.
+(Contexts follow lines that are moved, or which are deleted
+and then restored.)
+.sp
+The
+.CO \'
+and
+.CO `
+commands are both absolute movements.
+They may be used as a motion component for other
+.CO vi
+commands.
+For the
+.CO \'
+command, any text copied into a buffer is line oriented.
+For the
+.CO `
+command,
+any text copied into a buffer is character oriented,
+unless it both starts and stops at the first character in the line,
+in which case it is line oriented.
+In addition, when using the
+.CO `
+command as a motion component,
+commands which move backward and started at the first character in the line,
+or move forward and ended at the first character in the line,
+are corrected to the last character of the line preceding the starting and
+ending lines, respectively.
+.SS
+.SP Line:
+Set to the line from the context.
+.SP Column:
+Set to the first nonblank character in the line, for the
+.CO \'
+command, and set to the context's column for the
+.CO `
+command.
+.SP Options:
+None.
+.SE
+.KY (
+.IP "[count] ("
+Back up
+.LI count
+sentences.
+.sp
+The
+.CO (
+command is an absolute movement.
+The
+.CO (
+command may be used as the motion component of other
+.CO vi
+commands,
+in which case any text copied into a buffer is character oriented,
+unless the starting and stopping points of the region are the first
+character in the line,
+in which case it is line oriented.
+If it is line oriented,
+the starting point of the region is adjusted to be the end of the line
+immediately before the starting cursor position.
+.SS
+.SP Line:
+Set to the line containing the beginning of the sentence.
+.SP Column:
+Set to the first nonblank character of the sentence.
+.SP Options:
+Affected by the
+.OP lisp
+option.
+.SE
+.KY )
+.IP "[count] )"
+Move forward
+.LI count
+sentences.
+.sp
+The
+.CO )
+command is an absolute movement.
+The
+.CO )
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting point of the region is the
+first character in the line, in which case it is line oriented.
+In the latter case, if the stopping point of the region is also
+the first character in the line, it is adjusted to be the end of the
+line immediately before it.
+.SS
+.SP Line:
+Set to the line containing the beginning of the sentence.
+.SP Column:
+Set to the first nonblank character of the sentence.
+.SP Options:
+Affected by the
+.OP lisp
+option.
+.SE
+.KY ,
+.IP "[count] ,"
+Reverse find character
+.LI count
+times.
+Reverse the last
+.CO F ,
+.CO f ,
+.CO T
+or
+.CO t
+command, searching the other way in the line,
+.LI count
+times.
+It is an error if a
+.CO F ,
+.CO f ,
+.CO T
+or
+.CO t
+command has not been performed yet.
+.sp
+The
+.CO ,
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the searched-for character for the
+.CO F
+and
+.CO f
+commands,
+before the character for the
+.CO t
+command
+and after the character for the
+.CO T
+command.
+.SP Options:
+None.
+.SE
+.KY MINUSSIGN
+.IP "[count] \-"
+Move to the first nonblank of the previous line,
+.LI count
+times.
+.sp
+It is an error if the movement is past the beginning of the file.
+.sp
+The
+.CO -
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to the current line minus
+.LI count .
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+None.
+.SE
+.KY \&.
+.IP "[count] \&."
+Repeat the last
+.CO vi
+command that modified text.
+The repeated command may be a command and motion component combination.
+If
+.LI count
+is specified, it replaces
+.i both
+the count specified for the repeated command, and, if applicable, for
+the repeated motion component.
+If
+.LI count
+is not specified, the counts originally specified to the command being
+repeated are used again.
+.sp
+As a special case, if the
+.CO \.
+command is executed immediately after the
+.CO u
+command, the change log is rolled forward or backward, depending on
+the action of the
+.CO u
+command.
+.SS
+.SP Line:
+Set as described for the repeated command.
+.SP Column:
+Set as described for the repeated command.
+.SP Options:
+None.
+.SE
+.KY /RE/
+.IP "/RE<carriage-return>"
+.Ip "/RE/ [offset]<carriage-return>"
+.KY ?RE?
+.Ip "?RE<carriage-return>"
+.Ip "?RE? [offset]<carriage-return>"
+.KY N
+.Ip "N"
+.KY n
+.Ip "n"
+Search forward or backward for a regular expression.
+The commands beginning with a slash
+.PQ /
+character are forward searches, the commands beginning with a
+question mark
+.PQ ?
+are backward searches.
+.CO Vi
+prompts with the leading character on the last line of the screen
+for a string.
+It then searches forward or backward in the file for the next
+occurrence of the string, which is interpreted as a Basic Regular
+Expression.
+.sp
+The
+.CO /
+and
+.CO ?
+commands are absolute movements.
+They may be used as the motion components of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the search started and ended on
+the first column of a line, in which case it is line oriented.
+In addition, forward searches ending at the first character of a line,
+and backward searches beginning at the first character in the line,
+are corrected to begin or end at the last character of the previous line.
+(Note, forward and backward searches can occur for both
+.CO /
+and
+.CO ?
+commands, if the
+.OP wrapscan
+option is set.)
+.sp
+If an offset from the matched line is specified (i.e. a trailing
+.QT /
+or
+.QT ?
+character is followed by a signed offset), the buffer will always
+be line oriented (e.g.
+.QT /string/+0
+will always guarantee a line orientation).
+.sp
+The
+.CO N
+command repeats the previous search, but in the reverse direction.
+The
+.CO n
+command repeats the previous search.
+If either the
+.CO N
+or
+.CO n
+commands are used as motion components for the 
+.CO !
+command, you will not be prompted for the text of the bang command,
+instead the previous bang command will be executed.
+.sp
+Missing RE's (e.g.
+.QT //<carriage-return> ,
+.QT /<carriage-return> ,
+.QT ??<carriage-return> ,
+or
+.QT ?<carriage-return>
+search for the last search RE, in the indicated direction.
+.sp
+Searches may be interrupted using the
+.LI <interrupt>
+character.
+.sp
+Multiple search patterns may be grouped together by delimiting
+them with semicolons and zero or more whitespace characters, e.g.
+.LI "/foo/ ; ?bar?"
+searches forward for
+.LI foo
+and then, from that location, backwards for
+.LI bar .
+When search patterns are grouped together in this manner,
+the search patterns are evaluated left to right with the
+final cursor position determined by the last search pattern.
+.sp
+It is also permissible to append a
+.CO z
+command to the search strings, e.g.
+.LI "/foo/ z."
+searches forward for the next occurrence of
+.LI foo ,
+and then positions that line in the middle of screen.
+.SS
+.SP Line:
+Set to the line in which the match occurred.
+.SP Column:
+Set to the first character of the matched string.
+.SP Options:
+Affected by the
+.OP edcompatible ,
+.OP extended ,
+.OP ignorecase ,
+.OP magic ,
+and
+.OP wrapscan
+options.
+.SE
+.KY 0
+.IP "0"
+Move to the first character in the current line.
+It is not an error to use the
+.CO 0
+command when the cursor is on the first character in the line,
+.sp
+The
+.CO 0
+command may be used as the motion component of other
+.CO vi
+commands,
+in which case it is an error if the cursor is on the first character
+in the line,
+and any text copied into a buffer is character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the first character in the line.
+.SP Options:
+None.
+.SE
+.KY :
+.IP ":"
+Execute an
+.CO ex
+command.
+.CO Vi
+prompts for an
+.CO ex
+command on the last line of the screen, using a colon
+.PQ :
+character.
+The command is terminated by a
+.LI <carriage-return> ,
+.LI <newline>
+or
+.LI <escape>
+character; all of these characters may be escaped by using a
+.LI "<literal-next>"
+character.
+The command is then executed.
+.sp
+If the
+.CO ex
+command writes to the screen,
+.CO vi
+will prompt the user for a
+.LI <carriage-return>
+before continuing
+when the
+.CO ex
+command finishes.
+Large amounts of output from the
+.CO ex
+command will be paged for the user, and the user prompted for a
+.LI <carriage-return>
+or
+.LI <space>
+key to continue.
+In some cases, a quit (normally a
+.QQ q
+character) or
+.LI <interrupt>
+may be entered to interrupt the
+.CO ex
+command.
+.sp
+When the
+.CO ex
+command finishes, and the user is prompted to resume visual mode,
+it is also possible to enter another
+.QT :
+character followed by another
+.CO ex
+command.
+.SS
+.SP Line:
+The current line is set as described for the
+.CO ex
+command.
+.SP Column:
+The current column is set as described for the
+.CO ex
+command.
+.SP Options:
+Affected as described for the
+.CO ex
+command.
+.SE
+.KY ;
+.IP "[count] ;"
+Repeat the last character find
+.LI count
+times.
+The last character find is one of the
+.CO F ,
+.CO f ,
+.CO T
+or
+.CO t
+commands.
+It is an error if a
+.CO F ,
+.CO f ,
+.CO T
+or
+.CO t
+command has not been performed yet.
+.sp
+The
+.CO ;
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the searched-for character for the
+.CO F
+and
+.CO f
+commands,
+before the character for the
+.CO t
+command
+and after the character for the
+.CO T
+command.
+.SP Options:
+None.
+.SE
+.KY <
+.IP "[count] < motion"
+.KY >
+.Ip "[count] > motion"
+Shift lines left or right.
+Shift the number of lines in the region specified by the
+.LI count
+and
+.LI motion
+left (for the
+.CO <
+command) or right (for the
+.CO >
+command) by the number of columns specified by the
+.OP shiftwidth
+option.
+Only whitespace characters are deleted when shifting left.
+Once the first character in the line no longer contains a whitespace
+character, the command will succeed,
+but the line will not be modified.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+Affected by the
+.OP shiftwidth
+option.
+.SE
+.KY @
+.IP "@ buffer"
+Execute a named buffer.
+Execute the named buffer as
+.CO vi
+commands.
+The buffer may include
+.CO ex
+commands, too, but they must be expressed as a
+.CO :
+command.
+If the buffer is line oriented,
+.LI <newline>
+characters are logically appended to each line of the buffer.
+If the buffer is character oriented,
+.LI <newline>
+characters are logically appended to all but the last line in the buffer.
+.sp
+If the buffer name is
+.QT @ ,
+or
+.QT * ,
+then the last buffer executed shall be used.
+It is an error to specify
+.QT @@
+or
+.QT @*
+if there were no previous buffer executions.
+The text of a buffer may contain a
+.CO @
+command,
+and it is possible to create infinite loops in this manner.
+(The
+.LI <interrupt>
+character may be used to interrupt the loop.)
+.SS
+.SP Line:
+The current line is set as described for the command(s).
+.SP Column:
+The current column is set as described for the command(s).
+.SP Options:
+None.
+.SE
+.KY A
+.IP "[count] A"
+Enter input mode, appending the text after the end of the line.
+If
+.LI count
+is specified, the text is repeatedly input
+.LI "count - 1"
+more times after input mode is exited.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY B
+.IP "[count] B"
+Move backward
+.LI count
+bigwords.
+Move the cursor backward to the beginning of a bigword by repeating the
+following algorithm: if the current position is at the beginning of a
+bigword or the character at the current position cannot be part of a bigword,
+move to the first character of the preceding bigword.
+Otherwise, move to the first character of the bigword at the current position.
+If no preceding bigword exists on the current line, move to the first
+character of the last bigword on the first preceding line that contains a
+bigword.
+.sp
+The
+.CO B
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Set to the line containing the word selected.
+.SP Column:
+Set to the first character of the word selected.
+.SP Options:
+None.
+.SE
+.KY C
+.IP "[buffer] [count] C"
+Change text from the current position to the end-of-line.
+If
+.LI count
+is specified, the input text replaces from the current position to
+the end-of-line, plus
+.LI "count - 1"
+subsequent lines.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY D
+.IP "[buffer] D"
+Delete text from the current position to the end-of-line.
+.sp
+It is not an error to execute the
+.CO D
+command on an empty line.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the character before the current character, or, column 1 if
+the cursor was on column 1.
+.SP Options:
+None.
+.SE
+.KY E
+.IP "[count] E"
+Move forward
+.LI count
+end-of-bigwords.
+Move the cursor forward to the end of a bigword by repeating the
+following algorithm: if the current position is the end of a
+bigword or the character at that position cannot be part of a bigword,
+move to the last character of the following bigword.
+Otherwise, move to the last character of the bigword at the current
+position.
+If no succeeding bigword exists on the current line,
+move to the last character of the first bigword on the next following
+line that contains a bigword.
+.sp
+The
+.CO E
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Set to the line containing the word selected.
+.SP Column:
+Set to the last character of the word selected.
+.SP Options:
+None.
+.SE
+.KY F
+.IP "[count] F <character>"
+Search
+.LI count
+times backward through the current line for
+.LI <character> .
+.sp
+The
+.CO F
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the searched-for character.
+.SP Options:
+None.
+.SE
+.KY G
+.IP "[count] G"
+Move to line
+.LI count ,
+or the last line of the file if
+.LI count
+not specified.
+.sp
+The
+.CO G
+command is an absolute movement.
+The
+.CO \&G
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to
+.LI count ,
+if specified, otherwise, the last line.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+None.
+.SE
+.KY H
+.IP "[count] H"
+Move to the screen line
+.LI "count - 1"
+lines below the top of the screen.
+.sp
+The
+.CO H
+command is an absolute movement.
+The
+.CO H
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to the line
+.LI "count - 1"
+lines below the top of the screen.
+.SP Column:
+Set to the first nonblank character of the
+.i screen
+line.
+.SP Options:
+None.
+.SE
+.KY I
+.IP "[count] I"
+Enter input mode, inserting the text at the beginning of the line.
+If
+.LI count
+is specified, the text input is repeatedly input
+.LI "count - 1"
+more times.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+None.
+.SE
+.KY J
+.IP "[count] J"
+Join lines.
+If
+.LI count
+is specified,
+.LI count
+lines are joined; a minimum of two lines are always joined,
+regardless of the value of
+.LI count .
+.sp
+If the current line ends with a whitespace character, all whitespace
+is stripped from the next line.
+Otherwise, if the next line starts with a open parenthesis
+.PQ (
+do nothing.
+Otherwise, if the current line ends with a question mark
+.PQ ? ,
+period
+.PQ \&.
+or exclamation point
+.PQ ! ,
+insert two spaces.
+Otherwise, insert a single space.
+.sp
+It is not an error to join lines past the end of the file,
+i.e. lines that do not exist.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the character after the last character of the next-to-last
+joined line.
+.SP Options:
+None.
+.SE
+.KY L
+.IP "[count] L"
+Move to the screen line
+.LI "count - 1"
+lines above the bottom of the screen.
+.sp
+The
+.CO L
+command is an absolute movement.
+The
+.CO L
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.SS
+.SP Line:
+Set to the line
+.LI "count - 1"
+lines above the bottom of the screen.
+.SP Column:
+Set to the first nonblank character of the
+.i screen
+line.
+.SP Options:
+None.
+.SE
+.KY  M
+.IP " M"
+Move to the screen line in the middle of the screen.
+.sp
+The
+.CO M
+command is an absolute movement.
+The
+.CO M
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.sp
+Historically, any
+.LI count
+specified to the
+.CO M
+command was ignored.
+.SS
+.SP Line:
+Set to the line in the middle of the screen.
+.SP Column:
+Set to the first nonblank character of the
+.i screen
+line.
+.SP Options:
+None.
+.SE
+.KY O
+.IP "[count] O"
+Enter input mode, appending text in a new line above the current line.
+If
+.LI count
+is specified, the text input is repeatedly input
+.LI "count - 1"
+more times.
+.sp
+Historically, any
+.LI count
+specified to the
+.CO O
+command was ignored.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY P
+.IP "[buffer] P"
+Insert text from a buffer.
+Text from the buffer (the unnamed buffer by default) is inserted
+before the current column or, if the buffer is line oriented,
+before the current line.
+.SS
+.SP Line:
+Set to the lowest numbered line insert,
+if the buffer is line oriented, otherwise unchanged.
+.SP Column:
+Set to the first nonblank character of the appended text,
+if the buffer is line oriented, otherwise, the last character
+of the appended text.
+.SP Options:
+None.
+.SE
+.KY Q
+.IP "Q"
+Exit
+.CO vi
+(or visual) mode and switch to
+.CO ex
+mode.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+No longer relevant.
+.SP Options:
+None.
+.SE
+.KY R
+.IP "[count] R"
+Enter input mode, replacing the characters in the current line.
+If
+.LI count
+is specified, the text input is repeatedly input
+.LI "count - 1"
+more times.
+.sp
+If the end of the current line is reached, no more characters are
+replaced and any further characters input are appended to the line.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY S
+.IP "[buffer] [count] S"
+Substitute
+.LI count
+lines.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY T
+.IP "[count] T <character>"
+Search backward,
+.LI count
+times,
+through the current line for the character
+.i after
+the specified
+.LI <character> .
+.sp
+The
+.CO T
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the character
+.i after
+the searched-for character.
+.SP Options:
+None.
+.SE
+.KY U
+.IP "U"
+Restore the current line to its state before the cursor last
+moved to it.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+The first character in the line.
+.SP Options:
+None.
+.SE
+.KY W
+.IP "[count] W"
+Move forward
+.LI count
+bigwords.
+Move the cursor forward to the beginning of a bigword by repeating the
+following algorithm: if the current position is within a bigword or the
+character at that position cannot be part of a bigword, move to the first
+character of the next bigword.
+If no subsequent bigword exists on the current line,
+move to the first character of the first bigword on the first following
+line that contains a bigword.
+.sp
+The
+.CO W
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+The line containing the word selected.
+.SP Column:
+The first character of the word selected.
+.SP Options:
+None.
+.SE
+.KY X
+.IP "[buffer] [count] X"
+Delete
+.LI count
+characters before the cursor.
+If the number of characters to be deleted is greater than or equal to
+the number of characters to the beginning of the line, all of the
+characters before the current cursor position, to the beginning of the
+line, are deleted.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the current character minus
+.LI count ,
+or the first character if count is greater than the number of
+characters in the line before the cursor.
+.SP Options:
+None.
+.SE
+.KY Y
+.IP "[buffer] [count] Y"
+Copy (or
+.QQ yank )
+.LI count
+lines into the specified buffer.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY ZZ
+.IP "ZZ"
+Write the file and exit
+.CO vi .
+The file is only written if it has been modified since the last
+complete write of the file to any file.
+.sp
+The
+.CO ZZ
+command will exit the editor after writing the file,
+if there are no further files to edit.
+Entering two
+.QQ quit
+commands (i.e.
+.CO wq ,
+.CO quit ,
+.CO xit
+or
+.CO ZZ )
+in a row will override this check and the editor will exit,
+ignoring any files that have not yet been edited.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY [[
+.IP "[count] [["
+Back up
+.LI count
+section boundaries.
+.sp
+The
+.CO [[
+command is an absolute movement.
+The
+.CO [[
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting position is column 0,
+in which case it is line oriented.
+.sp
+It is an error if the movement is past the beginning of the file.
+.SS
+.SP Line:
+Set to the previous line that is
+.LI count
+section boundaries back,
+or the first line of the file if no more section boundaries exist
+preceding the current line.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+Affected by the
+.OP sections
+option.
+.SE
+.KY ]]
+.IP "[count] ]]"
+Move forward
+.LI count
+section boundaries.
+.sp
+The
+.CO ]]
+command is an absolute movement.
+The
+.CO ]]
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting position is column 0,
+in which case it is line oriented.
+.sp
+It is an error if the movement is past the end of the file.
+.SS
+.SP Line:
+Set to the line that is
+.LI count
+section boundaries forward,
+or to the last line of the file if no more section
+boundaries exist following the current line.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+Affected by the
+.OP sections
+option.
+.SE
+.KY ^
+.IP "\&^"
+Move to first nonblank character on the current line.
+.sp
+The
+.CO ^
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the first nonblank character of the current line.
+.SP Options:
+None.
+.SE
+.KY _
+.IP "[count] _"
+Move down
+.LI "count - 1"
+lines, to the first nonblank character.
+The
+.CO _
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+line oriented.
+.sp
+It is not an error to execute the
+.CO _
+command when the cursor is on the first character in the line.
+.SS
+.SP Line:
+The current line plus
+.LI "count - 1" .
+.SP Column:
+The first nonblank character in the line.
+.SP Options:
+None.
+.SE
+.KY a
+.IP "[count] a"
+Enter input mode, appending the text after the cursor.
+If
+.LI count
+is specified, the text input is repeatedly input
+.LI "count - 1"
+more times.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY b
+.IP "[count] b"
+Move backward
+.LI count
+words.
+Move the cursor backward to the beginning of a word by repeating the
+following algorithm: if the current position is at the beginning of a word,
+move to the first character of the preceding word.
+Otherwise, the current position moves to the first character of the word
+at the current position.
+If no preceding word exists on the current line, move to the first
+character of the last word on the first preceding line that contains
+a word.
+.sp
+The
+.CO b
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Set to the line containing the word selected.
+.SP Column:
+Set to the first character of the word selected.
+.SP Options:
+None.
+.SE
+.KY c
+.IP "[buffer] [count] c motion"
+Change the region of text specified by the
+.LI count
+and
+.LI motion .
+If only part of a single line is affected, then the last character
+being changed is marked with a
+.QT $ .
+Otherwise, the region of text is deleted, and input mode is entered.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY d
+.IP "[buffer] [count] d motion"
+Delete the region of text specified by the
+.LI count
+and
+.LI motion .
+.SS
+.SP Line:
+Set to the line where the region starts.
+.SP Column:
+Set to the first character in the line after the last character in the
+region.
+If no such character exists, set to the last character before the region.
+.SP Options:
+None.
+.SE
+.KY e
+.IP "[count] e"
+Move forward
+.LI count
+end-of-words.
+Move the cursor forward to the end of a word by repeating the following
+algorithm: if the current position is the end of a word,
+move to the last character of the following word.
+Otherwise, move to the last character of the word at the current position.
+If no succeeding word exists on the current line, move to the last character
+of the first word on the next following line that contains a word.
+.sp
+The
+.CO e
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Set to the line containing the word selected.
+.SP Column:
+Set to the last character of the word selected.
+.SP Options:
+None.
+.SE
+.KY f
+.IP "[count] f <character>"
+Search forward,
+.LI count
+times, through the rest of the current line for
+.LI <character> .
+.sp
+The
+.CO f
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the searched-for character.
+.SP Options:
+None.
+.SE
+.KY i
+.IP "[count] i"
+Enter input mode, inserting the text before the cursor.
+If
+.LI count
+is specified, the text input is repeatedly input
+.LI "count - 1"
+more times.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY m
+.IP "m <character>"
+Save the current context (line and column) as
+.LI <character> .
+The exact position is referred to by
+.QT `<character> .
+The line is referred to by
+.QT '<character> .
+.sp
+Historically,
+.LI <character>
+was restricted to lower-case letters.
+.CO Nvi
+permits the use of any character.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged.
+.SP Options:
+None.
+.SE
+.KY o
+.IP "[count] o"
+Enter input mode, appending text in a new line under the current line.
+If
+.LI count
+is specified, the text input is repeatedly input
+.LI "count - 1"
+more times.
+.sp
+Historically, any
+.LI count
+specified to the
+.CO o
+command was ignored.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY p
+.IP "[buffer] p"
+Append text from a buffer.
+Text from the buffer (the unnamed buffer by default) is appended
+after the current column or, if the buffer is line oriented,
+after the current line.
+.SS
+.SP Line:
+Set to the first line appended, if the buffer is line oriented,
+otherwise unchanged.
+.SP Column:
+Set to the first nonblank character of the appended text if the buffer
+is line oriented, otherwise, the last character of the appended text.
+.SP Options:
+None.
+.SE
+.KY r
+.IP "[count] r <character>"
+Replace characters.
+The next
+.LI count
+characters in the line are replaced with
+.LI <character> .
+Replacing characters with
+.LI <newline>
+characters results in creating new, empty lines into the file.
+.sp
+If
+.LI <character>
+is
+.LI <escape> ,
+the command is cancelled.
+.SS
+.SP Line:
+Unchanged unless the replacement character is a
+.LI <newline> ,
+in which case it is set to the current line plus
+.LI "count - 1" .
+.SP Column:
+Set to the last character replaced,
+unless the replacement character is a
+.LI <newline> ,
+in which case the cursor is in column 1 of the last line inserted.
+.SP Options:
+None.
+.SE
+.KY s
+.IP "[buffer] [count] s"
+Substitute
+.LI count
+characters in the current line starting with the current character.
+.SS
+.SP Line:
+Set to the last line upon which characters were entered.
+.SP Column:
+Set to the last character entered.
+.SP Options:
+Affected by the
+.OP altwerase ,
+.OP autoindent ,
+.OP beautify ,
+.OP showmatch ,
+.OP ttywerase
+and
+.OP wrapmargin
+options.
+.SE
+.KY t
+.IP "[count] t <character>"
+Search forward,
+.LI count
+times, through the current line for the character immediately
+.i before
+.LI <character> .
+.sp
+The
+.CO t
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the character
+.i before
+the searched-for character.
+.SP Options:
+None.
+.SE
+.KY u
+.IP "u"
+Undo the last change made to the file.
+If repeated, the
+.CO u
+command alternates between these two states, and is its own inverse.
+When used after an insert that inserted text on more than one line,
+the lines are saved in the numeric buffers.
+.sp
+The
+.CO \&.
+command, when used immediately after the
+.CO u
+command, causes the change log to be rolled forward or backward,
+depending on the action of the
+.CO u
+command.
+.SS
+.SP Line:
+Set to the position of the first line changed, if the reversal affects
+only one line or represents an addition or change; otherwise, the line
+preceding the deleted text.
+.SP Column:
+Set to the cursor position before the change was made.
+.SP Options:
+None.
+.SE
+.KY w
+.IP "[count] w"
+Move forward
+.LI count
+words.
+Move the cursor forward to the beginning of a word by repeating the
+following algorithm: if the current position is at the
+beginning of a word, move to the first character of the next word.
+If no subsequent word exists on the current line, move to the first
+character of the first word on the first following line that contains
+a word.
+.sp
+The
+.CO w
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+.SS
+.SP Line:
+Set to the line containing the word selected.
+.SP Column:
+Set to the first character of the word selected.
+.SP Options:
+None.
+.SE
+.KY x
+.IP "[buffer] [count] x"
+Delete
+.LI count
+characters.
+The deletion is at the current character position.
+If the number of characters to be deleted is greater than or equal to
+the number of characters to the end of the line, all of the characters
+from the current cursor position to the end of the line are deleted.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Unchanged unless the last character in the line is deleted and the cursor
+is not already on the first character in the line, in which case it is
+set to the previous character.
+.SP Options:
+None.
+.SE
+.KY y
+.IP "[buffer] [count] y motion"
+Copy (or
+.QQ yank )
+the text region specified by the
+.LI count
+and
+.LI motion ,
+into a buffer.
+.SS
+.SP Line:
+Unchanged, unless the region covers more than a single line,
+in which case it is set to the line where the region starts.
+.SP Column:
+Unchanged, unless the region covers more than a single line,
+in which case it is set to the character were the region starts.
+.SP Options:
+None.
+.SE
+.KY z
+.IP "[count1] z [count2] type"
+Redraw the screen with a window
+.LI count2
+lines long, with line
+.LI count1
+placed as specified by the
+.LI type
+character.
+If
+.LI count1
+is not specified, it defaults to the current line.
+If
+.LI count2
+is not specified, it defaults to the current window size.
+.sp
+The following
+.LI type
+characters may be used:
+.SS
+.SP +
+If
+.LI count1
+is specified, place the line
+.LI count1
+at the top of the screen.
+Otherwise, display the screen after the current screen, similarly to the
+.CO <control-F>
+command.
+.SP <carriage-return>
+Place the line
+.LI count1
+at the top of the screen.
+.SP \&.
+Place the line
+.LI count1
+in the center of the screen.
+.SP \-
+Place the line
+.LI count1
+at the bottom of the screen.
+.SP ^
+If
+.LI count1
+is specified, place the line that is at the top of the screen 
+when
+.LI count1
+is at the bottom of the screen, at the bottom of the screen,
+i.e. display the screen before the screen before
+.LI count1 .
+Otherwise, display the screen before the current screen, similarly to the
+.CO <control-B>
+command.
+.SE
+.SS
+.SP Line:
+Set to
+.LI count1
+unless
+.LI count1
+is not specified and the
+.LI type
+character was either
+.QT ^
+or
+.QT + ,
+in which case it is set to the line before the first line on the
+previous screen or the line after the last line on the previous
+screen, respectively.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+None.
+.SE
+.KY {
+.IP "[count] {"
+Move backward
+.LI count
+paragraphs.
+.sp
+The
+.CO {
+command is an absolute movement.
+The
+.CO {
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting character is the first
+character on its line, in which case it is line oriented.
+.SS
+.SP Line:
+Set to the line containing the beginning of the previous paragraph.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+Affected by the
+.OP paragraph
+option.
+.SE
+.KY |
+.IP "[count] |"
+Move to a specific
+.i column
+position on the current line.
+.sp
+The
+.CO |
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented.
+It is an error to use the
+.CO |
+command as a motion component and for the cursor not to move.
+.SS
+.SP Line:
+Unchanged.
+.SP Column:
+Set to the character occupying the column position identified by
+.LI count ,
+if the position exists in the line.
+If the column length of the current line is less than
+.LI count ,
+the cursor is moved to the last character in the line.
+.SP Options:
+None.
+.SE
+.KY }
+.IP "[count] }"
+Move forward
+.LI count
+paragraphs.
+.sp
+The
+.CO }
+command is an absolute movement.
+The
+.CO }
+command may be used as the motion component of other
+.CO vi
+commands, in which case any text copied into a buffer is
+character oriented, unless the starting character is at or
+before any nonblank characters in its line,
+in which case it is line oriented.
+.SS
+.SP Line:
+Set to the line containing the beginning of the next paragraph.
+.SP Column:
+Set to the first nonblank character in the line.
+.SP Options:
+Affected by the
+.OP paragraph
+option.
+.SE
+.KY ~
+.IP "[count] ~"
+Reverse the case of the next
+.LI count
+character(s).
+This is the historic semantic for the
+.CO ~
+command and it is only in effect if the
+.OP tildeop
+option is not set.
+.sp
+Lowercase alphabetic characters are changed to uppercase,
+and uppercase characters are changed to lowercase.
+No other characters are affected.
+.sp
+Historically, the
+.CO ~
+command did not take an associated count, nor did it move past the
+end of the current line.
+As it had no associated motion it was difficult to change the case
+of large blocks of text.
+In
+.CO nvi ,
+if the cursor is on the last character of a line, and there are
+more lines in the file, the cursor moves to the next line.
+.sp
+It is not an error to specify a count larger than the number of
+characters between the cursor and the end of the file.
+.SS
+.SP Line:
+Set to the line of the character after
+.LI count
+characters, or, end of file.
+.SP Column:
+Set to the character after
+.LI count
+characters, or, end-of-file.
+.SP Options:
+Affected by the
+.OP tildeop
+option.
+.SE
+.KY ~
+.IP "[count] ~ motion"
+Reverse the case of the characters in a text region specified by the
+.LI count
+and
+.LI motion .
+Only in effect if the
+.OP tildeop
+option is set.
+.sp
+Lowercase characters are changed to uppercase,
+and uppercase characters are changed to lowercase.
+No other characters are affected.
+.SS
+.SP Line:
+Set to the line of the character after the last character in the region.
+.SP Column:
+Set to the character after the last character in the region.
+.SP Options:
+Affected by the
+.OP tildeop
+option.
+.SE
+.KY <interrupt>
+.IP "<interrupt>"
+Interrupt the current operation.
+Many of the potentially long-running
+.CO vi
+commands may be interrupted using the terminal interrupt character.
+These operations include searches, file reading and writing, filter
+operations and map character expansion.
+Interrupts are also enabled when running commands outside of
+.CO vi .
+.sp
+If the
+.LI <interrupt>
+character is used to interrupt while entering an
+.CO ex
+command, the command is aborted, the cursor returns to its previous
+position, and
+.CO vi
+remains in command mode.
+.sp
+Generally, if the
+.LI <interrupt>
+character is used to interrupt any
+operation, any changes made before the interrupt are left in place.
+.SS
+.SP Line:
+Dependent on the operation being interrupted.
+.SP Column:
+Dependent on the operation being interrupted.
+.SP Options:
+None.
+.SH 1 "Vi Text Input Commands"
+.pp
+The following section describes the commands available in the text
+input mode of the
+.CO vi
+editor.
+.pp
+Historically,
+.CO vi
+implementations only permitted the characters inserted on the current
+line to be erased.
+In addition, only the
+.LI <control-D>
+erase character and the
+.QT 0<control-D>
+and
+.QT ^<control-D>
+erase strings could erase autoindent characters.
+(Autoindent characters include both the characters inserted automatically
+at the beginning of an input line as well as characters inserted using the
+.LI <control-T>
+command.)
+This implementation permits erasure to continue past the beginning
+of the current line, and back to where text input mode was entered.
+In addition, autoindent characters may be erased using the standard
+erase characters.
+For the line and word erase characters, reaching the autoindent
+characters forms a
+.QQ soft
+boundary, denoting the end of the current word or line erase.
+Repeating the word or line erase key will erase the autoindent characters.
+.pp
+Historically,
+.CO vi
+always used
+.LI <control-H>
+and
+.LI <control-W>
+as character and word erase characters, respectively, regardless of
+the current terminal settings.
+This implementation accepts, in addition to these two characters,
+the current terminal characters for those operations.
+.KY <nul>
+.IP "<nul>"
+If the first character of the input is a
+.LI <nul> ,
+the previous input is replayed, as if just entered.
+.KY <control-D>
+.IP "<control-D>"
+If the previous character on the line was an autoindent character,
+erase characters to move the cursor back to the column immediately
+after the previous (1-based) column which is a multiple of the
+.OP shiftwidth
+edit option.
+This may result in any number of
+.LI <tab>
+and
+.LI <space>
+characters preceding the cursor being changed.
+.sp
+Otherwise, if the
+.OP autoindent
+option is set and the user is entering the first character in the line,
+.LI <control-D>
+is ignored.
+Otherwise, a literal
+.LI <control-D>
+character is entered.
+.KY ^<control-D>
+.IP "^<control-D>"
+If the previous character on the line was an autoindent character,
+erase all of the autoindent characters on the line.
+In addition, the autoindent level is reset to 0.
+.KY 0<control-D>
+.IP "0<control-D>"
+If the previous character on the line was an autoindent character,
+erase all of the autoindent characters on the line.
+The autoindent level is not altered.
+.KY <control-T>
+.IP "<control-T>"
+Insert sufficient
+.LI <tab>
+and
+.LI <space>
+characters to move the cursor forward to the column immediately
+after the next (1-based) column which is a multiple of the
+.OP shiftwidth
+edit option.
+This may result in any number of
+.LI <tab>
+and
+.LI <space>
+characters preceding the cursor being changed.
+.sp
+Historically,
+.CO vi
+did not permit the
+.LI <control-T>
+command to be used unless the cursor was at the first column of a new
+line or it was preceded only by autoindent characters.
+.CO Nvi
+permits it to be used at any time during insert mode.
+.KY <erase>
+.IP <erase>
+.KY <control-H>
+.Ip <control-H>
+Erase the last character.
+.KY "<literal-next>"
+.IP "<literal-next>"
+Quote the next character.
+The next character will not be mapped (see the
+.CO map
+command for more information)
+or interpreted specially.
+A carat
+.PQ ^
+character will be displayed immediately as a placeholder,
+but will be replaced by the next character.
+.KY <escape>
+.IP <escape>
+If on the colon command line, and the
+.OP filec
+edit option is set, behave as described for that option.
+Otherwise, if on the colon command line,
+execute the command.
+Otherwise, if not on the colon command line,
+resolve all text input into the file, and return to command mode.
+.KY "<line erase>"
+.IP "<line erase>"
+Erase the current line.
+.KY "<control-W>"
+.IP "<control-W>"
+.KY "<word erase>"
+.Ip "<word erase>"
+Erase the last word.
+The definition of word is dependent on the
+.OP altwerase
+and
+.OP ttywerase
+options.
+.KY "<control-X>"
+.IP "<control-X>[0-9A-Fa-f]+"
+Insert a character with the specified hexadecimal value into the text.
+The value is delimited by any non-hexadecimal character or the input
+of the maximum number of characters that can be translated into a single
+character value.
+.KY <interrupt>
+.IP "<interrupt>"
+Interrupt text input mode, returning to command mode.
+If the
+.LI <interrupt>
+character is used to interrupt inserting text into the file,
+it is as if the
+.LI <escape>
+character was used; all text input up to the interruption is
+resolved into the file.
diff --git a/usr.bin/nvi/docs/USD.doc/vi.ref/vi.ref b/usr.bin/nvi/docs/USD.doc/vi.ref/vi.ref
new file mode 100644 (file)
index 0000000..2247120
--- /dev/null
@@ -0,0 +1,1851 @@
+.\"    $NetBSD: vi.ref,v 1.1 2008/09/02 09:25:39 christos Exp $
+.\"
+.\" Copyright (c) 1994
+.\"     The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\"    Keith Bostic.  All rights reserved.
+.\"
+.\" This document may not be republished without written permission from
+.\" Keith Bostic. 
+.\"
+.\" See the LICENSE file for redistribution information.
+.\"
+.\"     @(#)vi.ref     8.88 (Berkeley) 10/19/96
+.\"
+.\"
+.so ref.so
+.tp
+.(l C
+.ps 12
+.ft B
+Vi/Ex Reference Manual
+.ft
+.ps
+.sp
+.i "Keith Bostic"
+.sp
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, California  94720
+.sp 1
+\*(td
+.)l
+.sp 3
+.(l C
+.i Abstract
+.)l
+.(q
+.pp
+This document is the reference guide for the 4.4BSD
+implementations of
+.EV nex nvi ,
+which are implementations of the historic Berkeley
+.EV ex vi
+editors.
+.)q
+.sp 3
+.(l C
+.i Licensing
+.)l
+.sp
+.lp
+Copyright (c) 1991, 1992, 1993, 1994
+.ti +5
+The Regents of the University of California.  All Rights Reserved.
+.lp
+Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
+.ti +5
+Keith Bostic.  All Rights Reserved.
+.sp
+.pp
+The vi program is freely redistributable.  You are welcome to copy,
+modify and share it with others under the conditions listed in the
+LICENSE file.  If any company (not individual!) finds vi sufficiently
+useful that you would have purchased it, or if any company wishes to
+redistribute it, contributions to the authors would be appreciated.
+.bp 2
+.(l C
+.i Acknowledgements
+.)l
+.sp
+.(q
+.pp
+Bruce Englar encouraged the early development of the historic
+.EV ex vi
+editor.
+Peter Kessler helped bring sanity to version 2's command layout.
+Bill Joy wrote versions 1 and 2.0 through 2.7,
+and created the framework that users see in the present editor.
+Mark Horton added macros and other features and made
+.EV ex vi
+work on a large number of terminals and Unix systems.
+.pp
+.CO Nvi
+is originally derived from software contributed to the University of
+California, Berkeley by Steve Kirkendall, the author of the
+.CO vi
+clone
+.CO elvis .
+.pp
+IEEE Standard Portable Operating System Interface for Computer
+Environments (POSIX) 1003.2 style Regular Expression support was
+done by Henry Spencer.
+.pp
+The curses library was originally done by Ken Arnold.
+Scrolling and reworking for
+.CO nvi
+was done by Elan Amir.
+.pp
+George Neville-Neil added the Tcl interpreter,
+and Sven Verdoolaege added the Perl interpreter.
+.pp
+Rob Mayoff added Cscope support.
+.pp
+The Institute of Electrical and Electronics Engineers has
+given us permission to reprint portions of their documentation.
+Portions of this document are reprinted and reproduced from
+IEEE Std 1003.2-1992, IEEE Standard Portable Operating
+System Interface for Computer Environments (POSIX),
+copyright 1992 by the Institute of Electrical and Electronics
+Engineers, Inc.
+.pp
+The financial support of UUNET Communications Services is gratefully
+acknowledged.
+.)q
+.sy echo -n >index
+.oh 'Vi/Ex Reference''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference'
+.bp 4
+.SH 1 Description
+.pp
+.CO Vi
+is a screen oriented text editor.
+.CO Ex
+is a line-oriented text editor.
+.CO Ex
+and
+.CO vi
+are different interfaces to the same program,
+and it is possible to switch back and forth during an edit session.
+.CO View
+is the equivalent of using the
+.b \-R
+(read-only) option of
+.CO vi .
+.pp
+This reference manual is the one provided with the
+.EV nex nvi
+versions of the
+.EV ex vi
+text editors.
+.EV Nex nvi
+are intended as bug-for-bug compatible replacements for the original
+Fourth Berkeley Software Distribution (4BSD)
+.EV ex vi
+programs.
+This reference manual is accompanied by a traditional-style manual page.
+That manual page describes the functionality found in
+.EV ex vi
+in far less detail than the description here.
+In addition, it describes the system interface to
+.EV ex vi ,
+e.g. command line options, session recovery, signals,
+environmental variables, and similar things.
+.pp
+This reference is intended for users already familiar with
+.EV ex vi .
+Anyone else should almost certainly read a good tutorial on the
+editor first.
+If you are in an unfamiliar environment,
+and you absolutely have to get work done immediately,
+see the section entitled
+.QB "Fast Startup"
+in the manual page.
+It is probably enough to get you started.
+.pp
+There are a few features in
+.EV nex nvi
+that are not found in historic versions of
+.EV ex vi .
+Some of the more interesting of those features are briefly described
+in the next section, entitled
+.QB "Additional Features" .
+For the rest of this document,
+.EV nex nvi
+is used only when it is necessary to distinguish it from the historic
+implementations of
+.EV ex vi .
+.pp
+Future versions of this software will be periodically made available
+by anonymous ftp, and can be retrieved from
+.LI ftp.cs.berkeley.edu ,
+in the directory
+.LI ucb/4bsd .
+.SH 1 "Additional Features in Nex/Nvi"
+.pp
+There are a few features in
+.EV nex nvi
+that are not found in historic versions of
+.EV ex vi .
+Some of the more interesting of these are as follows:
+.IP "8-bit clean data, large lines, files"
+.EV Nex nvi
+will edit any format file.
+Line lengths are limited by available memory,
+and file sizes are limited by available disk space.
+The
+.CO vi
+text input mode command
+.CO <control-X>
+can insert any possible character value into the text.
+.IP "Background and foreground screens"
+The
+.CO bg
+command backgrounds the current screen, and the
+.CO fg
+command foregrounds backgrounded screens.
+The
+.CO display
+command can be used to list the background screens.
+.IP "Command Editing"
+You can enter a normal editing window on the collected commands that
+you've entered on the
+.CO vi
+colon command-line,
+and then modify and/or execute the commands.
+See the
+.OP cedit
+edit option for more information.
+.IP "Displays"
+The
+.CO display
+command can be used to display the current buffers, the backgrounded
+screens, and the tags stack.
+.IP "Extended Regular Expressions"
+The
+.CO extended
+option causes Regular Expressions to be interpreted as as Extended
+Regular Expressions, (i.e. \fIegrep\fP(1) style Regular Expressions).
+.IP "File Name Completion"
+It is possible to do file name completion and file name displays when
+entering commands on the
+.CO vi
+colon command-line.
+See the
+.OP filec
+option for more information.
+.IP "Infinite undo"
+Changes made during an edit session may be rolled backward and forward.
+A
+.CO \&.
+command immediately after a
+.CO u
+command continues either forward or backward depending on whether the
+.CO u
+command was an undo or a redo.
+.IP "Left-right scrolling"
+The
+.CO leftright
+option causes
+.CO nvi
+to do left-right screen scrolling, instead of the traditional
+.CO vi
+line wrapping.
+.IP "Message Catalogs"
+It is possible to display informational and error messages in different
+languages by providing a catalog of messages.
+See the
+.OP msgcat
+option and the file
+.LI "catalog/README"
+for more information.
+.IP "Incrementing numbers"
+The
+.CO \&#
+command increments or decrements the number referenced by the cursor.
+.IP "Previous file"
+The
+.CO previous
+command edits the previous file from the argument list.
+.IP "Scripting languages"
+The
+.CO ":pe[rl] cmd" ,
+.CO ":perld[o] cmd"
+and
+.CO ":tc[l] cmd"
+commands execute Perl and Tcl/Tk commands, respectively,
+on lines from the edit buffer.
+See the
+.QB "Scripting Languages"
+section and the specific commands for more information.
+.\".IP "Shell screens"
+.\"The
+.\".CO ":sc[ript] [file ...]"
+.\"command runs a shell in the screen.
+.\"Editing is unchanged, with the exception that a \fC<carriage-return>\fP
+.\"enters the current line (stripped of any prompt) as input to the
+.\"shell.
+.IP "Split screens"
+The
+.CO Edit ,
+.CO Ex ,
+.CO Next ,
+.CO Previous ,
+.CO Tag
+and
+.CO Visual
+(in
+.CO vi
+mode) commands divide the screen into multiple editing regions and
+then perform their normal function in a new screen area.
+The
+.CO <control-W>
+command rotates between the foreground screens.
+The
+.CO resize
+command can be used to grow or shrink a particular screen.
+.IP "Tag stacks"
+Tags are now maintained in a stack.
+The
+.CO <control-T>
+command returns to the previous tag location.
+The
+.CO tagpop
+command returns to the most recent tag location by default, or,
+optionally to a specific tag number in the tag stack,
+or the most recent tag from a specified file.
+The
+.CO display
+command can be used to list the tags stack.
+The
+.CO tagtop
+command returns to the top of the tag stack.
+.IP "Usage information"
+The
+.CO exusage
+and
+.CO viusage
+commands provide usage information for all of the
+.CO ex
+and
+.CO vi
+commands by default, or, optionally, for a specific command or key.
+.IP "Word search"
+The
+.CO <control-A>
+command searches for the word referenced by the cursor.
+.SH 1 "Startup Information"
+.pp
+.EV Ex vi
+interprets one of two possible environmental variables and reads up to
+three of five possible files during startup.
+The variables and files are expected to contain
+.CO ex
+commands, not
+.CO vi
+commands.
+In addition, they are interpreted
+.i before
+the file to be edited is read, and therefore many
+.CO ex
+commands may not be used.
+Generally, any command that requires output to the screen or that
+needs a file upon which to operate, will cause an error if included
+in a startup file or environmental variable.
+.pp
+Because the
+.CO ex
+command set supported by
+.EV nex nvi
+is a superset of the command set supported by historical implementations of
+.CO ex ,
+.EV nex nvi
+can use the startup files created for the historical implementations,
+but the converse may not be true.
+.pp
+If the
+.b \-s
+(the historic \- option)
+is specified, or if standard input is redirected from a file,
+all environmental variables and startup files are ignored.
+.pp
+Otherwise, startup files and environmental variables are handled
+in the following order:
+.np
+The file
+.LI /etc/vi.exrc
+is read,
+as long as it is owned by root or the effective user ID of the user.
+.np
+The environmental variable
+.LI NEXINIT
+(or the variable
+.LI EXINIT ,
+if
+.LI NEXINIT
+is not set) is interpreted.
+.np
+If neither
+.LI NEXINIT
+or
+.LI EXINIT
+was set, and the
+.LI HOME
+environmental variable is set, the file
+.LI $HOME/.nexrc
+(or the file
+.LI $HOME/.exrc ,
+if
+.LI $HOME/.nexrc
+does not exist) is read,
+as long as the effective user ID of the user is root or is the same as
+the owner of the file.
+.sp
+When the $HOME directory is being used for both
+.EV nex nvi
+and an historic implementation of
+.EV ex vi ,
+a possible solution is to put
+.EV nex nvi
+specific commands in the
+.LI \&.nexrc
+file, along with a
+.CO ":source $HOME/.exrc"
+command to read in the commands common to both implementations.
+.np
+If the
+.OP exrc
+option was turned on by one of the previous startup information
+sources, the file
+.LI \&.nexrc
+(or the file
+.LI \&.exrc ,
+if
+.LI \&.nexrc
+does not exist) is read, as long as the effective user ID of the user
+is the same as the owner of the file.
+.pp
+No startup file is read if it is writable by anyone other than its owner.
+.pp
+It is not an error for any of the startup environmental variables or files
+not to exist.
+.pp
+Once all environmental variables are interpreted,
+and all startup files are read,
+the first file to be edited is read in (or a temporary file is created).
+.pp
+As soon as an existing file is loaded
+(either due to the command line parameters or from within the editor),
+any command specified using the
+.b \-c
+option is executed, in the context of that file.
+Note that such a command is an
+.CO ex
+command and thus obeys the
+.CO ex
+behaviour by first jumping to the end of the file, even if used with
+.CO vi .
+.SH 1 "Recovery"
+.pp
+There is no recovery program for
+.EV nex nvi ,
+nor does
+.EV nex nvi
+run setuid.
+Recovery files are created readable and writable by the owner only.
+Users may recover any file which they can read,
+and the superuser may recover any edit session.
+.pp
+Edit sessions are backed by files in the directory named by the
+.OP recdir
+option (the directory
+.LI /var/tmp/vi.recover
+by default), and are named
+.QC vi.XXXXXX ,
+where
+.QC XXXXXX
+is a number related to the process ID.
+When a file is first modified,
+a second recovery file containing an email message for the user is created,
+and is named
+.QC recover.XXXXXX ,
+where, again,
+.QC XXXXXX
+is associated with the process ID.
+Both files are removed at the end of a normal edit session,
+but will remain if the edit session is abnormally terminated
+or the user runs the
+.CO ex
+.CO preserve
+command.
+.pp
+The
+.OP recdir
+option may be set in either the user's or system's startup information,
+changing the recovery directory.
+(Note, however, that if a memory based file system is used as the backup
+directory, each system reboot will delete all of the recovery files!
+The same caution applies to directories such as
+.LI /tmp
+which are cleared of their contents by a system reboot, or
+.LI /usr/tmp
+which is periodically cleared of old files on many systems.)
+.pp
+The recovery directory should be owned by root, or at least by a pseudo-user.
+In addition, if directory
+.QQ sticky-bit
+semantics are available, the directory should have the sticky-bit
+set so that files may only be removed by their owners.
+The recovery directory must be read, write, and executable by any user,
+i.e. mode 1777.
+.pp
+If the recovery directory does not exist,
+.EV ex vi
+will attempt to create it.
+This can result in the recovery directory being owned by a normal user,
+which means that that user will be able to remove other user's recovery
+and backup files.
+This is annoying, but is not a security issue as the user cannot
+otherwise access or modify the files.
+.pp
+The recovery file has all of the necessary information in it to enable the
+user to recover the edit session.
+In addition, it has all of the necessary email headers for
+.XR sendmail 8 .
+When the system is rebooted, all of the files in
+.LI /var/tmp/vi.recover
+named
+.QC recover.XXXXXX
+should be sent to their owners, by email, using the
+.b \-t
+option of
+.CO sendmail
+(or a similar mechanism in other mailers).
+If
+.EV ex vi
+receives a hangup (SIGHUP) signal, or the user executes the
+.CO ex
+.CO preserve
+command,
+.EV ex vi
+will automatically email the recovery information to the user.
+.pp
+If your system does not have the
+.CO sendmail
+utility (or a mailer program which supports its interface)
+the source file
+.LI nvi/common/recover.c
+will have to be modified to use your local mail delivery programs.
+Note, if
+.EV nex nvi
+is changed to use another mailer,
+it is important to remember that the owner of the file given to
+the mailer is the
+.EV nex nvi
+user, so nothing in the file should be trusted as it may have been
+modified in an effort to compromise the system.
+.pp
+Finally, the owner execute bit is set on backup files when they are
+created, and unset when they are first modified, e.g. backup files
+that have no associated email recovery file will have this bit set.
+(There is also a small window where empty files can be created and
+not yet have this bit set.
+This is due to the method in which the files are created.)
+Such files should be deleted when the system reboots.
+.pp
+A simple way to do this cleanup is to run the Bourne shell script
+.CO recover ,
+from your
+.LI /etc/rc.local
+(or other system startup) file.
+The script should work with the historic Bourne shell,
+a POSIX 1003.2 shell or the Korn shell.
+The
+.CO recover
+script is installed as part of the
+.EV nex nvi
+installation process.
+.pp
+Consult the manual page for details on recovering preserved or
+aborted editing sessions.
+.SH 1 "Sizing the Screen"
+.pp
+The size of the screen can be set in a number of ways.
+.EV Ex vi
+takes the following steps until values are obtained for both the
+number of rows and number of columns in the screen.
+.np
+If the environmental variable
+.LI LINES
+exists,
+it is used to specify the number of rows in the screen.
+.np
+If the environmental variable
+.LI COLUMNS
+exists,
+it is used to specify the number of columns in the screen.
+.np
+The TIOCGWINSZ
+.XR ioctl 2
+is attempted on the standard error file descriptor.
+.np
+The termcap entry (or terminfo entry on System V machines)
+is checked for the
+.QQ li
+entry (rows) and the
+.QQ co
+entry (columns).
+.np
+The number of rows is set to 24, and the number of columns is set to 80.
+.pp
+If a window change size signal (SIGWINCH) is received,
+the new window size is retrieved using the TIOCGWINSZ
+.XR ioctl 2
+call, and all other information is ignored.
+.SH 1 "Character Display"
+.pp
+In both
+.CO ex
+and
+.CO vi
+printable characters as defined by
+.XR isprint 3
+are displayed using the local character set.
+.pp
+Non-printable characters, for which
+.XR iscntrl 3
+returns true, and which are less than octal \e040,
+are displayed as the string
+.QT ^<character> ,
+where
+.LI <character>
+is the character that is the original character's value offset from the
+.QT @
+character.
+For example, the octal character \e001 is displayed as
+.QT ^A .
+If
+.XR iscntrl 3
+returns true for the octal character \e177,
+it is displayed as the string
+.QT ^? .
+All other characters are displayed as either hexadecimal values,
+in the form
+.QT "0x<high-halfbyte> ... 0x<low-halfbyte>" ,
+or as octal values, in the form
+.QT "\e<high-one-or-two-bits> ... \e<low-three-bits>" .
+The display of unknown characters is based on the value of the
+.OP octal
+option.
+.pp
+In
+.CO vi
+command mode, the cursor is always positioned on the last column of
+characters which take up more than one column on the screen.
+In
+.CO vi
+text input mode, the cursor is positioned on the first column of
+characters which take up more than one column on the screen.
+.SH 1 "Multiple Screens"
+.pp
+.CO Nvi
+supports multiple screens by dividing the window into regions.
+It also supports stacks of screens by permitting the user to change
+the set of screens that are currently displayed.
+.pp
+The
+.CO Edit ,
+.CO Ex ,
+.CO Fg ,
+.CO Next ,
+.CO Previous ,
+.CO Tag
+and
+.CO Visual
+(in
+.CO vi
+mode)
+commands divide the current screen into two regions of approximately
+equal size and then perform their usual action in a new screen area.
+If the cursor is in the lower half of the screen, the screen will split
+up, i.e. the new screen will be above the old one.
+If the cursor is in the upper half of the screen, the new screen will be
+below the old one.
+.pp
+When more than one screen is editing a file, changes in any screen are
+reflected in all other screens editing the same file.
+Exiting a screen without saving any changes (or explicitly discarding
+them) is permitted until the last screen editing the file is exited,
+at which time the changes must be saved or discarded.
+.pp
+The
+.CO resize
+command permits resizing of individual screens.
+Screens may be grown, shrunk or set to an absolute number of rows.
+.pp
+The
+.CO ^W
+command is used to switch between screens.
+Each
+.CO ^W
+moves to the next lower screen in the window, or to the first screen
+in the window if there are no lower screens.
+.pp
+The
+.CO bg
+command
+.QQ backgrounds
+the current screen.
+The screen disappears from the window,
+and the rows it occupied are taken over by a neighboring screen.
+It is an error to attempt to background the only screen in the window.
+.pp
+The
+.CO "display screens"
+command displays the names of the files associated with the current
+backgrounded screens in the window.
+.pp
+The
+.CO "fg [file]"
+command moves the specified screen from the list of backgrounded screens
+to the foreground.
+If no file argument is specified, the first screen on the list is
+foregrounded.
+By default,
+foregrounding consists of backgrounding the current screen,
+and replacing its space in the window with the foregrounded screen.
+.pp
+Capitalizing the first letter of the command, i.e.
+.CO Fg ,
+will foreground the backgrounded screen in a new screen instead of
+swapping it with the current screen.
+.pp
+If the last foregrounded screen in the window is exited,
+and there are backgrounded screens,
+the first screen on the list of backgrounded screens takes over the window.
+.SH 1 "Tags, Tag Stacks, and Cscope"
+.pp
+.CO Nvi
+supports the historic
+.CO vi
+tag command
+.CO <control-]> ,
+and the historic
+.CO ex
+tag command
+.CO tag .
+These commands change the current file context to a new location,
+based on information found in the
+.LI tags
+files.
+If you are unfamiliar with these commands,
+you should review their description in the
+.CO ex
+and
+.CO vi
+commands section of this manual.
+For additional information on tags files,
+see the discussion of the
+.OP tags
+edit option and the system
+.XR ctags 1
+manual page.
+.pp
+In addition,
+.CO nvi
+supports the notion of
+.QQ "tags stacks" ,
+using the
+.CO <control-T>
+command.
+The
+.CO <control-T>
+command returns the user to the previous context, i.e.,
+the last place from which a
+.CO <control-]>
+or
+.CO "tag"
+command was entered.
+These three commands provide the basic functionality which allows you
+to use
+.CO vi
+to review source code in a structured manner.
+.pp
+.CO Nvi
+also provides two other basic
+.CO ex
+commands for tag support:
+.CO tagpop
+and
+.CO tagtop .
+The
+.CO tagpop
+command is identical to the
+.CO <control-T>
+command,
+with the additional functionality that you may specify that modifications
+to the current file are to be discarded.
+This cannot be done using the
+.CO <control-T>
+command.
+The
+.CO tagtop
+command discards all of the contexts that have been pushed onto the tag
+stack, returning to the context from which the first
+.CO <control-]>
+or
+.CO tag
+command was entered.
+.pp
+The historic
+.XR ctags 1
+tags file format supports only a single location per tag,
+normally the function declaration or structure or string definition.
+More sophisticated source code tools often provide multiple locations
+per tag, e.g.,
+a list of the places from which a function is called or a string
+definition is used.
+An example of this functionality is the System V source code tool,
+.CO cscope .
+.sp
+.CO Cscope
+creates a database of information on source code files,
+and supports a query language for that information as described in the
+.XR cscope 1
+manual page.
+.CO Nvi
+contains an interface to the
+.CO cscope
+query language which permits you to query
+.CO cscope
+and then sequentially step through the locations in the sources files which
+.CO cscope
+returns.
+There are two
+.CO nvi
+commands which support this ability to step through multiple locations.
+They are the
+.CO ex
+commands
+.CO tagnext
+and
+.CO tagprev .
+The
+.CO tagnext
+command moves to the next location for the current tag.
+The
+.CO tagprev
+command moves to the previous location for the current tag.
+(See the
+.CO tagnext
+and
+.CO tagprev
+command discussion in the
+.CO ex
+commands section of this manual for more information.)
+At any time during this sequential walk,
+you may use the
+.CO <control-]> ,
+.CO tag
+or
+.CO cscope
+commands to move to a new tag context, and then use the
+.CO <control-T>
+or
+.CO tagpop
+commands to return and continue stepping through the locations for this
+tag.
+This is similar to the previous model of a simple tag stack,
+except that each entry in the tag stack may have more than one file context
+that is of interest.
+.pp
+Although there is no widely distributed version of
+.XR ctags 1
+that creates tags files with multiple locations per tag,
+.CO nvi
+has been written to understand the obvious extension to the historic
+tags file format, i.e., more than a single line in the tags file with
+the same initial tag name.
+If you wish to extend your
+.CO ctags 
+implementation or other tool with which you build tags files,
+this extension should be simple and will require no changes to
+.CO nvi .
+.pp
+The
+.CO nvi
+and
+.CO cscope
+interface is based on the new
+.CO ex
+command
+.CO cscope ,
+which has five subcommands:
+.CO add ,
+.CO find ,
+.CO help ,
+.CO kill
+and
+.CO reset .
+The subcommand
+.CO find
+itself has eight subcommands:
+.CO \&c ,
+.CO \&d ,
+.CO \&e ,
+.CO \&f ,
+.CO \&g ,
+.CO \&i ,
+.CO \&s
+and
+.CO \&t .
+.pp
+.IP "cs[cope] a[dd] file"
+The
+.CO add
+command attaches to the specified
+.CO cscope
+database.
+The file name is expanded using the standard filename expansions.
+If
+.CO file
+is a directory, the file
+.QQ cscope.out
+in that directory is used as the database.
+.pp
+After
+.CO nvi
+attaches to a new database,
+all subsequent
+.CO cscope
+queries will be asked of that database.
+The result of any single query is the collection of response to the query
+from all of the attached databases.
+.sp
+If the
+.QQ CSCOPE_DIRS
+environmental variable is set when
+.CO nvi
+is run,
+it is expected to be a <colon> or <blank>-separated list of
+.CO cscope
+databases or directories containing
+.CO cscope
+databases, to which the user wishes to attach.
+.IP ":cs[cope] f[ind] c|d|e|f|g|i|s|t buffer|pattern"
+The
+.CO find
+command is the
+.CO cscope
+query command for
+.CO nvi .
+For this command,
+.CO nvi
+queries all attached
+.CO cscope
+databases for the pattern.
+If the pattern is a double-quote character followed by a valid buffer
+name (e.g.,
+.LI """<character>" ), 
+then the contents of the named buffer are used as the pattern.
+Otherwise, the pattern is a Regular Expression.
+.sp
+The
+.CO find
+command pushes the current location onto the tags stack,
+and switches to the first location resulting from the query,
+if the query returned at least one result.
+.sp
+File names returned by the
+.CO cscope
+query, if not absolute paths, are searched for relative to the directory
+where the
+.CO cscope
+database is located.
+In addition, if the file
+.QQ cscope.tpath
+appears in the same directory as the
+.CO cscope
+database,
+it is expected to contain a colon-separated list of directory names
+where files referenced by its associated
+.CO cscope
+database may be found.
+.sp
+The
+.CO find
+subcommand is one of the following:
+.SS
+.SP \&c
+Find callers of the name.
+.SP \&d
+Find all function calls made from name.
+.SP \&e
+Find pattern.
+.SP \&f
+Find files with name as substring.
+.SP \&g
+Find definition of name.
+.SP \&i
+Find files #including name.
+.SP \&s
+Find all uses of name.
+.SP \&t
+Find assignments to name.
+.SE
+.IP ":cs[cope] h[elp] [command]"
+List the
+.CO cscope
+commands,
+or optionally list usage help for any single
+.CO cscope
+command.
+.IP ":display c[onnections]"
+Display the list of
+.CO cscope
+databases to which
+.CO nvi
+is currently connected.
+.IP ":cs[cope] k[ill] #"
+Disconnect from a specific
+.CO cscope
+database.
+The connection number is the one displayed by the
+.CO ex
+.CO "display connections"
+command.
+.IP ":cs[cope] r[eset]"
+Disconnect from all attached
+.CO cscope
+databases.
+.pp
+Cscope is not freely redistributable software,
+but is fairly inexpensive and easily available.
+To purchase a copy of
+.CO cscope ,
+see http://www.att.com/ssg/products/toolchest.html.
+.SH 1 "Regular Expressions and Replacement Strings"
+.pp
+Regular expressions are used in line addresses,
+as the first part of the
+.CO ex
+.CO substitute ,
+.CO global ,
+and
+.CO v
+commands, and in search patterns.
+.pp
+The regular expressions supported by
+.EV ex vi
+are, by default, the Basic Regular Expressions (BRE's) described in the
+IEEE POSIX Standard 1003.2.
+The
+.OP extended
+option causes all regular expressions to be interpreted as the Extended
+Regular Expressions (ERE's) described by the same standard.
+(See
+.XR re_format 7
+for more information.)
+Generally speaking, BRE's are the Regular Expressions found in
+.XR ed 1
+and
+.XR grep 1 ,
+and ERE's are the Regular Expressions found in
+.XR egrep 1 .
+.pp
+The following is not intended to provide a description of Regular
+Expressions.
+The information here only describes strings and characters which
+have special meanings in the
+.EV ex vi
+version of RE's,
+or options which change the meanings of characters that normally
+have special meanings in RE's.
+.np
+An empty RE (e.g.
+.QT //
+or
+.QT ??
+is equivalent to the last RE used.
+.np
+The construct
+.QT \e<
+matches the beginning of a word.
+.np
+The construct
+.QT \e>
+matches the end of a word.
+.np
+The character
+.QT ~
+matches the replacement part of the last
+.CO substitute
+command.
+.pp
+When the
+.OP magic
+option is
+.i not
+set, the only characters with special meanings are a
+.QT ^
+character at the beginning of an RE, a
+.QT $
+character at the end of an RE, and the escaping character
+.QT \e .
+The characters
+.QT \&. ,
+.QT * ,
+.QT [
+and
+.QT ~
+are treated as ordinary characters unless preceded by a
+.QT \e ;
+when preceded by a
+.QT \e
+they regain their special meaning.
+.pp
+Replacement strings are the second part of a
+.CO substitute
+command.
+.pp
+The character
+.QT &
+(or
+.QT \e&
+if the
+.OP magic
+option is
+.i not
+set) in the replacement string stands for the text matched by the RE
+that is being replaced.
+The character
+.QT ~
+(or
+.QT \e~
+if the
+.OP magic
+option is
+.i not
+set) stands for the replacement part of the previous
+.CO substitute
+command.
+It is only valid after a
+.CO substitute
+command has been performed.
+.pp
+The string
+.QT \e# ,
+where
+.QT #
+is an integer value from 1 to 9, stands for the text matched by
+the portion of the RE enclosed in the
+.QT # 'th
+set of escaped parentheses, e.g.
+.QT \e(
+and
+.QT \e) .
+For example,
+.QT "s/abc\e(.*\e)def/\e1/"
+deletes the strings
+.QT abc
+and
+.QT def
+from the matched pattern.
+.pp
+The strings
+.QT \el ,
+.QT \eu ,
+.QT \eL
+and
+.QT \eU
+can be used to modify the case of elements in the replacement string.
+The string
+.QT \el
+causes the next character to be converted to lowercase;
+the string
+.QT \eu
+behaves similarly, but converts to uppercase
+(e.g.
+.LI s/abc/\eU&/
+replaces the string
+.LI abc
+with
+.LI ABC ).
+The string
+.QT \eL
+causes characters up to the end of the string or the next occurrence
+of the strings
+.QT \ee
+or
+.QT \eE
+to be converted to lowercase;
+the string
+.QT \eU
+behaves similarly, but converts to uppercase.
+.pp
+If the entire replacement pattern is
+.QT % ,
+then the last replacement pattern is used again.
+.pp
+In
+.CO vi ,
+inserting a
+.LI <control-M>
+into the replacement string will cause
+the matched line to be split into two lines at that point.
+(The
+.LI <control-M>
+will be discarded.)
+.SH 1 "Scripting Languages"
+.pp
+The
+.CO nvi
+editor currently supports two scripting languages, Tcl/Tk and Perl.
+(Note that Perl4 isn't sufficient, and that the Perl5 used must be
+version 5.002 or later.
+See the
+.QB "Building Nvi"
+section for more information.
+.pp
+The scripting language interface is still being worked on,
+therefore the following information is probably incomplete,
+probably wrong in cases, and likely to change.
+See the
+.LI perl_api
+and
+.LI tcl_api
+source directories for more information.
+As a quick reference, the following function calls are provided for
+both the Perl and Tcl interfaces.
+The Perl interface uses a slightly different naming convention,
+e.g. ``viFindScreen'' is named ``VI::FindScreen''.
+.IP "viFindScreen file"
+Return the
+.LI "screenId" associated with
+.LI file .
+.IP "viAppendLine screenId lineNumber text"
+Append
+.LI text
+as a new line after line number
+.LI lineNumber ,
+in the screen
+.LI screenId .
+.IP "viDelLine screenId lineNum"
+Delete the line
+.LI lineNumber
+from the screen
+.LI screenId .
+.IP "viGetLine screenId lineNumber"
+Return the line
+.LI lineNumber
+from the screen
+.LI screenId .
+.IP "viInsertLine screenId lineNumber text"
+Insert
+.LI text
+as a new line before line number
+.LI lineNumber
+in the screen
+.LI screenId .
+.IP "viLastLine screenId"
+Return the line number of the last line in the screen
+.LI screenId .
+.IP "viSetLine screenId lineNumber text"
+Change the line
+.LI lineNumber
+in the screen
+.LI screenId
+to match the specified
+.LI text .
+.IP "viGetMark screenId mark"
+Return the current line and column for the specified
+.LI mark
+from the screen
+.LI screenId .
+.IP "viSetMark screenId mark line column"
+Set the specified
+.LI mark
+to be at line
+.LI line ,
+column
+.LI column ,
+in the screen
+.LI screenId .
+.IP "viGetCursor screenId"
+Return the current line and column for the cursor in the screen
+.LI screenId .
+.IP "viSetCursor screenId line column"
+Set the cursor in the screen
+.LI screenId
+to the specified
+.LI line
+and
+.LI column .
+.IP "viMsg screenId text"
+Display the specified
+.LI text
+as a vi message in the screen
+.LI screenId .
+.IP "viNewScreen screenId [file]"
+Create a new screen.
+.IP "viEndScreen screenId"
+Exit the screen 
+.LI screenId .
+.IP "viSwitchScreen screenId screenId"
+Switch from the screen
+.LI screenId
+to the screen
+.LI screenId .
+.IP "viMapKey screenId key tclproc"
+Map the specified
+.LI key
+in the screen
+.LI screenId
+to the Tcl procedure
+.LI tclproc .
+.IP "viUnmMapKey screenId key"
+Unmap the specified
+.LI key
+in the screen
+.LI screenId
+.IP "viGetOpt screenId option"
+Return the value of the specified
+.LI option
+from the screen
+.LI screenId .
+.IP "viSetOpt screenId command"
+Set one or more options in the screen
+.LI screenId .
+.SH 1 "General Editor Description"
+.pp
+When
+.CO ex
+or
+.CO vi
+are executed,
+the text of a file is read (or a temporary file is created),
+and then all editing changes happen within the context of the
+copy of the file.
+.i "No changes affect the actual file until the file is written out" ,
+either using a write command or another command which is affected by the
+.OP autowrite
+option.
+.pp
+All files are locked (using the
+.XR flock 2
+or
+.XR fcntl 2
+interfaces) during the edit session,
+to avoid inadvertently making modifications to multiple copies of the file.
+If a lock cannot be obtained for a file because it is locked by another
+process, the edit session is read-only (as if the
+.OP readonly
+option or the
+.b \-R
+flag had been specified).
+If a lock cannot be obtained for other reasons, the edit session will
+continue, but the file status information
+(see the
+.CO <control-G>
+command) will reflect this fact.
+.pp
+Both
+.CO ex
+and
+.CO vi
+are modeful editors, i.e. they have two modes,
+.QQ command
+mode and
+.QQ "text input"
+mode.
+The former is intended to permit you to enter commands which modifies
+already existing text.
+The latter is intended to permit you to enter new text.
+When
+.CO ex
+first starts running, it is in command mode, and usually displays a prompt
+(see the
+.OP prompt
+option for more information).
+The prompt is a single colon
+.PQ :
+character.
+There are three commands that switch
+.CO ex
+into text input mode:
+.CO append ,
+.CO change
+and
+.CO insert .
+Once in input mode, entering a line containing only a single period
+.PQ \&.
+ends text input mode and returns to command mode,
+where the prompt is redisplayed.
+.pp
+When
+.CO vi
+first starts running, it is in command mode as well.
+There are eleven commands that switch
+.CO vi
+into text input mode:
+.CO A ,
+.CO a ,
+.CO C ,
+.CO c ,
+.CO I ,
+.CO i ,
+.CO O ,
+.CO o ,
+.CO R ,
+.CO S
+and
+.CO s .
+Once in input mode, entering an
+.LI <escape>
+character ends text input mode and returns to command mode.
+.pp
+.EV Ex vi
+present three different interfaces to editing a file.
+.CO Ex
+presents a line oriented interface.
+.CO Vi
+presents a full screen display oriented interface,
+also known as
+.QQ "visual mode" .
+In addition, there is a third mode,
+.QQ "open mode" ,
+which is line oriented,
+but supports cursor movement and editing within the displayed line,
+similarly to visual mode.
+Open mode is not yet implemented in
+.CO nvi .
+.pp
+The following words have special meanings in both the
+.CO ex
+and
+.CO vi
+command descriptions:
+.KY <interrupt>
+.IP <interrupt>
+The interrupt character is used to interrupt the current operation.
+Normally
+.LI <control-C> ,
+whatever character is set for the current terminal is used.
+.KY "<literal-next>"
+.IP "<literal-next>"
+The literal next character is used to escape the subsequent character
+from any special meaning.
+This character is always
+.LI <control-V> .
+If the terminal is not set up to do XON/XOFF flow control,
+then
+.LI <control-Q>
+is used to mean literal next as well.
+.KY "current pathname"
+.IP "current pathname"
+The pathname of the file currently being edited by vi.
+When the percent character
+.PQ %
+appears in a file name entered as part of an
+.CO ex
+command argument, it is replaced by the current pathname.
+(The
+.QT %
+character can be escaped by preceding it with a backslash.)
+.KY "alternate pathname"
+.IP "alternate pathname"
+The name of the last file name mentioned in an
+.CO ex
+command, or,
+the previous current pathname if the last file mentioned
+becomes the current file.
+When the hash mark character
+.PQ #
+appears in a file name entered as part of an
+.CO ex
+command argument, it is replaced by the alternate pathname.
+(The
+.QT #
+character can be escaped by preceding it with a backslash.)
+.KY buffer
+.IP buffer
+One of a number of named areas for saving copies of text.
+Commands that change or delete text can save the changed or deleted
+text into a specific buffer, for later use, if the command allows
+it (i.e. the
+.CO ex
+.CO change
+command cannot save the changed text in a named buffer).
+Buffers are named with a single character, preceded by a double quote,
+e.g.
+.LI """<character>"
+in
+.CO vi
+and
+without the double quote, e.g.
+.LI <character> ,
+in
+.CO ex .
+(The double quote isn't necessary for
+.CO ex
+because buffers names are denoted by their position in the command line.)
+Historic implementations of
+.EV ex vi
+limited
+.LI <character>
+to the alphanumeric characters;
+.EV nex nvi
+permits the use of any character without another meaning in the position
+where a buffer name is expected.
+.sp
+Buffers named by uppercase characters are the same as buffers
+named by lowercase characters, e.g. the buffer named by the
+English character
+.QT A
+is the same as the buffer named by the character
+.QT a ,
+with the exception that, if the buffer contents are being changed (as
+with a text deletion or
+.CO vi
+.CO change
+command), the text is
+.i appended
+to the buffer, instead of replacing the current contents.
+.sp
+The buffers named by the numeric characters (in English,
+.QT 1
+through
+.QT 9 ),
+are special.
+If a region of text including characters from more than one line,
+or a single line of text specified by using a line-oriented motion,
+is changed or deleted in the file using the
+.CO vi
+.CO change
+or
+.CO delete
+commands, a copy of the text is placed into the numeric buffer
+.QT 1 ,
+regardless of the user specifying another buffer in which to save it.
+In addition, there are a few commands which, when used as a
+.LI motion
+with the
+.CO vi
+.CO change
+and
+.CO delete
+commands,
+.i always
+copy the specified region of text into the numeric buffers regardless
+of the region including characters from more than one line.
+These commands are:
+.sp
+.ne 3v
+.ft C
+.TS
+r r r r.
+<control-A>    %       (       )
+`<character>   /       ?       N
+n      {       }
+.TE
+.ft R
+.sp
+Before this copy is done, the previous contents of buffer
+.QT 1
+are moved into buffer
+.QT 2 ,
+.QT 2
+into buffer
+.QT 3 ,
+and so on.
+The contents of buffer
+.QT 9
+are discarded.
+In
+.CO vi ,
+text may be explicitly stored into the numeric buffers.
+In this case, the buffer rotation described above occurs before the
+replacement of the buffer's contents.
+The numeric buffers are only available in
+.LI visual
+and
+.LI open
+modes,
+and are not accessible by
+.CO ex
+in any way, although changed and deleted text is still stored there
+while in
+.CO ex
+mode.
+.sp
+When a
+.CO vi
+command synopsis shows both a
+.LI [buffer]
+and a
+.LI [count] ,
+they may be presented in any order.
+.sp
+Finally, all buffers are either
+.QQ line
+or
+.QQ character
+oriented.
+All
+.CO ex
+commands which store text into buffers are line oriented.
+Some
+.CO vi
+commands which store text into buffers are line oriented,
+and some are character oriented; the description for each applicable
+.CO vi
+command notes whether text copied into buffers using the command
+is line or character oriented.
+In addition, the
+.CO vi
+command
+.CO "display buffers"
+displays the current orientation for each buffer.
+Generally, the only importance attached to this orientation is that
+if the buffer is subsequently inserted into the text, line oriented
+buffers create new lines for each of the lines they contain, and
+character oriented buffers create new lines for any lines
+.i other
+than the first and last lines they contain.
+The first and last lines are inserted into the text at the current
+cursor position, becoming part of the current line.
+If there is more than one line in the buffer, however, the current
+line itself will be split.
+.KY "unnamed buffer"
+.IP "unnamed buffer"
+The unnamed buffer is a text storage area which is used by commands
+that use or operate on a buffer when no buffer is specified by the user.
+If the command stores text into a buffer,
+the text is stored into the unnamed buffer even if a buffer is also
+specified by the user.
+It is not possible to append text to the unnamed buffer.
+If text is appended to a named buffer,
+the named buffer contains both the old and new text,
+while the unnamed buffer contains only the new text.
+There is no way to explicitly reference the unnamed buffer.
+.sp
+Historically, the contents of the unnamed buffer were discarded by many
+different commands, even ones that didn't store text into it.
+.EV Nex nvi
+never discards the contents of the unnamed buffer until new text
+replaces them.
+.KY whitespace
+.IP whitespace
+The characters <tab> and <space>.
+.KY "<carriage-return>"
+.IP "<carriage-return>"
+The character represented by an ASCII
+.LI <control-M> .
+This character is almost always treated identically to a
+.LI <newline>
+character, but differs in that it can be escaped into the file text or
+into a command.
+.KY <newline>
+.IP <newline>
+The character represented by an ASCII
+.LI <control-J> .
+This character is almost always treated identically to a
+.LI <control-M>
+character, but differs in that it cannot be escaped into the file text or
+into a command.
+.oh 'Vi/Ex Reference (Vi Commands)''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference (Vi Commands)'
+.so vi.cmd.roff
+.oh 'Vi/Ex Reference''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference'
+.SH 1 "Ex Addressing"
+.pp
+Addressing in
+.CO ex
+(and when
+.CO ex
+commands are executed from
+.CO vi )
+relates to the current line.
+In general, the current line is the last line affected by a command.
+The exact effect on the current line is discussed under the description
+of each command.
+When the file contains no lines, the current line is zero.
+.pp
+Addresses are constructed by one or more of the following methods:
+.np
+The address
+.QT \&.
+refers to the current line.
+.np
+The address
+.QT $
+refers to the last line of the file.
+.np
+The address
+.QT N ,
+where
+.LI N
+is a positive number, refers to the N-th line of the file.
+.np
+The address
+.QT '<character>
+or
+.QT `<character>
+refers to the line marked with the name
+.LI <character> .
+(See the
+.CO k
+or
+.CO m
+commands for more information on how to mark lines.)
+.np
+A regular expression (RE) enclosed by slashes
+.PQ /
+is an address,
+and it refers to the first line found by searching forward from the line
+.i after
+the current line toward the end of the file, and stopping at the
+first line containing a string matching the RE.
+(The trailing slash can be omitted at the end of the command line.)
+.sp
+If no RE is specified, i.e. the pattern is
+.QT // ,
+the last RE used in any command is used in the search.
+.sp
+If the
+.OP extended
+option is set, the RE is handled as an extended RE, not a basic RE.
+If the
+.OP wrapscan
+option is set, the search wraps around to the beginning of the file
+and continues up to and including the current line, so that the entire
+file is searched.
+.sp
+The form
+.QT \e/
+is accepted for historic reasons,
+and is identical to
+.QT // .
+.np
+An RE enclosed in question marks
+.PQ ?
+addresses the first line found by searching backward from the line
+.i preceding
+the current line, toward the beginning of the file and stopping at the
+first line containing a string matching the RE.
+(The trailing question mark can be omitted at the end of a command line.)
+.sp
+If no RE is specified, i.e. the pattern is
+.QT ?? ,
+the last RE used in any command is used in the search.
+.sp
+If the
+.OP extended
+option is set, the RE is handled as an extended RE, not a basic RE.
+If the
+.OP wrapscan
+option is set, the search  wraps around from the beginning of the file to
+the end of the file and continues up to and including the current line,
+so that the entire file is searched.
+.sp
+The form
+.QT \e?
+is accepted for historic reasons, and is identical to
+.QT ?? .
+.np
+An address followed by a plus sign
+.PQ +
+or a minus sign
+.PQ -
+followed by a number is an offset address and refers to the address
+plus (or minus) the indicated number of lines.
+If the address is omitted, the addition or subtraction is done with
+respect to the current line.
+.np
+An address of
+.QT +
+or
+.QT \-
+followed by a number is an offset from the current line.
+For example,
+.QT \-5
+is the same as
+.QT \&.\-5 .
+.np
+An address ending with
+.QT +
+or
+.QT -
+has 1 added to or subtracted from the address, respectively.
+As a consequence of this rule and of the previous rule, the address
+.QT \-
+refers to the line preceding the current line.
+Moreover, trailing
+.QT +
+and
+.QT \-
+characters have a cumulative effect.
+For example,
+.QT ++\-++
+refers to the current line plus 3.
+.np
+A percent sign
+.PQ %
+is equivalent to the address range
+.QT 1,$ .
+.pp
+.CO Ex
+commands require zero, one, or two addresses.
+It is an error to specify an address to a command which requires zero
+addresses.
+.pp
+If the user provides more than the expected number of addresses to any
+.CO ex
+command, the first addresses specified are discarded.
+For example,
+.QT 1,2,3,5 print
+prints lines 3 through 5, because the
+.CO print
+command only takes two addresses.
+.pp
+The addresses in a range are separated from each other by a comma
+.PQ ,
+or a semicolon
+.PQ ; .
+In the latter case, the current line
+.PQ \&.
+is set to the first address, and only then is the second address calculated.
+This feature can be used to determine the starting line for forward and
+backward searches (see rules (5) and (6) above).
+The second address of any two-address sequence corresponds to a line that
+follows, in the file, the line corresponding to the first address.
+The first address must be less than or equal to the second address.
+The first address must be greater than or equal to the first line of the
+file, and the last address must be less than or equal to the last line
+of the file.
+.oh 'Vi/Ex Reference (Ex Commands)''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference (Ex Commands)'
+.so ex.cmd.roff
+.oh 'Vi/Ex Reference (Options)''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference (Options)'
+.so set.opt.roff
+.oh 'Vi/Ex Reference''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference'
+.bp
+.SH 1 Index
+.lp
+.2c +0.5i 3
+.ta \n($luR
+.nf
+.so index.so
+.fi
+.\" Force the TOC to an odd page, in case it's a duplex printer.
+.if o .bp
+.bp 3
+.1c
+.ce 1
+\fB\s+2Table of Contents\s0\fP
+.sp
+.xp
diff --git a/usr.bin/nvi/docs/USD.doc/vitut/Makefile b/usr.bin/nvi/docs/USD.doc/vitut/Makefile
new file mode 100644 (file)
index 0000000..ded95e5
--- /dev/null
@@ -0,0 +1,26 @@
+#      $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+#
+#      @(#)Makefile    8.7 (Berkeley) 8/18/96
+
+.include "../../../Makefile.inc"
+.PATH: ${DIST}/docs/vitut
+DIR=           usd/12.vi
+SRCS=          vi.in vi.chars
+MACROS=                -ms
+CLEANFILES+=   vitut.ps summary.ps viapwh.ps
+
+all: vitut.ps summary.ps viapwh.ps
+
+vitut.ps: ${SRCS}
+       ${TOOL_TBL} ${.ALLSRC} | ${TOOL_ROFF_PS} ${MACROS} > $@
+       chmod 444 $@
+
+summary.ps: vi.summary
+       ${TOOL_TBL} ${.ALLSRC} | ${TOOL_ROFF_PS} ${MACROS} > $@
+       chmod 444 $@
+
+viapwh.ps: vi.apwh.ms
+       ${TOOL_TBL} ${.ALLSRC} | ${TOOL_ROFF_PS} ${MACROS} > $@
+       chmod 444 $@
+
+.include <bsd.doc.mk>
diff --git a/usr.bin/nvi/docs/ev b/usr.bin/nvi/docs/ev
new file mode 100644 (file)
index 0000000..144295a
--- /dev/null
@@ -0,0 +1,55 @@
+#      @(#)ev  8.4 (Berkeley) 4/29/94
+
+Ev:    Vi:     Result:
+<CK>   <CK>    (Cursor keys).  Move around the file.
+
+Meta key commands:
+^A<#>  <#>G    Goto line #.
+^A$    G       Goto the end of the file.
+^A/    /       Prompt and execute a forward search.
+^A:    :       Prompt and execute an ex command.
+^A?    ?       Prompt and execute a backward search.
+^Ac    y'<c>   Copy to mark in line mode (or copy the current line).
+^AC    y`<c>   Copy to mark in character mode.
+^Ad    d'<c>   Delete to mark in line mode (or delete the current line).
+^AD    d`<c>   Delete to mark in character mode.
+^Aj    J       Join lines.
+^Am    m<c>    Mark the current cursor position.
+^AN    N       Repeat search in the reverse direction.
+^An    ^A      Search for the word under the cursor.
+^Ar    u       Redo a command.
+^Au    u       Undo a command.
+
+Single key commands:
+^B     ^B      Page up a screen.
+^C     ^C      Interrupt long-running commands.
+^D     ^D      Page down a half-screen.
+^E     $       End of line.
+^F     ^F      Page down a screen.
+^G     ^G      File status/information.
+^H     X       Delete the character to the left of the cursor.
+^I (TAB)
+^J     j       Cursor down one line.
+^K     k       Cursor up one line.
+^L     ^L      Redraw the screen.
+^M (CR)        ^M      In insert mode, split the line at the current cursor,
+               creating a new line.
+               In overwrite mode, cursor down one line.
+^N     n       Repeat previous search, in previous direction.
+^O (UNUSED)
+^P     p       Paste the cut text at the cursor position.
+^Q (XON/XOFF)
+^R (UNUSED)
+^S (XON/XOFF)
+^T     D       Truncate the line at the cursor position.
+^U     ^U      Page up a half-screen.
+^V<c>  ^V<c>   Insert/overwrite with a literal next character.
+^W     w       Move forward one whitespace separated word.
+^X     x       Delete the current character.
+^Y (UNUSED)
+^Z     ^Z      Suspend.
+
+New ex mode commands:
+
+^A:set ov[erwrite]     Toggle "insert" mode, so that input keys overwrite
+                       the existing characters.
diff --git a/usr.bin/nvi/docs/help b/usr.bin/nvi/docs/help
new file mode 100644 (file)
index 0000000..7391a1c
--- /dev/null
@@ -0,0 +1,230 @@
+MOVING THE CURSOR:
+ k - cursor up    ^F - page forward           /<pattern><CR> - search forward
+ j - cursor down  ^B - page backward          ?<pattern><CR> - search backward
+ h - cursor left   w - move forward a "word"   n - repeat the last search
+ l - cursor right  b - move backward a "word"
+
+ENTERING TEXT:
+a - append after the cursor.             Use the <escape> key to return to
+i - insert before the cursor.            command mode.
+o - open a new line below the cursor.
+O - open new line above the cursor.
+
+WRITING AND EXITING:
+:w<Enter>  - write the file
+:q<Enter>  - exit the file
+:q!<Enter> - exit without writing the file
+:#<Enter>  - move to a line (e.g., :35<Enter> moves to line 35)
+
+MISCELLANEOUS:
+^G - display the file name
+ J - join two lines (use i<Enter><escape> to split a line)
+ u - undo the last change (enter . after a 'u' to undo more than one change)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+VI COMMANDS:
+       ^A search forward for cursor word
+       ^B scroll up by screens
+       ^C interrupt an operation (e.g. read, write, search)
+       ^D scroll down by half screens (setting count)
+       ^E scroll down by lines
+       ^F scroll down by screens
+       ^G file status 
+       ^H move left by characters
+       ^J move down by lines
+       ^L redraw screen
+       ^M move down by lines (to first non-blank)
+       ^N move down by lines 
+       ^P move up by lines   
+       ^R redraw screen
+       ^T tag pop
+       ^U half page up (set count)
+       ^V input a literal character
+       ^W move to next screen
+       ^Y page up by lines
+       ^Z suspend editor
+       ^[ <escape> exit input mode, cancel partial commands
+       ^\ switch to ex mode
+       ^] tag push cursor word
+       ^^ switch to previous file
+   <space> move right by columns
+        ! filter through command(s) to motion
+        # number increment/decrement
+        $ move to last column
+        % move to match
+        & repeat substitution
+        ' move to mark (to first non-blank)
+        ( move back sentence
+        ) move forward sentence
+        + move down by lines (to first non-blank)
+        , reverse last F, f, T or t search
+        - move up by lines (to first non-blank)
+        . repeat the last command
+        / search forward
+        0 move to first character
+        : ex command
+        ; repeat last F, f, T or t search
+        < shift lines left to motion
+        > shift lines right to motion
+        ? search backward
+        @ execute buffer
+        A append to the line
+        B move back bigword
+        C change to end-of-line
+        D delete to end-of-line
+        E move to end of bigword
+        F character in line backward search
+        G move to line
+        H move to count lines from screen top
+        I insert before first nonblank
+        J join lines
+        L move to screen bottom
+        M move to screen middle
+        N reverse last search
+        O insert above line
+        P insert before cursor from buffer
+        Q switch to ex mode
+        R replace characters
+        S substitute for the line(s)
+        T before character in line backward search
+        U Restore the current line
+        W move to next bigword
+        X delete character before cursor
+        Y copy line
+       ZZ save file and exit
+       [[ move back section
+       ]] move forward section
+        ^ move to first non-blank
+        _ move to first non-blank
+        ` move to mark
+        a append after cursor
+        b move back word
+        c change to motion
+        d delete to motion
+        e move to end of word
+        f character in line forward search
+        h move left by columns
+        i insert before cursor
+        j move down by lines
+        k move up by lines
+        l move right by columns
+        m set mark
+        n repeat last search
+        o append after line
+        p insert after cursor from buffer
+        r replace character
+        s substitute character
+        t before character in line forward search
+        u undo last change
+        w move to next word
+        x delete character
+        y copy text to motion into a cut buffer
+        z reposition the screen
+        { move back paragraph
+        | move to column
+        } move forward paragraph
+        ~ reverse case
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+EX COMMANDS:
+         ^D: scroll lines
+          !: filter lines through commands or run commands
+          #: display numbered lines
+          &: repeat the last subsitution
+          *: execute a buffer
+          <: shift lines left
+          =: display line number
+          >: shift lines right  
+          @: execute a buffer   
+      append: append input to a line
+  abbreviate: specify an input abbreviation
+       args: display file argument list
+         bg: background the current screen
+      change: change lines to input
+         cd: change the current directory
+       chdir: change the current directory
+       copy: copy lines elsewhere in the file
+      cscope: create a set of tags using a cscope command
+      delete: delete lines from the file
+     display: display buffers, screens or tags
+     [Ee]dit: begin editing another file
+       [Ee]x: begin editing another file
+     exusage: display ex command usage statement
+       file: display (and optionally set) file name
+         fg: switch the current screen and a backgrounded screen
+      global: execute a global command on lines matching an RE
+       help: display help statement
+      insert: insert input before a line
+       join: join lines into a single line
+          k: mark a line position
+       list: display lines in an unambiguous form
+       move: move lines elsewhere in the file
+       mark: mark a line position
+        map: map input or commands to one or more keys
+      mkexrc: write a .exrc file
+     [Nn]ext: edit (and optionally specify) the next file
+      number: change display to number lines
+       open: enter "open" mode (not implemented)
+       print: display lines
+       perl: run the perl interpreter with the command
+      perldo: run the perl interpreter with the command, on each line
+    preserve: preserve an edit session for recovery
+ [Pp]revious: edit the previous file in the file argument list
+        put: append a cut buffer to the line
+       quit: exit ex/vi
+       read: append input from a command or file to the line
+     recover: recover a saved file
+      resize: grow or shrink the current screen
+      rewind: re-edit all the files in the file argument list
+          s: substitute on lines matching an RE
+      script: run a shell in a screen
+        set: set options (use ":set all" to see all options)
+       shell: suspend editing and run a shell
+      source: read a file of ex commands
+       stop: suspend the edit session
+     suspend: suspend the edit session
+          t: copy lines elsewhere in the file
+      [Tt]ag: edit the file containing the tag
+     tagnext: move to the next tag
+      tagpop: return to the previous group of tags
+     tagprev: move to the previous tag
+      tagtop: discard all tags
+        tcl: run the tcl interpreter with the command
+       undo: undo the most recent change
+unabbreviate: delete an abbreviation
+       unmap: delete an input or command map
+          v: execute a global command on lines NOT matching an RE
+     version: display the program version information
+      visual: enter visual (vi) mode from ex mode
+   [Vv]isual: edit another file (from vi mode only)
+     viusage: display vi key usage statement
+       write: write the file
+         wn: write the file and switch to the next file
+         wq: write the file and exit
+        xit: exit
+       yank: copy lines to a cut buffer
+          z: display different screens of the file
+          ~: replace previous RE with previous replacement string,
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Edit options:
+noaltwerase     filec=""        nomodeline      scroll=17       notildeop
+autoindent      flash           msgcat="./"     nosearchincr    timeout  
+autoprint       hardtabs=0      noprint=""      nosecure        nottywerase
+noautowrite     noiclower       nonumber        shiftwidth=8    noverbose  
+backup=""       noignorecase    nooctal         noshowmatch     warn
+nobeautify      keytime=6       open            noshowmode      window=35
+cedit=""        noleftright     optimize        sidescroll=16   nowindowname
+columns=80      lines=36        print=""        noslowopen      wraplen=0
+comment         nolisp          prompt          nosourceany     wrapmargin=0
+noedcompatible  nolist          readonly        tabstop=8       wrapscan
+escapetime=1    lock            noredraw        taglength=0     nowriteany
+noerrorbells    magic           remap           tags="tags"
+exrc            matchtime=7     report=5        term="xterm"
+noextended      mesg            ruler           noterse
+cdpath="/usr/src/local/nvi:/tmp"
+directory="/tmp"
+matchchars="[]{}()<>"
+paragraphs="IPLPPPQPP LIpplpipbp"
+recdir="/var/tmp/vi.recover"
+sections="NHSHH HUnhsh"
+shell="/bin/csh"
+shellmeta="~{[*?$`'"\"
diff --git a/usr.bin/nvi/docs/info/Makefile b/usr.bin/nvi/docs/info/Makefile
new file mode 100644 (file)
index 0000000..007c8db
--- /dev/null
@@ -0,0 +1,12 @@
+#      $NetBSD: Makefile,v 1.2 2008/12/09 23:49:42 lukem Exp $
+
+.include "${.CURDIR}/../../Makefile.inc"
+
+.PATH: ${DIST}/docs/vi.ref
+
+TEXINFO=       vi.texi
+INFOFLAGS=     -I${DIST}/doc
+
+vi.info: ref.texi vi.cmd.texi ex.cmd.texi set.opt.texi
+
+.include <bsd.info.mk>
diff --git a/usr.bin/nvi/docs/internals/autowrite b/usr.bin/nvi/docs/internals/autowrite
new file mode 100644 (file)
index 0000000..dbad6c8
--- /dev/null
@@ -0,0 +1,88 @@
+#      @(#)autowrite   8.3 (Berkeley) 2/17/95
+
+Vi autowrite behavior, the fields with *'s are "don't cares".
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Commands that are affected only by autowrite:
+
+Command        File            Autowrite?      Action:
+       modified?
+-----------------------------------------------
+^Z     Y               Y               Write file and suspend.
+^Z     Y               N               Suspend.
+^Z     N               *               Suspend.
+
+# This behavior is NOT identical to :edit.
+^^     Y               Y               Write file and jump.
+^^     Y               N               Error.
+^^     N               *               Jump.
+
+# The new nvi command ^T (:tagpop) behaves identically to ^].
+# This behavior is identical to :tag, :tagpop, and :tagpush with
+# force always set to N.
+^]     Y               Y               Write file and jump.
+^]     Y               N               Error.
+^]     N               *               Jump.
+
+# There's no way to specify a force flag to the '!' command.
+:!     Y               Y               Write file and execute.
+:!     Y               N               Warn (if warn option) and execute.
+:!     N               *               Execute.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Commands that are affected by both autowrite and force:
+
+NOTE: the "force" flag is never passed on, i.e. the write
+to the file caused by the autowrite flag is never forced.
+
+Command        File            Autowrite?      Force?  Action:
+       modified?                       (!)
+-------------------------------------------------------
+# The first rule (YYY) is historic practice, but seems wrong.
+# In nvi, :next and :prev commands behave identically to :rewind.
+:next  Y               Y               Y       Write changes and jump.
+:next  Y               Y               N       Write changes and jump.
+:next  Y               N               Y       Abandon changes and jump.
+:next  Y               N               N       Error.
+:next  N               *               *       Jump.
+
+:rewind        Y               Y               Y       Abandon changes and jump.
+:rewind        Y               Y               N       Write changes and jump.
+:rewind        Y               N               Y       Abandon changes and jump.
+:rewind        Y               N               N       Error.
+:rewind        N               *               *       Jump.
+
+# The new nvi commands, :tagpop and :tagtop, behave identically to :tag.
+# Note, this behavior is the same as :rewind and friends, as well.
+:tag   Y               Y               Y       Abandon changes and jump.
+:tag   Y               Y               N       Write changes and jump.
+:tag   Y               N               Y       Abandon changes and jump.
+:tag   Y               N               N       Error.
+:tag   N               *               *       Jump.
+
+# The command :suspend behaves identically to :stop.
+:stop  Y               Y               Y       Suspend.
+:stop  Y               Y               N       Write changes and suspend.
+:stop  Y               N               Y       Suspend.
+:stop  Y               N               N       Suspend.
+:stop  N               *               *       Suspend.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Commands that might be affected by autowrite, but aren't:
+
+Command        File            Autowrite?      Force?  Action:
+       modified?                       (!)
+-------------------------------------------------------
+#:ex, and :vi (executed while in vi mode) behave identically to :edit.
+:edit  Y               *               Y       Abandon changes and jump.
+:edit  Y               *               N       Error.
+:edit  N               *               *       Jump.
+
+:quit  Y               *               Y       Quit.
+:quit  Y               *               N       Error.
+:quit  N               *               *       Quit.
+
+:shell *               *               *       Execute shell.
+
+:xit   Y               *               *       Write changes and exit.
+:xit   N               *               *       Exit.
diff --git a/usr.bin/nvi/docs/internals/context b/usr.bin/nvi/docs/internals/context
new file mode 100644 (file)
index 0000000..8b1db32
--- /dev/null
@@ -0,0 +1,32 @@
+#      @(#)context     8.6 (Berkeley) 10/14/94
+
+In historic vi, the previous context mark was always set:
+
+ex address:
+    any number, <question-mark>, <slash>, <dollar-sign>,
+    <single-quote>, <backslash>
+
+ex commands: undo, "z.", global, v
+
+vi commands: (, ), {, }, %, [[, ]], ^]
+
+nvi adds the vi command ^T to this list.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+In historic vi, the previous context mark was set if the
+line changed:
+
+vi commands: '<mark>, G, H, L, M, z
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+In historic vi, the previous context mark was set if the
+line or column changed:
+
+vi commands: `<mark>, /, ?, N, n
+
+nvi adds the vi command ^A to this list.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+In historic vi, the previous context mark was set in non-visual
+mode for ^R and ^L if the line changed, but I have yet to figure
+out how the line could change.
diff --git a/usr.bin/nvi/docs/internals/gdb.script b/usr.bin/nvi/docs/internals/gdb.script
new file mode 100644 (file)
index 0000000..a112234
--- /dev/null
@@ -0,0 +1,76 @@
+#      @(#)gdb.script  8.5 (Berkeley) 5/4/96
+
+# display the VI screen map
+# usage dmap(sp)
+define dmap
+       set $h = ((VI_PRIVATE *)$arg0->vi_private)->h_smap
+       set $t = ((VI_PRIVATE *)$arg0->vi_private)->t_smap
+       while ($h <= $t)
+               printf "lno: %2d; soff %d coff %d ", \
+                   (int)$h->lno, (int)$h->soff, (int)$h->coff
+               if ($h->c_ecsize == 0)
+                       printf "flushed\n"
+               else
+                       printf "\n\tsboff %d; scoff %d\n", \
+                           (int)$h->c_sboff, (int)$h->c_scoff
+                       printf "\teboff %d; eclen %d; ecsize %d\n", \
+                           (int)$h->c_eboff, (int)$h->c_eclen, \
+                           (int)$h->c_ecsize
+               end
+               set $h = $h + 1
+       end
+end
+
+# display the tail of the VI screen map
+define tmap
+       set $h = ((VI_PRIVATE *)$arg0->vi_private)->h_smap
+       set $t = ((VI_PRIVATE *)$arg0->vi_private)->t_smap
+       while ($t >= $h)
+               printf "lno: %2d; soff %d coff %d ", \
+                   (int)$t->lno, (int)$t->soff, (int)$t->coff
+               if ($t->c_ecsize == 0)
+                       printf "flushed\n"
+               else
+                       printf "\n\tsboff %d; scoff %d\n", \
+                           (int)$t->c_sboff, (int)$t->c_scoff
+                       printf "\teboff %d; eclen %d; ecsize %d\n", \
+                           (int)$t->c_eboff, (int)$t->c_eclen, \
+                           (int)$t->c_ecsize
+               end
+               set $t = $t - 1
+       end
+end
+
+# display the private structures
+define clp
+       print *((CL_PRIVATE *)sp->gp->cl_private)
+end
+define vip
+       print *((VI_PRIVATE *)sp->vi_private)
+end
+define exp
+       print *((EX_PRIVATE *)sp->ex_private)
+end
+
+# display the marks
+define markp
+       set $h = sp->ep->marks.next
+       set $t = &sp->ep->marks
+       while ($h != 0 && $h != $t)
+               printf "key %c lno: %d cno: %d flags: %x\n", \
+                   ((MARK *)$h)->name, ((MARK *)$h)->lno, \
+                   ((MARK *)$h)->cno, ((MARK *)$h)->flags
+               set $h = ((MARK *)$h)->next
+       end
+end
+
+# display the tags
+define tagp
+       set $h = sp->taghdr.next
+       set $t = &sp->taghdr
+       while ($h != 0 && $h != $t)
+               printf "tag: %s lno %d cno %d\n", ((TAG *)$h)->frp->fname, \
+                   ((TAG *)$h)->lno, ((TAG *)$h)->cno
+               set $h= ((TAG *)$h)->next
+       end
+end
diff --git a/usr.bin/nvi/docs/internals/input b/usr.bin/nvi/docs/internals/input
new file mode 100644 (file)
index 0000000..9a7506e
--- /dev/null
@@ -0,0 +1,350 @@
+#      @(#)input       5.5 (Berkeley) 7/2/94
+
+MAPS, EXECUTABLE BUFFERS AND INPUT IN EX/VI:
+
+The basic rule is that input in ex/vi is a stack.  Every time a key which
+gets expanded is encountered, it is expanded and the expansion is treated
+as if it were input from the user.  So, maps and executable buffers are
+simply pushed onto the stack from which keys are returned.  The exception
+is that if the "remap" option is turned off, only a single map expansion
+is done.  I intend to be fully backward compatible with this.
+
+Historically, if the mode of the editor changed (ex to vi or vice versa),
+any queued input was silently discarded.  I don't see any reason to either
+support or not support this semantic.  I intend to retain the queued input,
+mostly because it's simpler than throwing it away.
+
+Historically, neither the initial command on the command line (the + flag)
+or the +cmd associated with the ex and edit commands was subject to mapping.
+Also, while the +cmd appears to be subject to "@buffer" expansion, once
+expanded it doesn't appear to work correctly.  I don't see any reason to
+either support or not support these semantics, so, for consistency, I intend
+to pass both the initial command and the command associated with ex and edit
+commands through the standard mapping and @ buffer expansion.
+
+One other difference between the historic ex/vi and nex/nvi is that nex
+displays the executed buffers as it executes them.  This means that if
+the file is:
+
+       set term=xterm
+       set term=yterm
+       set term=yterm
+
+the user will see the following during a typical edit session:
+
+       nex testfile
+       testfile: unmodified: line 3
+       :1,$yank a
+       :@a
+       :set term=zterm
+       :set term=yterm
+       :set term=xterm
+       :q!
+
+This seems like a feature and unlikely to break anything, so I don't
+intend to match historic practice in this area.
+
+The rest of this document is a set of conclusions as to how I believe
+the historic maps and @ buffers work.  The summary is as follows:
+
+1: For buffers that are cut in "line mode", or buffers that are not cut
+   in line mode but which contain portions of more than a single line, a
+   trailing <newline> character appears in the input for each line in the
+   buffer when it is executed.  For buffers not cut in line mode and which
+   contain portions of only a single line, no additional characters
+   appear in the input.
+2: Executable buffers that execute other buffers don't load their
+   contents until they execute them.
+3: Maps and executable buffers are copied when they are executed --
+   they can be modified by the command but that does not change their
+   actions.
+4: Historically, executable buffers are discarded if the editor
+   switches between ex and vi modes.
+5: Executable buffers inside of map commands are expanded normally.
+   Maps inside of executable buffers are expanded normally.
+6: If an error is encountered while executing a mapped command or buffer,
+   the rest of the mapped command/buffer is discarded.  No user input
+   characters are discarded.
+7: Characters in executable buffers are remapped.
+8: Characters in executable buffers are not quoted.
+
+Individual test cases follow.  Note, in the test cases, control characters
+are not literal and will have to be replaced to make the test cases work.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+1: For buffers that are cut in "line mode", or buffers that are not cut
+   in line mode but which contain portions of more than a single line, a
+   trailing <newline> character appears in the input for each line in the
+   buffer when it is executed.  For buffers not cut in line mode and which
+   contain portions of only a single line, no additional characters
+   appear in the input.
+
+===   test file   ===
+3Gw
+w
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+=== end test file ===
+
+   If the first line is loaded into 'a' and executed:
+
+1G"ayy@a
+
+   The cursor ends up on the '2', a result of pushing "3Gw^J" onto
+   the stack.
+
+   If the first two lines are loaded into 'a' and executed:
+
+1G2"ayy@a
+
+   The cursor ends up on the 'f' in "foo" in the fifth line of the
+   file, a result of pushing "3Gw^Jw^J" onto the stack.
+
+   If the first line is loaded into 'a', but not using line mode,
+   and executed:
+
+1G"ay$@a
+
+   The cursor ends up on the '1', a result of pushing "3Gw" onto
+   the stack
+
+   If the first two lines are loaded into 'a', but not using line mode,
+   and executed:
+
+1G2"ay$@a
+
+   The cursor ends up on the 'f' in "foo" in the fifth line of the
+   file, a result of pushing "3Gw^Jw^J" onto the stack.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+2: Executable buffers that execute other buffers don't load their
+   contents until they execute them.
+
+===   test file   ===
+cwLOAD B^[
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+@a@b
+"byy
+=== end test file ===
+
+   The command is loaded into 'e', and then executed.  'e' executes
+   'a', which loads 'b', then 'e' executes 'b'.
+
+5G"eyy6G"ayy1G@e
+
+   The output should be:
+
+===   output file   ===
+cwLOAD B^[
+LOAD B 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+@a@b
+"byy
+=== end output file ===
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+3: Maps and executable buffers are copied when they are executed --
+   they can be modified by the command but that does not change their
+   actions.
+
+   Executable buffers:
+
+===   test file   ===
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+@a@b
+"eyy
+cwEXECUTE B^[
+=== end test file ===
+
+4G"eyy5G"ayy6G"byy1G@eG"ep
+
+   The command is loaded into 'e', and then executed.  'e' executes
+   'a', which loads 'e', then 'e' executes 'b' anyway.
+
+   The output should be:
+
+===   output file   ===
+line 1 foo bar baz
+EXECUTE B 2 foo bar baz
+line 3 foo bar baz
+@a@b
+"eyy
+cwEXECUTE B^[
+line 1 foo bar baz
+=== end output file ===
+
+   Maps:
+
+===   test file   ===
+Cine 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+=== end test file ===
+
+   Entering the command ':map = :map = rB^V^MrA^M1G==' shows that
+   the first time the '=' is entered the '=' map is set and the
+   character is changed to 'A', the second time the character is
+   changed to 'B'.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+4: Historically, executable buffers are discarded if the editor
+   switches between ex and vi modes.
+
+===   test file   ===
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+cwCHANGE^[Q:set
+set|visual|1Gwww
+=== end test file ===
+
+vi testfile
+4G"ayy@a
+
+ex testfile
+$p
+yank a
+@a
+
+   In vi, the command is loaded into 'a' and then executed.  The command
+   subsequent to the 'Q' is (historically, silently) discarded.
+
+   In ex, the command is loaded into 'a' and then executed.  The command
+   subsequent to the 'visual' is (historically, silently) discarded.  The
+   first set command is output by ex, although refreshing the screen usually
+   causes it not to be seen.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+5: Executable buffers inside of map commands are expanded normally.
+   Maps inside of executable buffers are expanded normally.
+
+   Buffers inside of map commands:
+
+===   test file   ===
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+cwREPLACE BY A^[
+=== end test file ===
+
+4G"ay$:map x @a
+1Gx
+
+   The output should be:
+
+===   output file   ===
+REPLACE BY A 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+cwREPLACE BY A^[
+=== end output file ===
+
+   Maps commands inside of executable buffers:
+
+===   test file   ===
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+X
+=== end test file ===
+
+:map X cwREPLACE BY XMAP^[
+4G"ay$1G@a
+
+   The output should be:
+
+===   output file   ===
+REPLACE BY XMAP 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+X
+=== end output file ===
+
+   Here's a test that does both, repeatedly.
+
+===   test file   ===
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+X
+Y
+cwREPLACED BY C^[
+blank line
+=== end test file ===
+
+:map x @a
+4G"ay$
+:map X @b
+5G"by$
+:map Y @c
+6G"cy$
+1Gx
+
+   The output should be:
+
+===   output file   ===
+REPLACED BY C 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+X
+Y
+cwREPLACED BY C^[
+blank line
+=== end output file ===
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+6: If an error is encountered while executing a mapped command or
+   a buffer, the rest of the mapped command/buffer is discarded.  No
+   user input characters are discarded.
+
+===   test file   ===
+line 1 foo bar baz
+line 2 foo bar baz
+line 3 foo bar baz
+:map = 10GcwREPLACMENT^V^[^[
+=== end test file ===
+
+   The above mapping fails, however, if the 10G is changed to 1, 2,
+   or 3G, it will succeed.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+7: Characters in executable buffers are remapped.
+
+===   test file   ===
+abcdefghijklmnnop
+ggg
+=== end test file ===
+
+:map g x
+2G"ay$1G@a
+
+   The output should be:
+
+===   output file   ===
+defghijklmnnop
+ggg
+=== end output file ===
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+8: Characters in executable buffers are not quoted.
+
+===   test file   ===
+iFOO^[
+
+=== end test file ===
+
+1G"ay$2G@a
+
+   The output should be:
+
+===   output file   ===
+iFOO^[
+FOO
+=== end output file ===
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
diff --git a/usr.bin/nvi/docs/internals/openmode b/usr.bin/nvi/docs/internals/openmode
new file mode 100644 (file)
index 0000000..c64b767
--- /dev/null
@@ -0,0 +1,36 @@
+       @(#)openmode    8.1 (Berkeley) 10/29/94
+
+Open mode has the following special behaviors:
+
+z, ^F, ^B:
+       If count is not specified, it shall default to the window
+       edit option - 2.
+
+       Write lines from the edit buffer starting at:
+
+               (the current line) - ((count - 2) / 2)
+
+       until:
+
+               (((count + 1) / 2) * 2) - 1
+       
+       lines, or the last line in the edit buffer has been written.  A
+       line consisting of the smaller of the number of columns in the
+       display divided by two or 40 ``-'' characters shall be written
+       immediately before and after the specified is written.  These two
+       lines shall count against the total number of lines to be written.
+       A blank line shall be written after the last line is written.
+
+       z, ^F and ^B all behave identically.
+
+^D:    Display the next scroll value lines, change the current line.
+
+^U:    Change the current line, do nothing else.
+
+^E, ^Y:        Do nothing.
+
+^L:    Clear the screen and redisplay the current line.
+
+H, L, M:
+       Move to the first nonblank of the current line and do nothing
+       else.
diff --git a/usr.bin/nvi/docs/internals/quoting b/usr.bin/nvi/docs/internals/quoting
new file mode 100644 (file)
index 0000000..a5fb892
--- /dev/null
@@ -0,0 +1,208 @@
+#      @(#)quoting     5.5 (Berkeley) 11/12/94
+
+QUOTING IN EX/VI:
+
+There are four escape characters in historic ex/vi:
+
+       \ (backslashes)
+       ^V
+       ^Q (assuming it wasn't used for IXON/IXOFF)
+       The terminal literal next character.
+
+Vi did not use the lnext character, it always used ^V (or ^Q).
+^V and ^Q were equivalent in all cases for vi.
+
+There are four different areas in ex/vi where escaping characters
+is interesting:
+
+       1: In vi text input mode.
+       2: In vi command mode.
+       3: In ex command and text input modes.
+       4: In the ex commands themselves.
+
+1: Vi text input mode (a, i, o, :colon commands, etc.):
+
+   The set of characters that users might want to escape are as follows.
+   As ^L and ^Z were not special in input mode, they are not listed.
+
+       carriage return (^M)
+       escape          (^[)
+       autoindents     (^D, 0, ^, ^T)
+       erase           (^H)
+       word erase      (^W)
+       line erase      (^U)
+       newline         (^J)            (not historic practice)
+
+   Historic practice was that ^V was the only way to escape any
+   of these characters, and that whatever character followed
+   the ^V was taken literally, e.g. ^V^V is a single ^V.  I
+   don't see any strong reason to make it possible to escape
+   ^J, so I'm going to leave that alone.
+
+   One comment regarding the autoindent characters.  In historic
+   vi, if you entered "^V0^D" autoindent erasure was still
+   triggered, although it wasn't if you entered "0^V^D".  In
+   nvi, if you escape either character, autoindent erasure is
+   not triggered.
+
+   Abbreviations were not performed if the non-word character
+   that triggered the abbreviation was escaped by a ^V.  Input
+   maps were not triggered if any part of the map was escaped
+   by a ^V.
+
+   The historic vi implementation for the 'r' command requires
+   two leading ^V's to replace a character with a literal
+   character.  This is obviously a bug, and should be fixed.
+
+2: Vi command mode
+
+   Command maps were not triggered if the second or later
+   character of a map was escaped by a ^V.
+
+   The obvious extension is that ^V should keep the next command
+   character from being mapped, so you can do ":map x xxx" and
+   then enter ^Vx to delete a single character.
+
+3: Ex command and text input modes.
+
+   As ex ran in canonical mode, there was little work that it
+   needed to do for quoting.  The notable differences between
+   ex and vi are that it was possible to escape a <newline> in
+   the ex command and text input modes, and ex used the "literal
+   next" character, not control-V/control-Q.
+
+4: The ex commands:
+
+   Ex commands are delimited by '|' or newline characters.
+   Within the commands, whitespace characters delimit the
+   arguments.  Backslash will generally escape any following
+   character.  In the abbreviate, unabbreviate, map and unmap
+   commands, control-V escapes the next character, instead.
+
+   This is historic behavior in vi, although there are special
+   cases where it's impossible to escape a character, generally
+   a whitespace character.
+
+   Escaping characters in file names in ex commands:
+
+       :cd [directory]                         (directory)
+       :chdir [directory]                      (directory)
+       :edit [+cmd] [file]                     (file)
+       :ex [+cmd] [file]                       (file)
+       :file [file]                            (file)
+       :next [file ...]                        (file ...)
+       :read [!cmd | file]                     (file)
+       :source [file]                          (file)
+       :write [!cmd | file]                    (file)
+       :wq [file]                              (file)
+       :xit [file]                             (file)
+
+   Since file names are also subject to word expansion, the
+   underlying shell had better be doing the correct backslash
+   escaping.  This is NOT historic behavior in vi, making it
+   impossible to insert a whitespace, newline or carriage return
+   character into a file name.
+
+4: Escaping characters in non-file arguments in ex commands:
+
+       :abbreviate word string                 (word, string)
+*      :edit [+cmd] [file]                     (+cmd)
+*      :ex [+cmd] [file]                       (+cmd)
+       :map word string                        (word, string)
+*      :set [option ...]                       (option)
+*      :tag string                             (string)
+       :unabbreviate word                      (word)
+       :unmap word                             (word)
+
+   These commands use whitespace to delimit their arguments, and use
+   ^V to escape those characters.  The exceptions are starred in the
+   above list, and are discussed below.
+
+   In general, I intend to treat a ^V in any argument, followed by
+   any character, as that literal character.  This will permit
+   editing of files name "foo|", for example, by using the string
+   "foo\^V|", where the literal next character protects the pipe
+   from the ex command parser and the backslash protects it from the
+   shell expansion.
+
+   This is backward compatible with historical vi, although there
+   were a number of special cases where vi wasn't consistent.
+
+4.1: The edit/ex commands:
+
+   The edit/ex commands are a special case because | symbols may
+   occur in the "+cmd" field, for example:
+
+       :edit +10|s/abc/ABC/ file.c
+
+   In addition, the edit and ex commands have historically
+   ignored literal next characters in the +cmd string, so that
+   the following command won't work.
+
+       :edit +10|s/X/^V / file.c
+
+   I intend to handle the literal next character in edit/ex consistently
+   with how it is handled in other commands.
+
+   More fun facts to know and tell:
+       The acid test for the ex/edit commands:
+
+               date > file1; date > file2
+               vi
+               :edit +1|s/./XXX/|w file1| e file2|1 | s/./XXX/|wq
+
+       No version of vi, of which I'm aware, handles it.
+
+4.2: The set command:
+
+   The set command treats ^V's as literal characters, so the
+   following command won't work.  Backslashes do work in this
+   case, though, so the second version of the command does work.
+
+       set tags=tags_file1^V tags_file2
+       set tags=tags_file1\ tags_file2
+
+   I intend to continue permitting backslashes in set commands,
+   but to also permit literal next characters to work as well.
+   This is backward compatible, but will also make set
+   consistent with the other commands.  I think it's unlikely
+   to break any historic .exrc's, given that there are probably
+   very few files with ^V's in their name.
+
+4.3: The tag command:
+
+   The tag command ignores ^V's and backslashes; there's no way to
+   get a space into a tag name.
+
+   I think this is a don't care, and I don't intend to fix it.
+
+5: Regular expressions:
+
+       :global /pattern/ command
+       :substitute /pattern/replace/
+       :vglobal /pattern/ command
+
+   I intend to treat a backslash in the pattern, followed by the
+   delimiter character or a backslash, as that literal character.
+
+   This is historic behavior in vi.  It would get rid of a fairly
+   hard-to-explain special case if we could just use the character
+   immediately following the backslash in all cases, or, if we
+   changed nvi to permit using the literal next character as a
+   pattern escape character, but that would probably break historic
+   scripts.
+
+   There is an additional escaping issue for regular expressions.
+   Within the pattern and replacement, the '|' character did not
+   delimit ex commands.  For example, the following is legal.
+
+       :substitute /|/PIPE/|s/P/XXX/
+
+   This is a special case that I will support.
+
+6: Ending anything with an escape character:
+
+   In all of the above rules, an escape character (either ^V or a
+   backslash) at the end of an argument or file name is not handled
+   specially, but used as a literal character.
+
diff --git a/usr.bin/nvi/docs/internals/structures b/usr.bin/nvi/docs/internals/structures
new file mode 100644 (file)
index 0000000..a25c780
--- /dev/null
@@ -0,0 +1,68 @@
+#      @(#)structures  5.4 (Berkeley) 10/4/95
+
+There are three major data structures in this package, plus a single data
+structure per screen type.  The first is a single global structure (GS)
+which contains information common to all files and screens.  It hold
+global things like the input key queues, and functions as a single place
+to hang things.  For example, interrupt routines have to be able to find
+screen structures, and they can only do this if they have a starting
+point.  The number of globals in nvi is dependent on the screen type, but
+every screen type will have at least one global, __global_list, which
+references the GS structure.
+
+The GS structure contains linked lists of screen (SCR) structures.
+Each SCR structure normally references a file (EXF) structure.
+
+The GS structure has a set of functions which update the screen and/or
+return information about the screen from the underlying screen package.
+The GS structure never goes away.  The SCR structure persists over
+instances of screens, and the EXF structure persists over references to
+files.
+
+File names have different properties than files themselves, so the name
+information for a file is held in an FREF structure which is chained from
+the SCR structure.
+
+In general, functions are always passed an SCR structure, which usually
+references an underlying EXF structure.  The SCR structure is necessary
+for any routine that wishes to talk to the screen, the EXF structure is
+necessary for any routine that wants to modify the file.  The relationship
+between an SCR structure and its underlying EXF structure is not fixed,
+and various ex commands will substitute a new EXF in place of the current
+one, and there's no way to detect this.
+
+The naming of the structures is consistent across the program.  (Macros
+even depend on it, so don't try and change it!)  The global structure is
+"gp", the screen structure is "sp", and the file structure is "ep".
+
+A few other data structures:
+
+TEXT   In nvi/cut.h.  This structure describes a portion of a line,
+       and is used by the input routines and as the "line" part of a
+       cut buffer.
+
+CB     In nvi/cut.h.   A cut buffer.  A cut buffer is a place to
+       hang a list of TEXT structures.
+
+CL     The curses screen private data structure.  Everything to
+       do standalone curses screens.
+
+MARK   In nvi/mark.h.  A cursor position, consisting of a line number
+       and a column number.
+
+MSG    In nvi/msg.h.  A chain of messages for the user.
+
+SEQ    In nvi/seq.h.  An abbreviation or a map entry.
+
+TK     The Tcl/Tk screen private data structure.  Everything to
+       do standalone Tcl/Tk screens.
+
+EXCMD   In nvi/ex/ex.h.  The structure that gets passed around to the
+       functions that implement the ex commands.  (The main ex command
+       loop (see nvi/ex/ex.c) builds this up and then passes it to the
+       ex functions.)
+
+VICMD  In nvi/vi/vi.h.  The structure that gets passed around to the
+       functions that implement the vi commands.  (The main vi command
+       loop (see nvi/vi/vi.c) builds this up and then passes it to the
+       vi functions.)
diff --git a/usr.bin/nvi/recover/Makefile b/usr.bin/nvi/recover/Makefile
new file mode 100644 (file)
index 0000000..bdc8b5f
--- /dev/null
@@ -0,0 +1,7 @@
+#      $NetBSD: Makefile,v 1.1 2008/09/02 09:25:39 christos Exp $
+
+SCRIPTS =      virecover
+SCRIPTSDIR =   /usr/libexec
+MAN=           virecover.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nvi/recover/virecover b/usr.bin/nvi/recover/virecover
new file mode 100644 (file)
index 0000000..bd1c985
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh -
+#
+#      $NetBSD: virecover,v 1.1 2008/09/02 09:25:39 christos Exp $
+#
+#      @(#)recover.in  8.8 (Berkeley) 10/10/96
+#
+# Script to recover nvi edit sessions.
+
+RECDIR="/var/tmp/vi.recover"
+SENDMAIL="/usr/sbin/sendmail"
+
+# Check editor backup files.
+vibackup=`echo $RECDIR/vi.*`
+if [ "$vibackup" != "$RECDIR/vi.*" ]; then
+       for i in $vibackup; do
+               # Only test files that are readable.
+               if test ! -f $i || test ! -r $i; then
+                       continue
+               fi
+
+               # Unmodified nvi editor backup files either have the
+               # execute bit set or are zero length.  Delete them.
+               if test -x $i -o ! -s $i; then
+                       rm $i
+               fi
+       done
+fi
+
+# It is possible to get incomplete recovery files, if the editor crashes
+# at the right time.
+virecovery=`echo $RECDIR/recover.*`
+if [ "$virecovery" != "$RECDIR/recover.*" ]; then
+       for i in $virecovery; do
+               # Only test files that are readable.
+               if test ! -r $i; then
+                       continue
+               fi
+
+               # Delete any recovery files that are zero length, corrupted,
+               # or that have no corresponding backup file.  Else send mail
+               # to the user.
+               recfile=`awk '/^X-vi-recover-path:/{print $2}' < $i`
+               if test -n "$recfile" -a -s "$recfile"; then
+                       $SENDMAIL -t < $i
+               else
+                       rm $i
+               fi
+       done
+fi
diff --git a/usr.bin/nvi/recover/virecover.8 b/usr.bin/nvi/recover/virecover.8
new file mode 100644 (file)
index 0000000..dafc3d1
--- /dev/null
@@ -0,0 +1,90 @@
+.\" $NetBSD: virecover.8,v 1.1 2008/09/02 09:25:39 christos Exp $
+.\"
+.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Jeremy C. Reed.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd October 9, 2006
+.Dt VIRECOVER 8
+.Os
+.Sh NAME
+.Nm virecover
+.Nd report recovered vi edit sessions
+.Sh SYNOPSIS
+.Pa /usr/libexec/virecover
+.Sh DESCRIPTION
+The
+.Nm
+utility sends emails to users who have
+.Xr vi 1
+recovery files.
+.Pp
+This email gives the name of the file that was
+saved for recovery and instructions for recovering
+most, if not all, of the changes to the file.
+This is done by using the
+.Fl r
+option with
+.Xr vi 1 .
+See the
+.Fl r
+option in
+.Xr vi 1
+for details.
+.Pp
+If the backup files have the execute bit set or are zero length,
+then they have not been modified, so
+.Nm
+deletes them to clean up.
+.Nm
+also removes recovery files that are corrupted, zero length,
+or do not have a corresponding backup file.
+.Pp
+.Nm
+is normally run automatically at boot time using
+.Pa /etc/rc.d/virecover .
+.Sh FILES
+.Bl -tag -width "/var/tmp/vi.recover/recover.*" -compact
+.It Pa /var/tmp/vi.recover/recover.*
+.Xr vi 1
+recovery files
+.It Pa /var/tmp/vi.recover/vi.*
+.Xr vi 1
+editor backup files
+.El
+.Sh SEE ALSO
+.Xr vi 1 ,
+.Xr rc.conf 5
+.Sh HISTORY
+This script, previously known as
+.Nm recover.script ,
+is from nvi and was added to
+.Nx
+in 1996.
+It was renamed in 2001.
+.Sh AUTHORS
+This man page was written by
+.An Jeremy C. Reed Aq reed@reedmedia.net .